diff --git a/DEPS b/DEPS
index 8425162..6ccb663 100644
--- a/DEPS
+++ b/DEPS
@@ -121,11 +121,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'd426dd0dd92d3bd99ed96bb7db9f5c7956e2692c',
+  'skia_revision': 'b7af275ebbf55b6c79cf361bcf87612b328ea50a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e569d8487b3785007945b50e2c5da89a10ca3dd0',
+  'v8_revision': 'e0899ad9ee97543e6f45961fe13435882df25b8a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -133,7 +133,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'a7429204afcd957fef29facf44acf06d05cf284e',
+  'angle_revision': '783809808ec09d2040047c252925b19f507b06c8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -141,7 +141,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'ddcbdc51f2aa9767f1f8fc9508e1cb2c14fde107',
+  'swiftshader_revision': '787f953343b0cd97e946682cc28be5d9900f2e49',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -181,7 +181,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': '36e00d45b42c2b88a7fe2ec3e0ef132edb4fc25b',
+  'catapult_revision': '2061050c4d27b3b27bc3cfc7cf20fc99644f66f7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -245,7 +245,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'd77fd5f8893a5182447d876fbeef48bac414242c',
+  'dawn_revision': 'baa3741c9fbe88e83e6d8cbbea1ca44d53e1da24',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -690,7 +690,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8bcc373a271eaea3caf50d85d6d2c4a734c06935',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2e223a915e69248a5edc320d032731e16448d6fc',
       'condition': 'checkout_linux',
   },
 
@@ -1047,7 +1047,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '64ac720366ce8e92db6528bf4c4ba310a7b1b773',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'a3eb6034c5d2949481222e93246db1b4617cc33a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1251,7 +1251,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8adced44d39b7287ab7e5d368864964fdc382311',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c8eab41c449dab4ab19b8699b3fca179a40ec371',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 3604caec..f91d5d8 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -40,7 +40,7 @@
 #include "components/services/heap_profiling/public/cpp/sampling_profiler_wrapper.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/viz/common/features.h"
-#include "content/public/browser/android/browser_media_player_manager_register.h"
+#include "content/public/browser/android/media_url_interceptor_register.h"
 #include "content/public/browser/browser_main_runner.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
diff --git a/ash/accelerators/accelerator_controller.h b/ash/accelerators/accelerator_controller.h
index 23e6819..2dab948 100644
--- a/ash/accelerators/accelerator_controller.h
+++ b/ash/accelerators/accelerator_controller.h
@@ -17,6 +17,7 @@
 #include "ash/accelerators/exit_warning_handler.h"
 #include "ash/ash_export.h"
 #include "ash/public/interfaces/accelerator_controller.mojom.h"
+#include "ash/public/interfaces/volume.mojom.h"
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc
index 95f88aa..209926a 100644
--- a/ash/assistant/assistant_interaction_controller.cc
+++ b/ash/assistant/assistant_interaction_controller.cc
@@ -635,6 +635,14 @@
       break;
   }
 
+  // Explicitly check the interaction state to ensure warmer welcome will
+  // not interrupt any ongoing active interactions. This happens, for example,
+  // when the first Assistant launch of the current user session is trigger by
+  // Assistant notification, or directly sending query without showing Ui
+  // during integration test.
+  if (model_.interaction_state() == InteractionState::kActive)
+    should_attempt_warmer_welcome_ = false;
+
   // TODO(yileili): Currently WW is only triggered when the first Assistant
   // launch of the user session does not automatically start an interaction that
   // would otherwise cause us to interrupt the user. Need further UX design to
diff --git a/ash/keyboard/ash_keyboard_controller.cc b/ash/keyboard/ash_keyboard_controller.cc
index 4a437fa..c769090b 100644
--- a/ash/keyboard/ash_keyboard_controller.cc
+++ b/ash/keyboard/ash_keyboard_controller.cc
@@ -10,10 +10,12 @@
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
+#include "base/command_line.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_ui_factory.h"
+#include "ui/keyboard/public/keyboard_switches.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
 using keyboard::mojom::KeyboardConfig;
@@ -65,6 +67,12 @@
       << "keyboard_ui_factory can be null only when window service is used.";
   keyboard_ui_factory_ = std::move(keyboard_ui_factory);
   virtual_keyboard_controller_ = std::make_unique<VirtualKeyboardController>();
+
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          keyboard::switches::kEnableVirtualKeyboard)) {
+    keyboard_controller_->SetEnableFlag(
+        KeyboardEnableFlag::kCommandLineEnabled);
+  }
 }
 
 void AshKeyboardController::DestroyVirtualKeyboard() {
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h
index 38ea5f3..f48bff02 100644
--- a/ash/media/media_notification_item.h
+++ b/ash/media/media_notification_item.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/media_session/public/mojom/media_controller.mojom.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
 
 namespace ash {
 
diff --git a/ash/public/cpp/test/test_keyboard_controller_observer.h b/ash/public/cpp/test/test_keyboard_controller_observer.h
index 203dbb6..c1c8c63a 100644
--- a/ash/public/cpp/test/test_keyboard_controller_observer.h
+++ b/ash/public/cpp/test/test_keyboard_controller_observer.h
@@ -7,6 +7,7 @@
 
 #include "ash/public/interfaces/keyboard_controller.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "ui/keyboard/public/keyboard_config.mojom.h"
 
 namespace ash {
 
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc
index e1e7e0d..6fb6528 100644
--- a/ash/shell_unittest.cc
+++ b/ash/shell_unittest.cc
@@ -555,8 +555,7 @@
 
 // Verifies keyboard is re-enabled on proper timing.
 TEST_F(ShellTest, KeyboardCreation) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      keyboard::switches::kEnableVirtualKeyboard);
+  keyboard::SetTouchKeyboardEnabled(true);
 
   ASSERT_TRUE(keyboard::IsKeyboardEnabled());
 
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc
index 7808be1..92f758d 100644
--- a/ash/system/network/network_icon.cc
+++ b/ash/system/network/network_icon.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/network/network_icon.h"
 
+#include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/network_icon_image_source.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -442,7 +443,7 @@
       badges->bottom_right = {&kNetworkBadgeRoamingIcon, icon_color};
   }
   // Only show technology badge when connected.
-  if (network->IsConnectedState())
+  if (network->IsConnectedState() && !features::IsSeparateNetworkIconsEnabled())
     badges->top_left = technology_badge_;
   if (show_vpn_badge_)
     badges->bottom_left = {&kUnifiedNetworkBadgeVpnIcon, icon_color};
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index b681131..01e2135f 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -126,8 +126,8 @@
     "net/http_network_session_0x?/quic_stream_factory",
     "net/http_network_session_0x?/socket_pool",
     "net/http_network_session_0x?/spdy_session_pool",
+    "net/http_network_session_0x?/ssl_client_session_cache",
     "net/http_network_session_0x?/stream_factory",
-    "net/ssl_session_cache",
     "net/url_request_context",
     "net/url_request_context/app_request",
     "net/url_request_context/app_request/0x?",
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 995638ad..05ce8a9 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -333,7 +333,7 @@
 # targets need to manually override it for their compiles.
 config("winver") {
   defines = [
-    "NTDDI_VERSION=0x0A000002",
+    "NTDDI_VERSION=0x0A000003",  # NTDDI_WIN10_RS2
     "_WIN32_WINNT=0x0A00",
     "WINVER=0x0A00",
   ]
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index a05841a..998fb9d 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-022626e5320778cea154352d4592cc3d1686ef89
\ No newline at end of file
+bd18abd7baddaa69cdf9a888581fcd3fa815e38c
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 933911e..8cc3500 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-4e0562dca48415b215553b5cf8032420ad66a25f
\ No newline at end of file
+a6442bbdbb932d9df04001e77c8e4ddea51bd0af
\ No newline at end of file
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index 74d2b6d..ddfa824 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -31,6 +31,8 @@
     "image_provider.h",
     "image_transfer_cache_entry.cc",
     "image_transfer_cache_entry.h",
+    "node_holder.cc",
+    "node_holder.h",
     "paint_cache.cc",
     "paint_cache.h",
     "paint_canvas.h",
@@ -79,6 +81,7 @@
     "skottie_wrapper.h",
     "solid_color_analyzer.cc",
     "solid_color_analyzer.h",
+    "text_holder.h",
     "transfer_cache_deserialize_helper.h",
     "transfer_cache_entry.cc",
     "transfer_cache_entry.h",
diff --git a/cc/paint/node_holder.cc b/cc/paint/node_holder.cc
new file mode 100644
index 0000000..c94f3de
--- /dev/null
+++ b/cc/paint/node_holder.cc
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/paint/node_holder.h"
+
+namespace cc {
+
+NodeHolder::NodeHolder() : tag(EMPTY) {}
+
+NodeHolder::NodeHolder(scoped_refptr<TextHolder> holder)
+    : tag(TEXT_HOLDER), text_holder(holder) {}
+
+NodeHolder::NodeHolder(int id) : tag(ID), id(id) {}
+
+NodeHolder::NodeHolder(const NodeHolder& other) {
+  text_holder = other.text_holder;
+  id = other.id;
+  tag = other.tag;
+}
+
+NodeHolder::~NodeHolder() = default;
+
+bool operator==(const NodeHolder& l, const NodeHolder& r) {
+  if (l.tag != r.tag)
+    return false;
+  switch (l.tag) {
+    case NodeHolder::TEXT_HOLDER:
+      return l.text_holder == r.text_holder;
+    case NodeHolder::ID:
+      return l.id == r.id;
+    case NodeHolder::EMPTY:
+      return true;
+  }
+}
+
+bool operator!=(const NodeHolder& l, const NodeHolder& r) {
+  return !(l == r);
+}
+
+}  // namespace cc
diff --git a/cc/paint/node_holder.h b/cc/paint/node_holder.h
new file mode 100644
index 0000000..eae2e58
--- /dev/null
+++ b/cc/paint/node_holder.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PAINT_NODE_HOLDER_H_
+#define CC_PAINT_NODE_HOLDER_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "cc/paint/paint_export.h"
+#include "cc/paint/text_holder.h"
+
+namespace cc {
+
+// This struct is used to hold the information of node that PaintOp associates
+// with, either the TextHolder or the Id could be set, but only one will finally
+// be supported base on the performance impact.
+struct CC_PAINT_EXPORT NodeHolder {
+  NodeHolder();
+  explicit NodeHolder(scoped_refptr<TextHolder> text_holder);
+  explicit NodeHolder(int id);
+  NodeHolder(const NodeHolder& node_holder);
+  virtual ~NodeHolder();
+
+  bool IsEmpty() const { return tag == EMPTY; }
+
+  enum { EMPTY, TEXT_HOLDER, ID } tag;
+
+  scoped_refptr<TextHolder> text_holder;
+  int id;
+};
+
+bool operator==(const NodeHolder& l, const NodeHolder& r);
+
+bool operator!=(const NodeHolder& l, const NodeHolder& r);
+
+}  // namespace cc
+
+#endif  // CC_PAINT_NODE_HOLDER_H_
diff --git a/cc/paint/paint_canvas.h b/cc/paint/paint_canvas.h
index df30609..eb6f05de 100644
--- a/cc/paint/paint_canvas.h
+++ b/cc/paint/paint_canvas.h
@@ -19,6 +19,8 @@
 class PaintFlags;
 class PaintOpBuffer;
 
+struct NodeHolder;
+
 using PaintRecord = PaintOpBuffer;
 
 // PaintCanvas is the cc/paint wrapper of SkCanvas.  It has a more restricted
@@ -156,6 +158,12 @@
                             SkScalar y,
                             const PaintFlags& flags) = 0;
 
+  virtual void drawTextBlob(sk_sp<SkTextBlob> blob,
+                            SkScalar x,
+                            SkScalar y,
+                            const PaintFlags& flags,
+                            const NodeHolder& holder) = 0;
+
   // Unlike SkCanvas::drawPicture, this only plays back the PaintRecord and does
   // not add an additional clip.  This is closer to SkPicture::playback.
   virtual void drawPicture(sk_sp<const PaintRecord> record) = 0;
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 4516fec0..a4b9744 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -1027,7 +1027,7 @@
                                      void* output,
                                      size_t output_size,
                                      const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawTextBlobOp));
+  DCHECK_GE(output_size, sizeof(DrawTextBlobOp) - sizeof(NodeHolder));
   DrawTextBlobOp* op = new (output) DrawTextBlobOp;
 
   PaintOpReader helper(input, input_size, options);
@@ -1763,6 +1763,8 @@
     return false;
   if (!AreEqualEvenIfNaN(left->y, right->y))
     return false;
+  if (left->node_holder != right->node_holder)
+    return false;
 
   SkSerialProcs default_procs;
   return left->blob->serialize(default_procs)
@@ -2193,6 +2195,17 @@
                                const PaintFlags& flags)
     : PaintOpWithFlags(kType, flags), blob(std::move(blob)), x(x), y(y) {}
 
+DrawTextBlobOp::DrawTextBlobOp(sk_sp<SkTextBlob> blob,
+                               SkScalar x,
+                               SkScalar y,
+                               const PaintFlags& flags,
+                               const NodeHolder& holder)
+    : PaintOpWithFlags(kType, flags),
+      blob(std::move(blob)),
+      x(x),
+      y(y),
+      node_holder(holder) {}
+
 DrawTextBlobOp::~DrawTextBlobOp() = default;
 
 PaintOpBuffer::CompositeIterator::CompositeIterator(
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index c2ad0c9e..d51f317 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -18,6 +18,7 @@
 #include "base/memory/aligned_memory.h"
 #include "base/optional.h"
 #include "cc/base/math_util.h"
+#include "cc/paint/node_holder.h"
 #include "cc/paint/paint_canvas.h"
 #include "cc/paint/paint_export.h"
 #include "cc/paint/paint_flags.h"
@@ -741,6 +742,11 @@
                  SkScalar x,
                  SkScalar y,
                  const PaintFlags& flags);
+  DrawTextBlobOp(sk_sp<SkTextBlob> blob,
+                 SkScalar x,
+                 SkScalar y,
+                 const PaintFlags& flags,
+                 const NodeHolder& node_holder);
   ~DrawTextBlobOp();
   static void RasterWithFlags(const DrawTextBlobOp* op,
                               const PaintFlags* flags,
@@ -753,6 +759,8 @@
   sk_sp<SkTextBlob> blob;
   SkScalar x;
   SkScalar y;
+  // This field isn't serialized.
+  NodeHolder node_holder;
 
  private:
   DrawTextBlobOp();
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
index b8854c46..a8b777f 100644
--- a/cc/paint/paint_op_reader.cc
+++ b/cc/paint/paint_op_reader.cc
@@ -33,17 +33,9 @@
          static_cast<uint8_t>(PaintShader::Type::kShaderCount);
 }
 
-// SkShader::TileMode has no defined backing type, so read/write int32_t's.
-// If read_mode is a valid tile mode, this returns true and updates mode to the
-// equivalent enum value. Otherwise false is returned and mode is not modified.
-bool ValidateAndGetSkShaderTileMode(int32_t read_mode,
-                                    SkShader::TileMode* mode) {
-  if (read_mode < 0 || read_mode >= SkShader::kTileModeCount) {
-    return false;
-  }
-
-  *mode = static_cast<SkShader::TileMode>(read_mode);
-  return true;
+bool IsValidSkShaderTileMode(SkShader::TileMode mode) {
+  // When Skia adds Decal, update this (skbug.com/7638)
+  return mode <= SkShader::kMirror_TileMode;
 }
 
 bool IsValidPaintShaderScalingBehavior(PaintShader::ScalingBehavior behavior) {
@@ -468,14 +460,10 @@
   ReadSimple(&ref.flags_);
   ReadSimple(&ref.end_radius_);
   ReadSimple(&ref.start_radius_);
-
-  int32_t tx, ty;  // See ValidateAndGetSkShaderTileMode
-  Read(&tx);
-  Read(&ty);
-  if (!ValidateAndGetSkShaderTileMode(tx, &ref.tx_) ||
-      !ValidateAndGetSkShaderTileMode(ty, &ref.ty_)) {
+  ReadSimple(&ref.tx_);
+  ReadSimple(&ref.ty_);
+  if (!IsValidSkShaderTileMode(ref.tx_) || !IsValidSkShaderTileMode(ref.ty_))
     SetInvalid();
-  }
   ReadSimple(&ref.fallback_color_);
   ReadSimple(&ref.scaling_behavior_);
   if (!IsValidPaintShaderScalingBehavior(ref.scaling_behavior_))
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index 492e0fbc..72783966 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -397,10 +397,8 @@
   WriteSimple(shader->flags_);
   WriteSimple(shader->end_radius_);
   WriteSimple(shader->start_radius_);
-  // SkShader::TileMode does not have an explicitly defined backing type, so
-  // write a consistently sized value.
-  Write(static_cast<int32_t>(shader->tx_));
-  Write(static_cast<int32_t>(shader->ty_));
+  WriteSimple(shader->tx_);
+  WriteSimple(shader->ty_);
   WriteSimple(shader->fallback_color_);
   WriteSimple(shader->scaling_behavior_);
   if (shader->local_matrix_) {
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
index 24e7819..080cd03 100644
--- a/cc/paint/record_paint_canvas.cc
+++ b/cc/paint/record_paint_canvas.cc
@@ -4,6 +4,8 @@
 
 #include "cc/paint/record_paint_canvas.h"
 
+#include <utility>
+
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/paint_image_builder.h"
 #include "cc/paint/paint_record.h"
@@ -275,6 +277,14 @@
   list_->push<DrawTextBlobOp>(std::move(blob), x, y, flags);
 }
 
+void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
+                                     SkScalar x,
+                                     SkScalar y,
+                                     const PaintFlags& flags,
+                                     const NodeHolder& holder) {
+  list_->push<DrawTextBlobOp>(std::move(blob), x, y, flags, holder);
+}
+
 void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
   // TODO(enne): If this is small, maybe flatten it?
   list_->push<DrawRecordOp>(record);
diff --git a/cc/paint/record_paint_canvas.h b/cc/paint/record_paint_canvas.h
index 183f8fe..5b1c795 100644
--- a/cc/paint/record_paint_canvas.h
+++ b/cc/paint/record_paint_canvas.h
@@ -88,6 +88,11 @@
                     SkScalar x,
                     SkScalar y,
                     const PaintFlags& flags) override;
+  void drawTextBlob(sk_sp<SkTextBlob> blob,
+                    SkScalar x,
+                    SkScalar y,
+                    const PaintFlags& flags,
+                    const NodeHolder& holder) override;
 
   void drawPicture(sk_sp<const PaintRecord> record) override;
 
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index 9109f3d..62060b8 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -316,6 +316,14 @@
   FlushAfterDrawIfNeeded();
 }
 
+void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
+                                   SkScalar x,
+                                   SkScalar y,
+                                   const PaintFlags& flags,
+                                   const NodeHolder& holder) {
+  drawTextBlob(blob, x, y, flags);
+}
+
 void SkiaPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
   drawPicture(record, PlaybackParams::CustomDataRasterCallback());
 }
diff --git a/cc/paint/skia_paint_canvas.h b/cc/paint/skia_paint_canvas.h
index e22e6f23..38abfe8 100644
--- a/cc/paint/skia_paint_canvas.h
+++ b/cc/paint/skia_paint_canvas.h
@@ -111,6 +111,11 @@
                     SkScalar x,
                     SkScalar y,
                     const PaintFlags& flags) override;
+  void drawTextBlob(sk_sp<SkTextBlob> blob,
+                    SkScalar x,
+                    SkScalar y,
+                    const PaintFlags& flags,
+                    const NodeHolder& holder) override;
 
   void drawPicture(sk_sp<const PaintRecord> record) override;
 
diff --git a/cc/paint/text_holder.h b/cc/paint/text_holder.h
new file mode 100644
index 0000000..0bda890
--- /dev/null
+++ b/cc/paint/text_holder.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PAINT_TEXT_HOLDER_H_
+#define CC_PAINT_TEXT_HOLDER_H_
+
+#include <set>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "cc/paint/paint_export.h"
+
+namespace cc {
+
+// The base class for embedder (blink) to associate DrawTextBlobOp with a text
+// node.
+// This class has to be RefCountedThreadSafe because the asscociated
+// DrawTextBlobOp could be dereferenced in main, compositor or raster worker
+// threads.
+class CC_PAINT_EXPORT TextHolder
+    : public base::RefCountedThreadSafe<TextHolder> {
+ protected:
+  friend class base::RefCountedThreadSafe<TextHolder>;
+  virtual ~TextHolder() = default;
+};
+
+}  // namespace cc
+
+#endif  // CC_PAINT_TEXT_HOLDER_H_
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 4ef934a..586bbac 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -5118,6 +5118,8 @@
 
 void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
                                          const UIResourceBitmap& bitmap) {
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+               "LayerTreeHostImpl::CreateUIResource");
   DCHECK_GT(uid, 0);
 
   // Allow for multiple creation requests with the same UIResourceId.  The
@@ -5327,6 +5329,8 @@
 }
 
 void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) {
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+               "LayerTreeHostImpl::DeleteUIResource");
   auto it = ui_resource_map_.find(uid);
   if (it != ui_resource_map_.end()) {
     UIResourceData& data = it->second;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 034dc7e295..e6ebda2 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1833,6 +1833,8 @@
 }
 
 void LayerTreeImpl::ProcessUIResourceRequestQueue() {
+  TRACE_EVENT1("cc", "ProcessUIResourceRequestQueue", "queue_size",
+               ui_resource_request_queue_.size());
   for (const auto& req : ui_resource_request_queue_) {
     switch (req.GetType()) {
       case UIResourceRequest::UI_RESOURCE_CREATE:
diff --git a/chrome/app/android/chrome_main_delegate_android.cc b/chrome/app/android/chrome_main_delegate_android.cc
index c76d611b..2f14a0b 100644
--- a/chrome/app/android/chrome_main_delegate_android.cc
+++ b/chrome/app/android/chrome_main_delegate_android.cc
@@ -17,7 +17,6 @@
 #include "components/safe_browsing/android/safe_browsing_api_handler.h"
 #include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h"
 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
-#include "content/browser/media/android/browser_media_player_manager.h"
 #include "content/public/browser/browser_main_runner.h"
 
 using safe_browsing::SafeBrowsingApiHandler;
diff --git a/chrome/app/vector_icons/incognito.icon b/chrome/app/vector_icons/incognito.icon
index f5c71093e..8c3e5c6 100644
--- a/chrome/app/vector_icons/incognito.icon
+++ b/chrome/app/vector_icons/incognito.icon
@@ -1,7 +1,7 @@
 // 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.
-
+CIRCLE, 24, 24, 24,
 MOVE_TO, 22.15f, 33.23f,
 R_CUBIC_TO, 0, 3.06f, -2.48f, 5.54f, -5.54f, 5.54f,
 R_CUBIC_TO, -3.06f, 0, -5.54f, -2.48f, -5.54f, -5.54f,
@@ -26,7 +26,6 @@
 R_CUBIC_TO, 2.04f, 0, 3.69f, -1.66f, 3.69f, -3.69f,
 R_CUBIC_TO, 0, -2.04f, -1.66f, -3.69f, -3.69f, -3.69f,
 CLOSE,
-NEW_PATH,
 MOVE_TO, 24, 33.23f,
 R_CUBIC_TO, 1.72f, 0, 3.15f, 1.18f, 3.56f, 2.77f,
 R_CUBIC_TO, 0.08f, -0.3f, 0.13f, -0.6f, 0.13f, -0.92f,
@@ -34,7 +33,6 @@
 R_CUBIC_TO, -2.04f, 0, -3.69f, 1.65f, -3.69f, 3.69f,
 R_CUBIC_TO, 0, 0.32f, 0.05f, 0.63f, 0.13f, 0.92f,
 R_CUBIC_TO, 0.41f, -1.59f, 1.84f, -2.77f, 3.56f, -2.77f,
-NEW_PATH,
 MOVE_TO, 33.29f, 20,
 R_LINE_TO, 0.06f, 0.18f,
 LINE_TO, 40.62f, 24,
@@ -52,6 +50,7 @@
 CLOSE
 
 CANVAS_DIMENSIONS, 24,
+CIRCLE, 12, 12, 12,
 MOVE_TO, 11, 17,
 R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
 R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
@@ -76,7 +75,6 @@
 R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
 R_CUBIC_TO, 0, -1.1f, -0.89f, -2, -2, -2,
 CLOSE,
-NEW_PATH,
 MOVE_TO, 12, 17,
 R_CUBIC_TO, 0.93f, 0, 1.71f, 0.64f, 1.93f, 1.5f,
 R_CUBIC_TO, 0.04f, -0.16f, 0.07f, -0.33f, 0.07f, -0.5f,
@@ -84,7 +82,6 @@
 R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
 R_CUBIC_TO, 0, 0.17f, 0.03f, 0.34f, 0.07f, 0.5f,
 R_CUBIC_TO, 0.22f, -0.86f, 1, -1.5f, 1.93f, -1.5f,
-NEW_PATH,
 MOVE_TO, 16.39f, 8,
 LINE_TO, 15, 4,
 R_LINE_TO, -3, 1,
diff --git a/chrome/app/vr_strings.grdp b/chrome/app/vr_strings.grdp
index 53a303d2..5597345 100644
--- a/chrome/app/vr_strings.grdp
+++ b/chrome/app/vr_strings.grdp
@@ -67,7 +67,7 @@
   <!-- VR browser -->
   <!-- TODO(https://crbug.com/731802): Only build these when the VR browser is supported. -->
   <message name="IDS_VR_UPDATE_KEYBOARD_PROMPT" desc="Text shown when the keyboard is not installed or needs to be updated on the user's device">
-    Install or update Daydream Keyboard to use Chrome in VR
+    To type text, update the Daydream Keyboard app
   </message>
   <message name="IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION" desc="Text on the exit prompt that shows up when the user tries to use a feature that is not supported in VR">
     This feature is not supported in VR
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 970fcd4..5511262 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2010,6 +2010,7 @@
     "//ui/accessibility",
     "//ui/base",
     "//ui/base:ui_data_pack",
+    "//ui/base/idle",
     "//ui/base/ime",
     "//ui/events:events_base",
     "//ui/gfx",
@@ -2784,6 +2785,8 @@
       "media/webrtc/desktop_media_picker_factory_impl.h",
       "media/webrtc/display_media_access_handler.cc",
       "media/webrtc/display_media_access_handler.h",
+      "media/webrtc/system_media_capture_permissions_mac.h",
+      "media/webrtc/system_media_capture_permissions_mac.mm",
       "media/webrtc/tab_desktop_media_list.cc",
       "media/webrtc/tab_desktop_media_list.h",
       "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc",
@@ -3351,6 +3354,8 @@
       "notifications/win/notification_image_retainer.h",
       "notifications/win/notification_template_builder.cc",
       "notifications/win/notification_template_builder.h",
+      "taskbar/taskbar_decorator_win.cc",
+      "taskbar/taskbar_decorator_win.h",
     ]
     public_deps += [
       "//ui/views",
@@ -3465,6 +3470,7 @@
     libs += [
       "Accelerate.framework",
       "AudioUnit.framework",
+      "AVFoundation.framework",
       "DiskArbitration.framework",
       "IOKit.framework",
       "ImageCaptureCore.framework",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 77088a0..610017f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1517,6 +1517,9 @@
      flag_descriptions::kUseMessagesGoogleComDomainName,
      flag_descriptions::kUseMessagesGoogleComDomainDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kUseMessagesGoogleComDomain)},
+    {"use_messages_staging_url", flag_descriptions::kUseMessagesStagingUrlName,
+     flag_descriptions::kUseMessagesStagingUrlDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kUseMessagesStagingUrl)},
     {"enable_messages_web_push", flag_descriptions::kEnableMessagesWebPushName,
      flag_descriptions::kEnableMessagesWebPushDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kEnableMessagesWebPush)},
@@ -2300,10 +2303,6 @@
          switches::kBlinkSettings,
          "disallowFetchForDocWrittenScriptsInMainFrame=false")},
 #if defined(OS_WIN)
-    {"trace-export-events-to-etw",
-     flag_descriptions::kTraceExportEventsToEtwName,
-     flag_descriptions::kTraceExportEventsToEtwDesription, kOsWin,
-     SINGLE_VALUE_TYPE(switches::kTraceExportEventsToETW)},
     {"use-winrt-midi-api", flag_descriptions::kUseWinrtMidiApiName,
      flag_descriptions::kUseWinrtMidiApiDescription, kOsWin,
      FEATURE_VALUE_TYPE(midi::features::kMidiManagerWinrt)},
@@ -4285,6 +4284,12 @@
      FEATURE_VALUE_TYPE(ash::features::kEnableOverviewRoundedCorners)},
 #endif  // defined(OS_CHROMEOS)
 
+#if defined(OS_WIN)
+    {"d3d11-video-decoder", flag_descriptions::kD3D11VideoDecoderName,
+     flag_descriptions::kD3D11VideoDecoderDescription, kOsWin,
+     FEATURE_VALUE_TYPE(media::kD3D11VideoDecoder)},
+#endif
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/apps/platform_apps/shortcut_manager.cc b/chrome/browser/apps/platform_apps/shortcut_manager.cc
index 39b10d01..21379bb4 100644
--- a/chrome/browser/apps/platform_apps/shortcut_manager.cc
+++ b/chrome/browser/apps/platform_apps/shortcut_manager.cc
@@ -57,10 +57,6 @@
                            creation_locations, profile, app);
 }
 
-void SetCurrentAppShortcutsVersion(PrefService* prefs) {
-  prefs->SetInteger(prefs::kAppShortcutsVersion, kCurrentAppShortcutsVersion);
-}
-
 }  // namespace
 
 // static
@@ -73,7 +69,6 @@
 AppShortcutManager::AppShortcutManager(Profile* profile)
     : profile_(profile),
       is_profile_attributes_storage_observer_(false),
-      prefs_(profile->GetPrefs()),
       extension_registry_observer_(this),
       weak_ptr_factory_(this) {
   // Use of g_browser_process requires that we are either on the UI thread, or
@@ -145,17 +140,32 @@
                      profile_path));
 }
 
+void AppShortcutManager::UpdateShortcutsForAllAppsNow() {
+  web_app::UpdateShortcutsForAllApps(
+      profile_,
+      base::BindOnce(&AppShortcutManager::SetCurrentAppShortcutsVersion,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AppShortcutManager::SetCurrentAppShortcutsVersion() {
+  profile_->GetPrefs()->SetInteger(prefs::kAppShortcutsVersion,
+                                   kCurrentAppShortcutsVersion);
+}
+
 void AppShortcutManager::UpdateShortcutsForAllAppsIfNeeded() {
+  // Updating shortcuts writes to user home folders, which can not be done in
+  // tests without exploding disk space usage on the bots.
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType))
     return;
 
-  int last_version = prefs_->GetInteger(prefs::kAppShortcutsVersion);
+  int last_version =
+      profile_->GetPrefs()->GetInteger(prefs::kAppShortcutsVersion);
   if (last_version >= kCurrentAppShortcutsVersion)
     return;
 
   base::PostDelayedTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&web_app::UpdateShortcutsForAllApps, profile_,
-                     base::Bind(&SetCurrentAppShortcutsVersion, prefs_)),
+      base::BindOnce(&AppShortcutManager::UpdateShortcutsForAllAppsNow,
+                     weak_ptr_factory_.GetWeakPtr()),
       base::TimeDelta::FromSeconds(kUpdateShortcutsForAllAppsDelay));
 }
diff --git a/chrome/browser/apps/platform_apps/shortcut_manager.h b/chrome/browser/apps/platform_apps/shortcut_manager.h
index 565b6639..dfb6458 100644
--- a/chrome/browser/apps/platform_apps/shortcut_manager.h
+++ b/chrome/browser/apps/platform_apps/shortcut_manager.h
@@ -13,7 +13,6 @@
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension.h"
 
-class PrefService;
 class Profile;
 
 namespace extensions {
@@ -35,8 +34,8 @@
 
   ~AppShortcutManager() override;
 
-  // Updates all shortcuts if kAppShortcutsVersion in prefs is less than
-  // kCurrentAppShortcutsVersion.
+  // Schedules a call to UpdateShortcutsForAllAppsNow() if kAppShortcutsVersion
+  // in prefs is less than kCurrentAppShortcutsVersion.
   void UpdateShortcutsForAllAppsIfNeeded();
 
   // extensions::ExtensionRegistryObserver.
@@ -52,11 +51,12 @@
   void OnProfileWillBeRemoved(const base::FilePath& profile_path) override;
 
  private:
+  void UpdateShortcutsForAllAppsNow();
+  void SetCurrentAppShortcutsVersion();
   void DeleteApplicationShortcuts(const extensions::Extension* extension);
 
   Profile* profile_;
   bool is_profile_attributes_storage_observer_;
-  PrefService* prefs_;
 
   ScopedObserver<extensions::ExtensionRegistry,
                  extensions::ExtensionRegistryObserver>
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index 5695e30..ace57e9 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -65,6 +65,7 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "media/base/media_switches.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/dns/mock_host_resolver.h"
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index c8c3d44..1ac2e6f 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -1015,15 +1015,9 @@
 #endif  // !defined(OS_ANDROID)
 
 #if defined(OS_WIN)
-  // This is needed to enable ETW exporting when requested in about:flags.
-  // Normally, we enable it in ContentMainRunnerImpl::Initialize when the flag
-  // is present on the command line but flags in about:flags are converted only
-  // after this function runs. Note that this starts exporting later which
-  // affects tracing the browser startup. Also, this is only relevant for the
-  // browser process, as other processes will get all the flags on their command
-  // line regardless of the origin (command line or about:flags).
-  if (parsed_command_line().HasSwitch(switches::kTraceExportEventsToETW))
-    base::trace_event::TraceEventETWExport::EnableETWExport();
+  // This is needed to enable ETW exporting. This is only relevant for the
+  // browser process, as other processes enable it separately.
+  base::trace_event::TraceEventETWExport::EnableETWExport();
 #endif  // OS_WIN
 
   // Reset the command line in the crash report details, since we may have
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 4d63a3d..32c174c 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -232,6 +232,7 @@
     "//ui/accessibility",
     "//ui/aura",
     "//ui/base",
+    "//ui/base/idle",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
diff --git a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc
index 0bb3afd..729d86c 100644
--- a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc
+++ b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc
@@ -18,6 +18,8 @@
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/common/video_decode_accelerator.mojom.h"
+#include "components/arc/common/video_encode_accelerator.mojom.h"
+#include "components/arc/common/video_protected_buffer_allocator.mojom.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_service_registry.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index a3a2b580..814ac111 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -46,6 +46,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
 #include "dbus/message.h"
+#include "device/usb/public/mojom/device.mojom.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "extensions/browser/extension_registry.h"
 #include "net/base/escape.h"
 #include "net/base/network_change_notifier.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 8b83a30..19b5574 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -24,6 +24,7 @@
 #include "chromeos/dbus/concierge_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
+#include "device/usb/public/mojom/device_manager_client.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 
 class Profile;
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index 1add0bb..7daaf70 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
+#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "services/ws/public/mojom/window_server_test.mojom.h"
 #include "ui/message_center/public/cpp/notification_types.h"
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 90ba7cf9..151b4344 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -51,6 +51,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "services/device/public/mojom/mtp_manager.mojom.h"
+#include "services/device/public/mojom/mtp_storage_info.mojom.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 
 namespace file_manager {
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index ac26a6c..ad53b0eb 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -38,6 +38,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "extensions/browser/extension_registry.h"
+#include "services/device/public/mojom/mtp_storage_info.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using chromeos::disks::Disk;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
index 6311828e1..1c29312 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -145,15 +145,15 @@
   DISALLOW_COPY_AND_ASSIGN(KeyEventDoneCallback);
 };
 
-INSTANTIATE_TEST_CASE_P(InputMethodEngineBrowserTest,
-                        InputMethodEngineBrowserTest,
-                        ::testing::Values(kTestTypeNormal));
-INSTANTIATE_TEST_CASE_P(InputMethodEngineIncognitoBrowserTest,
-                        InputMethodEngineBrowserTest,
-                        ::testing::Values(kTestTypeIncognito));
-INSTANTIATE_TEST_CASE_P(InputMethodEngineComponentExtensionBrowserTest,
-                        InputMethodEngineBrowserTest,
-                        ::testing::Values(kTestTypeComponent));
+INSTANTIATE_TEST_SUITE_P(InputMethodEngineBrowserTest,
+                         InputMethodEngineBrowserTest,
+                         ::testing::Values(kTestTypeNormal));
+INSTANTIATE_TEST_SUITE_P(InputMethodEngineIncognitoBrowserTest,
+                         InputMethodEngineBrowserTest,
+                         ::testing::Values(kTestTypeIncognito));
+INSTANTIATE_TEST_SUITE_P(InputMethodEngineComponentExtensionBrowserTest,
+                         InputMethodEngineBrowserTest,
+                         ::testing::Values(kTestTypeComponent));
 
 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest,
                        BasicScenarioTest) {
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
index 0b53484..9d67e11 100644
--- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/hid_controller_mixin.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_configuration_waiter.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
@@ -37,12 +38,6 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
-#include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "device/bluetooth/test/mock_bluetooth_adapter.h"
-#include "services/device/public/cpp/hid/fake_input_service_linux.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/device/public/mojom/input_service.mojom.h"
-#include "services/service_manager/public/cpp/service_binding.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/chromeos/input_method_util.h"
 
@@ -712,47 +707,14 @@
 class EnterpriseEnrollmentConfigurationTestNoHID
     : public EnterpriseEnrollmentConfigurationTest {
  public:
-  using InputDeviceInfoPtr = device::mojom::InputDeviceInfoPtr;
+  EnterpriseEnrollmentConfigurationTestNoHID() = default;
 
-  EnterpriseEnrollmentConfigurationTestNoHID() {
-    fake_input_service_manager_ =
-        std::make_unique<device::FakeInputServiceLinux>();
+  ~EnterpriseEnrollmentConfigurationTestNoHID() override = default;
 
-    service_manager::ServiceBinding::OverrideInterfaceBinderForTesting(
-        device::mojom::kServiceName,
-        base::BindRepeating(
-            &device::FakeInputServiceLinux::Bind,
-            base::Unretained(fake_input_service_manager_.get())));
-  }
-
-  ~EnterpriseEnrollmentConfigurationTestNoHID() override {
-    service_manager::ServiceBinding::ClearInterfaceBinderOverrideForTesting<
-        device::mojom::InputDeviceManager>(device::mojom::kServiceName);
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    EnterpriseEnrollmentConfigurationTest::SetUpInProcessBrowserTestFixture();
-
-    mock_adapter_ = new testing::NiceMock<device::MockBluetoothAdapter>();
-
-    device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
-    EXPECT_CALL(*mock_adapter_, IsPresent())
-        .WillRepeatedly(testing::Return(true));
-    EXPECT_CALL(*mock_adapter_, IsPowered())
-        .WillRepeatedly(testing::Return(true));
-    EXPECT_CALL(*mock_adapter_, GetDevices())
-        .WillRepeatedly(
-            testing::Return(device::BluetoothAdapter::ConstDeviceList()));
-
-    // Note: The SecureChannel service, which is never destroyed until the
-    // browser process is killed, utilizes |mock_adapter_|.
-    testing::Mock::AllowLeak(mock_adapter_.get());
-  }
+ protected:
+  test::HIDControllerMixin hid_controller_{&mixin_host_};
 
  private:
-  std::unique_ptr<device::FakeInputServiceLinux> fake_input_service_manager_;
-  scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
-
   DISALLOW_COPY_AND_ASSIGN(EnterpriseEnrollmentConfigurationTestNoHID);
 };
 
diff --git a/chrome/browser/chromeos/login/hid_detection_browsertest.cc b/chrome/browser/chromeos/login/hid_detection_browsertest.cc
index 9c33dfa..693b575 100644
--- a/chrome/browser/chromeos/login/hid_detection_browsertest.cc
+++ b/chrome/browser/chromeos/login/hid_detection_browsertest.cc
@@ -4,110 +4,36 @@
 
 #include <memory>
 
-#include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
+#include "chrome/browser/chromeos/login/test/hid_controller_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
-#include "content/public/browser/browser_thread.h"
-#include "device/bluetooth/bluetooth_adapter_factory.h"
-#include "device/bluetooth/test/mock_bluetooth_adapter.h"
-#include "services/device/public/cpp/hid/fake_input_service_linux.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/device/public/mojom/input_service.mojom.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "testing/gmock/include/gmock/gmock.h"
 
-using content::BrowserThread;
 using testing::_;
 
-namespace {
-
-void SetUpBluetoothMock(
-    scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter,
-    bool is_present) {
-  device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter);
-
-  EXPECT_CALL(*mock_adapter, IsPresent())
-      .WillRepeatedly(testing::Return(is_present));
-
-  EXPECT_CALL(*mock_adapter, IsPowered()).WillRepeatedly(testing::Return(true));
-  EXPECT_CALL(*mock_adapter, GetDevices())
-      .WillRepeatedly(
-          testing::Return(device::BluetoothAdapter::ConstDeviceList()));
-}
-
-}  // namespace
-
 namespace chromeos {
 
 class HidDetectionTest : public OobeBaseTest {
  public:
-  typedef device::mojom::InputDeviceInfoPtr InputDeviceInfoPtr;
+  HidDetectionTest() = default;
+  ~HidDetectionTest() override = default;
 
-  HidDetectionTest() : weak_ptr_factory_(this) {
-    fake_input_service_manager_ =
-        std::make_unique<device::FakeInputServiceLinux>();
-
-    service_manager::ServiceBinding::OverrideInterfaceBinderForTesting(
-        device::mojom::kServiceName,
-        base::Bind(&device::FakeInputServiceLinux::Bind,
-                   base::Unretained(fake_input_service_manager_.get())));
-  }
-
-  ~HidDetectionTest() override {
-    service_manager::ServiceBinding::ClearInterfaceBinderOverrideForTesting<
-        device::mojom::InputDeviceManager>(device::mojom::kServiceName);
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    OobeBaseTest::SetUpInProcessBrowserTestFixture();
-
-    mock_adapter_ = new testing::NiceMock<device::MockBluetoothAdapter>();
-    SetUpBluetoothMock(mock_adapter_, true);
-
-    // Note: The SecureChannel service, which is never destroyed until the
-    // browser process is killed, utilizes |mock_adapter_|.
-    testing::Mock::AllowLeak(mock_adapter_.get());
-  }
-
-  void AddUsbMouse(const std::string& mouse_id) {
-    auto mouse = device::mojom::InputDeviceInfo::New();
-    mouse->id = mouse_id;
-    mouse->subsystem = device::mojom::InputDeviceSubsystem::SUBSYSTEM_INPUT;
-    mouse->type = device::mojom::InputDeviceType::TYPE_USB;
-    mouse->is_mouse = true;
-    fake_input_service_manager_->AddDevice(std::move(mouse));
-  }
-
-  void AddUsbKeyboard(const std::string& keyboard_id) {
-    auto keyboard = device::mojom::InputDeviceInfo::New();
-    keyboard->id = keyboard_id;
-    keyboard->subsystem = device::mojom::InputDeviceSubsystem::SUBSYSTEM_INPUT;
-    keyboard->type = device::mojom::InputDeviceType::TYPE_USB;
-    keyboard->is_keyboard = true;
-    fake_input_service_manager_->AddDevice(std::move(keyboard));
-  }
+ protected:
+  test::HIDControllerMixin hid_controller_{&mixin_host_};
 
  private:
-  std::unique_ptr<device::FakeInputServiceLinux> fake_input_service_manager_;
-  scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
-
-  base::WeakPtrFactory<HidDetectionTest> weak_ptr_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(HidDetectionTest);
 };
 
 class HidDetectionSkipTest : public HidDetectionTest {
  public:
   HidDetectionSkipTest() {
-    AddUsbMouse("mouse");
-    AddUsbKeyboard("keyboard");
+    hid_controller_.AddUsbMouse(test::HIDControllerMixin::kMouseId);
+    hid_controller_.AddUsbKeyboard(test::HIDControllerMixin::kKeyboardId);
   }
 
-  void SetUpOnMainThread() override { HidDetectionTest::SetUpOnMainThread(); }
+  ~HidDetectionSkipTest() override = default;
 };
 
 IN_PROC_BROWSER_TEST_F(HidDetectionTest, NoDevicesConnected) {
diff --git a/chrome/browser/chromeos/login/test/hid_controller_mixin.cc b/chrome/browser/chromeos/login/test/hid_controller_mixin.cc
new file mode 100644
index 0000000..c3ded89
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/hid_controller_mixin.cc
@@ -0,0 +1,89 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/test/hid_controller_mixin.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "services/device/public/cpp/hid/fake_input_service_linux.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/input_service.mojom.h"
+#include "services/service_manager/public/cpp/service_binding.h"
+
+using testing::_;
+
+namespace {
+
+void SetUpBluetoothMock(
+    scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter,
+    bool is_present) {
+  device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter);
+
+  EXPECT_CALL(*mock_adapter, IsPresent())
+      .WillRepeatedly(testing::Return(is_present));
+
+  EXPECT_CALL(*mock_adapter, IsPowered()).WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_adapter, GetDevices())
+      .WillRepeatedly(
+          testing::Return(device::BluetoothAdapter::ConstDeviceList()));
+}
+
+}  // namespace
+
+namespace chromeos {
+namespace test {
+
+using InputDeviceInfoPtr = device::mojom::InputDeviceInfoPtr;
+
+// static
+const char HIDControllerMixin::kMouseId[] = "mouse";
+const char HIDControllerMixin::kKeyboardId[] = "keyboard";
+
+HIDControllerMixin::HIDControllerMixin(InProcessBrowserTestMixinHost* host)
+    : InProcessBrowserTestMixin(host) {
+  fake_input_service_manager_ =
+      std::make_unique<device::FakeInputServiceLinux>();
+
+  service_manager::ServiceBinding::OverrideInterfaceBinderForTesting(
+      device::mojom::kServiceName,
+      base::BindRepeating(&device::FakeInputServiceLinux::Bind,
+                          base::Unretained(fake_input_service_manager_.get())));
+}
+
+HIDControllerMixin::~HIDControllerMixin() {
+  service_manager::ServiceBinding::ClearInterfaceBinderOverrideForTesting<
+      device::mojom::InputDeviceManager>(device::mojom::kServiceName);
+}
+
+void HIDControllerMixin::SetUpInProcessBrowserTestFixture() {
+  mock_adapter_ = new testing::NiceMock<device::MockBluetoothAdapter>();
+  SetUpBluetoothMock(mock_adapter_, true);
+
+  // Note: The SecureChannel service, which is never destroyed until the
+  // browser process is killed, utilizes |mock_adapter_|.
+  testing::Mock::AllowLeak(mock_adapter_.get());
+}
+
+void HIDControllerMixin::AddUsbMouse(const std::string& mouse_id) {
+  auto mouse = device::mojom::InputDeviceInfo::New();
+  mouse->id = mouse_id;
+  mouse->subsystem = device::mojom::InputDeviceSubsystem::SUBSYSTEM_INPUT;
+  mouse->type = device::mojom::InputDeviceType::TYPE_USB;
+  mouse->is_mouse = true;
+  fake_input_service_manager_->AddDevice(std::move(mouse));
+}
+
+void HIDControllerMixin::AddUsbKeyboard(const std::string& keyboard_id) {
+  auto keyboard = device::mojom::InputDeviceInfo::New();
+  keyboard->id = keyboard_id;
+  keyboard->subsystem = device::mojom::InputDeviceSubsystem::SUBSYSTEM_INPUT;
+  keyboard->type = device::mojom::InputDeviceType::TYPE_USB;
+  keyboard->is_keyboard = true;
+  fake_input_service_manager_->AddDevice(std::move(keyboard));
+}
+
+}  // namespace test
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/hid_controller_mixin.h b/chrome/browser/chromeos/login/test/hid_controller_mixin.h
new file mode 100644
index 0000000..40bd86f9
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/hid_controller_mixin.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_HID_CONTROLLER_MIXIN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_HID_CONTROLLER_MIXIN_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h"
+#include "device/bluetooth/test/mock_bluetooth_adapter.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace device {
+class FakeInputServiceLinux;
+}
+
+namespace chromeos {
+namespace test {
+
+// This test mixin allows to control presence of Human Input Devices during
+// OOBE. Just adding this mixin would result in "ho HID available" case,
+// and it can be changed using AddUsbMouse / AddUsbKeyboard methods.
+class HIDControllerMixin : public InProcessBrowserTestMixin {
+ public:
+  static const char kMouseId[];
+  static const char kKeyboardId[];
+
+  explicit HIDControllerMixin(InProcessBrowserTestMixinHost* host);
+  ~HIDControllerMixin() override;
+
+  void AddUsbMouse(const std::string& mouse_id);
+  void AddUsbKeyboard(const std::string& keyboard_id);
+
+  void SetUpInProcessBrowserTestFixture() override;
+
+ private:
+  std::unique_ptr<device::FakeInputServiceLinux> fake_input_service_manager_;
+  scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
+
+  base::WeakPtrFactory<HIDControllerMixin> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(HIDControllerMixin);
+};
+
+}  // namespace test
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_HID_CONTROLLER_MIXIN_H_
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
index 89f719d7..8c021c6 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/login/ui/login_display_mojo.h"
 
+#include "ash/public/interfaces/login_user_info.mojom.h"
 #include "base/bind.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 80ab8275..ac65679 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -149,7 +149,7 @@
                                       is_enterprise_device) {
     // Set the baseline time to a fixed value (1 hour after day start) to
     // prevent test flakiness due to a single activity period spanning two days.
-    SetBaselineTime(Time::Now().UTCMidnight() + activity_day_start + kHour);
+    SetBaselineTime(Time::Now().LocalMidnight() + activity_day_start + kHour);
   }
 
   void UpdateUsageTime() { UpdateChildUsageTime(); }
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn b/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
index 764e4252..dba4838 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
+++ b/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
@@ -25,6 +25,7 @@
     "//chrome/common:constants",
     "//chromeos:chromeos",
     "//chromeos/services/machine_learning/public/cpp:cpp",
+    "//chromeos/services/machine_learning/public/mojom:mojom",
     "//components/assist_ranker",
     "//components/assist_ranker/proto",
     "//components/sessions",
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/ml_service_client.h b/chrome/browser/chromeos/power/ml/smart_dim/ml_service_client.h
index 9b76d42..af0cfba 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/ml_service_client.h
+++ b/chrome/browser/chromeos/power/ml/smart_dim/ml_service_client.h
@@ -13,6 +13,9 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/power/ml/smart_dim/model.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
+#include "chromeos/services/machine_learning/public/mojom/graph_executor.mojom.h"
+#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
+#include "chromeos/services/machine_learning/public/mojom/tensor.mojom.h"
 
 namespace chromeos {
 namespace power {
diff --git a/chrome/browser/chromeos/printing/usb_printer_util.cc b/chrome/browser/chromeos/printing/usb_printer_util.cc
index a644deb..e4e7fd2f 100644
--- a/chrome/browser/chromeos/printing/usb_printer_util.cc
+++ b/chrome/browser/chromeos/printing/usb_printer_util.cc
@@ -18,6 +18,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/printing/printer_configuration.h"
 #include "device/usb/public/cpp/usb_utils.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_device.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index a820398..816eed3 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -1228,7 +1228,7 @@
   CheckDownload(browser(), file, file);
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
 // Download a file and confirm that the file is correctly quarantined.
 //
 // TODO(asanka): We should enable the test on Mac as well, but currently
@@ -1252,7 +1252,9 @@
   EXPECT_TRUE(download::IsFileQuarantined(downloaded_file, url, GURL()));
   CheckDownload(browser(), file, file);
 }
+#endif
 
+#if defined(OS_WIN)
 // A couple of Windows specific tests to make sure we respect OS specific
 // restrictions on Mark-Of-The-Web can be applied. While Chrome doesn't directly
 // apply these policies, Chrome still needs to make sure the correct APIs are
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index d1585d6..e3d79a429 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -27,6 +27,7 @@
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/base/ime/ime_engine_handler_interface.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/keyboard/public/keyboard_config.mojom.h"
 
 namespace input_ime = extensions::api::input_ime;
 namespace input_method_private = extensions::api::input_method_private;
diff --git a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
index e20bfa4..fe929f59 100644
--- a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -533,7 +533,6 @@
     NOTIMPLEMENTED();
     return nullptr;
   }
-  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
 
  private:
   std::vector<std::unique_ptr<net::StaticSocketDataProvider>> providers_;
diff --git a/chrome/browser/extensions/test_blacklist_state_fetcher.cc b/chrome/browser/extensions/test_blacklist_state_fetcher.cc
index 4bc514c3..73d1d07 100644
--- a/chrome/browser/extensions/test_blacklist_state_fetcher.cc
+++ b/chrome/browser/extensions/test_blacklist_state_fetcher.cc
@@ -8,6 +8,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/safe_browsing/db/v4_test_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 
 namespace extensions {
 namespace {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 24f458ba..d624898 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -496,6 +496,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "d3d11-video-decoder",
+    "owners": [ "liberato", "tmathmeyer", "videostack-eng" ],
+    "expiry_milestone": 78
+  },
+  {
     "name": "data-saver-server-previews",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
@@ -2227,6 +2232,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "use_messages_staging_url",
+    "owners": [ "azeemarshad", "khorimoto" ],
+    "expiry_milestone": 76
+  },
+  {
     "name": "enable_messages_web_push",
     "owners": [ "azeemarshad", "jlklein", "khorimoto" ],
     "expiry_milestone": 76
@@ -3204,11 +3214,6 @@
     "expiry_milestone": 76
   },
   {
-    "name": "trace-export-events-to-etw",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "trace-upload-url",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 74fda64..8ee3295 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -58,6 +58,11 @@
     "Use the messages.google.com domain as part of the \"Messages\" "
     "feature under \"Connected Devices\" settings.";
 
+const char kUseMessagesStagingUrlName[] = "Use Messages staging URL";
+const char kUseMessagesStagingUrlDescription[] =
+    "Use the staging server as part of the \"Messages\" feature under "
+    "\"Connected Devices\" settings.";
+
 const char kEnableMessagesWebPushName[] =
     "Web push in Android Messages integration";
 const char kEnableMessagesWebPushDescription[] =
@@ -2918,6 +2923,10 @@
     "Print with Chrome. Printers must be re-connected after changing this "
     "flag.";
 
+const char kD3D11VideoDecoderName[] = "D3D11 Video Decoder";
+const char kD3D11VideoDecoderDescription[] =
+    "Enables D3D11VideoDecoder for hardware accelerated video decoding.";
+
 const char kDisablePostscriptPrinting[] = "Disable PostScript Printing";
 const char kDisablePostscriptPrintingDescription[] =
     "Disables PostScript generation when printing to PostScript capable "
@@ -2937,13 +2946,6 @@
 const char kGdiTextPrintingDescription[] =
     "Use GDI to print text as simply text";
 
-const char kTraceExportEventsToEtwName[] =
-    "Enable exporting of tracing events to ETW.";
-const char kTraceExportEventsToEtwDesription[] =
-    "If enabled, trace events will be exported to the Event Tracing for "
-    "Windows (ETW) and can then be captured by tools such as UIForETW or "
-    "Xperf.";
-
 const char kUseAngleName[] = "Choose ANGLE graphics backend";
 const char kUseAngleDescription[] =
     "Choose the graphics backend for ANGLE. D3D11 is used on most Windows "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index bba0166..d21bc7b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -67,6 +67,9 @@
 extern const char kUseMessagesGoogleComDomainName[];
 extern const char kUseMessagesGoogleComDomainDescription[];
 
+extern const char kUseMessagesStagingUrlName[];
+extern const char kUseMessagesStagingUrlDescription[];
+
 extern const char kEnableMessagesWebPushName[];
 extern const char kEnableMessagesWebPushDescription[];
 
@@ -1727,6 +1730,9 @@
 extern const char kCloudPrintXpsName[];
 extern const char kCloudPrintXpsDescription[];
 
+extern const char kD3D11VideoDecoderName[];
+extern const char kD3D11VideoDecoderDescription[];
+
 extern const char kDisablePostscriptPrinting[];
 extern const char kDisablePostscriptPrintingDescription[];
 
@@ -1739,9 +1745,6 @@
 extern const char kGdiTextPrinting[];
 extern const char kGdiTextPrintingDescription[];
 
-extern const char kTraceExportEventsToEtwName[];
-extern const char kTraceExportEventsToEtwDesription[];
-
 extern const char kUseAngleName[];
 extern const char kUseAngleDescription[];
 
diff --git a/chrome/browser/media/router/mojo/media_route_controller.h b/chrome/browser/media/router/mojo/media_route_controller.h
index aee0aa1..b210b2b 100644
--- a/chrome/browser/media/router/mojo/media_route_controller.h
+++ b/chrome/browser/media/router/mojo/media_route_controller.h
@@ -12,6 +12,7 @@
 #include "base/observer_list.h"
 #include "chrome/common/media_router/media_route.h"
 #include "chrome/common/media_router/mojo/media_controller.mojom.h"
+#include "chrome/common/media_router/mojo/media_status.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 class PrefService;
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
index 9a128a0..475cef5 100644
--- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
+++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -9,6 +9,7 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/media_stream_device_permissions.h"
 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
 #include "chrome/browser/permissions/permission_manager.h"
@@ -31,9 +32,12 @@
 #include "chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.h"
 #include "chrome/browser/permissions/permission_uma_util.h"
 #include "chrome/browser/permissions/permission_util.h"
-
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_MACOSX)
+#include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
+#endif
+
 using content::BrowserThread;
 
 using RepeatingMediaResponseCallback =
@@ -123,6 +127,25 @@
   }
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_MACOSX)
+  // Fail if access is denied in system permission. Note that if permission is
+  // not yet determined, we don't fail. If all other permissions are OK, we'll
+  // allow access. The reason for doing this is that if the permission is not
+  // yet determined, the user will get an async alert dialog and we don't want
+  // to wait on that before resolving getUserMedia. getUserMedia will succeed,
+  // but audio will be silent until user allows permission in the dialog. If the
+  // user denies permission audio will continue being silent but they will
+  // likely understand why since they denied it.
+  // TODO(https://crbug.com/885184): Handle the not determined case better.
+  if (request.audio_type == blink::MEDIA_DEVICE_AUDIO_CAPTURE &&
+      SystemAudioCapturePermissionIsDisallowed()) {
+    std::move(callback).Run(blink::MediaStreamDevices(),
+                            blink::MEDIA_DEVICE_SYSTEM_PERMISSION_DENIED,
+                            nullptr);
+    return;
+  }
+#endif  // defined(OS_MACOSX)
+
   RequestsQueue& queue = pending_requests_[web_contents];
   queue.push_back(PendingAccessRequest(
       request, base::AdaptCallbackForRepeating(std::move(callback))));
@@ -207,6 +230,17 @@
   if (queue.empty())
     return;
 
+#if defined(OS_MACOSX)
+  // If the request was approved, trigger system user dialog if needed. We need
+  // to do this explicitly so that the system gives the correct information
+  // about the permission state in future requests
+  // (see PermissionBubbleMediaAccessHandler::HandleRequest).
+  if (queue.front().request.audio_type == blink::MEDIA_DEVICE_AUDIO_CAPTURE &&
+      result == blink::MEDIA_DEVICE_OK) {
+    EnsureSystemAudioCapturePermission();
+  }
+#endif  // defined(OS_MACOSX)
+
   RepeatingMediaResponseCallback callback = queue.front().callback;
   queue.pop_front();
 
diff --git a/chrome/browser/media/webrtc/system_media_capture_permissions_mac.h b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.h
new file mode 100644
index 0000000..4e460fc
--- /dev/null
+++ b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_WEBRTC_SYSTEM_MEDIA_CAPTURE_PERMISSIONS_MAC_H_
+#define CHROME_BROWSER_MEDIA_WEBRTC_SYSTEM_MEDIA_CAPTURE_PERMISSIONS_MAC_H_
+
+// On 10.14 and above: returns true if permission is not allowed in system
+// settings, false otherwise, including if permission is not determined yet.
+// On 10.13 and below: returns false, since there are no system media capture
+// permissions.
+bool SystemAudioCapturePermissionIsDisallowed();
+
+// On 10.14 and above: if system permission is not determined, requests
+// permission. Otherwise, does nothing. When requesting permission, the OS will
+// show a user dialog and respond asynchronously. This function does not wait
+// for the response and nothing is done at the response. The reason
+// for explicitly requesting permission is that if only implicitly requesting
+// permission (when media::AUAudioInputStream::Start() calls
+// AudioOutputUnitStart()), the OS returns not determined when we ask what the
+// permission state is, even though it's actually set to something else, until
+// browser restart.
+// On 10.13 and below: does nothing, since there are no system media capture
+// permissions.
+void EnsureSystemAudioCapturePermission();
+
+#endif  // CHROME_BROWSER_MEDIA_WEBRTC_SYSTEM_MEDIA_CAPTURE_PERMISSIONS_MAC_H_
diff --git a/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm
new file mode 100644
index 0000000..a6942b9
--- /dev/null
+++ b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm
@@ -0,0 +1,67 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Authorization functions and types are available on 10.14+.
+// To avoid availability compile errors, use performSelector invocation of
+// functions and NSInteger instead of AVAuthorizationStatus.
+// The AVAuthorizationStatus enum is defined as follows (10.14 SDK):
+// AVAuthorizationStatusNotDetermined = 0,
+// AVAuthorizationStatusRestricted    = 1,
+// AVAuthorizationStatusDenied        = 2,
+// AVAuthorizationStatusAuthorized    = 3,
+// TODO(grunell): Call functions directly and use AVAuthorizationStatus once
+// we use the 10.14 SDK.
+
+#include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
+
+#import <AVFoundation/AVFoundation.h>
+
+#include "base/logging.h"
+
+namespace {
+
+NSInteger AudioAuthorizationStatus() {
+  if (@available(macOS 10.14, *)) {
+    AVCaptureDevice* target = [AVCaptureDevice class];
+    SEL selector = @selector(authorizationStatusForMediaType:);
+    NSInteger auth_status = 0;
+    if ([target respondsToSelector:selector]) {
+      auth_status = (NSInteger)[target performSelector:selector
+                                            withObject:AVMediaTypeAudio];
+    } else {
+      DLOG(WARNING) << "authorizationStatusForMediaType could not be executed";
+    }
+    return auth_status;
+  }
+
+  NOTREACHED();
+  return 0;
+}
+
+}  // namespace
+
+bool SystemAudioCapturePermissionIsDisallowed() {
+  if (@available(macOS 10.14, *)) {
+    NSInteger auth_status = AudioAuthorizationStatus();
+    return auth_status == 1 || auth_status == 2;
+  }
+  return false;
+}
+
+void EnsureSystemAudioCapturePermission() {
+  if (@available(macOS 10.14, *)) {
+    if (AudioAuthorizationStatus() == 0) {
+      AVCaptureDevice* target = [AVCaptureDevice class];
+      SEL selector = @selector(requestAccessForMediaType:completionHandler:);
+      if ([target respondsToSelector:selector]) {
+        [target performSelector:selector
+                     withObject:AVMediaTypeAudio
+                     withObject:^(BOOL granted){
+                     }];
+      } else {
+        DLOG(WARNING) << "requestAccessForMediaType could not be executed";
+      }
+    }
+  }
+}
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc
index 0d49766e..5ee353a 100644
--- a/chrome/browser/password_manager/password_store_x.cc
+++ b/chrome/browser/password_manager/password_store_x.cc
@@ -570,7 +570,8 @@
   return PasswordStoreDefault::RemoveLoginByPrimaryKeySync(primary_key);
 }
 
-syncer::SyncMetadataStore* PasswordStoreX::GetMetadataStore() {
+password_manager::PasswordStoreSync::MetadataStore*
+PasswordStoreX::GetMetadataStore() {
   // This method is called from the PasswordSyncBridge which supports only
   // PasswordStoreDefault. Therefore, on Linux, it should be called only if the
   // client is using LogainDatabase instead of the NativeBackend's. It's the
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h
index 6217b95a..c7cda92e 100644
--- a/chrome/browser/password_manager/password_store_x.h
+++ b/chrome/browser/password_manager/password_store_x.h
@@ -143,7 +143,8 @@
       password_manager::PrimaryKeyToFormMap* key_to_form_map) override;
   password_manager::PasswordStoreChangeList RemoveLoginByPrimaryKeySync(
       int primary_key) override;
-  syncer::SyncMetadataStore* GetMetadataStore() override;
+  password_manager::PasswordStoreSync::MetadataStore* GetMetadataStore()
+      override;
 
  private:
   friend class PasswordStoreXTest;
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
index 930a808..0ebe872 100644
--- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
@@ -327,7 +327,7 @@
   UploadChromeDesktopReport(&chrome_desktop_report);
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     MachineLevelUserCloudPolicyServiceIntegrationTestInstance,
     MachineLevelUserCloudPolicyServiceIntegrationTest,
     testing::Values(
@@ -499,10 +499,10 @@
 #endif
 }
 
-INSTANTIATE_TEST_CASE_P(,
-                        MachineLevelUserCloudPolicyEnrollmentTest,
-                        ::testing::Combine(::testing::Bool(),
-                                           ::testing::Bool(),
-                                           ::testing::Bool()));
+INSTANTIATE_TEST_SUITE_P(,
+                         MachineLevelUserCloudPolicyEnrollmentTest,
+                         ::testing::Combine(::testing::Bool(),
+                                            ::testing::Bool(),
+                                            ::testing::Bool()));
 
 }  // namespace policy
diff --git a/chrome/browser/profiles/profile_downloader_unittest.cc b/chrome/browser/profiles/profile_downloader_unittest.cc
index 89e4f53..08f8f95 100644
--- a/chrome/browser/profiles/profile_downloader_unittest.cc
+++ b/chrome/browser/profiles/profile_downloader_unittest.cc
@@ -9,13 +9,11 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile_downloader_delegate.h"
 #include "chrome/browser/signin/account_fetcher_service_factory.h"
-#include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/fake_account_fetcher_service_builder.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
 #include "chrome/browser/signin/test_signin_client_builder.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/signin/core/browser/account_info.h"
-#include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_account_fetcher_service.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -26,7 +24,6 @@
 namespace {
 
 const char kTestEmail[] = "test@example.com";
-const char kTestGaia[] = "gaia";
 const char kTestHostedDomain[] = "google.com";
 const char kTestFullName[] = "full_name";
 const char kTestGivenName[] = "given_name";
@@ -54,8 +51,6 @@
     profile_ = IdentityTestEnvironmentProfileAdaptor::
         CreateProfileForIdentityTestEnvironment(builder);
 
-    account_tracker_service_ =
-        AccountTrackerServiceFactory::GetForProfile(profile_.get());
     account_fetcher_service_ = static_cast<FakeAccountFetcherService*>(
         AccountFetcherServiceFactory::GetForProfile(profile_.get()));
     profile_downloader_.reset(new ProfileDownloader(this));
@@ -85,12 +80,12 @@
       ProfileDownloader* downloader,
       ProfileDownloaderDelegate::FailureReason reason) override {}
 
-  void SimulateUserInfoSuccess(const std::string& picture_url) {
+  void SimulateUserInfoSuccess(const std::string& picture_url,
+                               const AccountInfo& account_info) {
     account_fetcher_service_->FakeUserInfoFetchSuccess(
-        account_tracker_service_->PickAccountIdForAccount(kTestGaia,
-                                                          kTestEmail),
-        kTestEmail, kTestGaia, kTestHostedDomain, kTestFullName, kTestGivenName,
-        kTestLocale, picture_url);
+        account_info.account_id, account_info.email, account_info.gaia,
+        kTestHostedDomain, kTestFullName, kTestGivenName, kTestLocale,
+        picture_url);
   }
 
   // IdentityManager::DiagnosticsObserver:
@@ -110,7 +105,6 @@
     on_access_token_request_callback_ = std::move(callback);
   }
 
-  AccountTrackerService* account_tracker_service_;
   FakeAccountFetcherService* account_fetcher_service_;
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<Profile> profile_;
@@ -123,49 +117,57 @@
 };
 
 TEST_F(ProfileDownloaderTest, FetchAccessToken) {
-  std::string account_id =
-      account_tracker_service_->SeedAccountInfo(kTestGaia, kTestEmail);
-  identity_test_env_->SetRefreshTokenForAccount(account_id);
+  AccountInfo account_info =
+      identity_test_env_->MakeAccountAvailable(kTestEmail);
+  identity_test_env_->SetRefreshTokenForAccount(account_info.account_id);
 
   base::RunLoop run_loop;
   set_on_access_token_requested_callback(run_loop.QuitClosure());
-  profile_downloader_->StartForAccount(account_id);
+  profile_downloader_->StartForAccount(account_info.account_id);
   run_loop.Run();
 
-  EXPECT_EQ(account_id, account_id_for_access_token_request_);
+  EXPECT_EQ(account_info.account_id, account_id_for_access_token_request_);
 }
 
 TEST_F(ProfileDownloaderTest, AccountInfoReady) {
-  std::string account_id =
-      account_tracker_service_->SeedAccountInfo(kTestGaia, kTestEmail);
-  SimulateUserInfoSuccess(kTestValidPictureURL);
+  AccountInfo account_info =
+      identity_test_env_->MakeAccountAvailable(kTestEmail);
+  SimulateUserInfoSuccess(kTestValidPictureURL, account_info);
 
   ASSERT_EQ(ProfileDownloader::PICTURE_FAILED,
             profile_downloader_->GetProfilePictureStatus());
-  profile_downloader_->StartForAccount(account_id);
+  base::RunLoop run_loop;
+  set_on_access_token_requested_callback(run_loop.QuitClosure());
+  profile_downloader_->StartForAccount(account_info.account_id);
+  run_loop.Run();
   profile_downloader_->StartFetchingImage();
   ASSERT_EQ(kTestValidPictureURL, profile_downloader_->GetProfilePictureURL());
 }
 
 TEST_F(ProfileDownloaderTest, AccountInfoNotReady) {
-  std::string account_id =
-      account_tracker_service_->SeedAccountInfo(kTestGaia, kTestEmail);
-
+  AccountInfo account_info =
+      identity_test_env_->MakeAccountAvailable(kTestEmail);
   ASSERT_EQ(ProfileDownloader::PICTURE_FAILED,
             profile_downloader_->GetProfilePictureStatus());
-  profile_downloader_->StartForAccount(account_id);
+  base::RunLoop run_loop;
+  set_on_access_token_requested_callback(run_loop.QuitClosure());
+  profile_downloader_->StartForAccount(account_info.account_id);
+  run_loop.Run();
   profile_downloader_->StartFetchingImage();
-  SimulateUserInfoSuccess(kTestValidPictureURL);
+  SimulateUserInfoSuccess(kTestValidPictureURL, account_info);
   ASSERT_EQ(kTestValidPictureURL, profile_downloader_->GetProfilePictureURL());
 }
 
 // Regression test for http://crbug.com/854907
 TEST_F(ProfileDownloaderTest, AccountInfoNoPictureDoesNotCrash) {
-  std::string account_id =
-      account_tracker_service_->SeedAccountInfo(kTestGaia, kTestEmail);
-  SimulateUserInfoSuccess(kNoPictureURLFound);
+  AccountInfo account_info =
+      identity_test_env_->MakeAccountAvailable(kTestEmail);
+  SimulateUserInfoSuccess(kNoPictureURLFound, account_info);
 
-  profile_downloader_->StartForAccount(account_id);
+  base::RunLoop run_loop;
+  set_on_access_token_requested_callback(run_loop.QuitClosure());
+  profile_downloader_->StartForAccount(account_info.account_id);
+  run_loop.Run();
   profile_downloader_->StartFetchingImage();
 
   EXPECT_TRUE(profile_downloader_->GetProfilePictureURL().empty());
@@ -175,11 +177,14 @@
 
 // Regression test for http://crbug.com/854907
 TEST_F(ProfileDownloaderTest, AccountInfoInvalidPictureURLDoesNotCrash) {
-  std::string account_id =
-      account_tracker_service_->SeedAccountInfo(kTestGaia, kTestEmail);
-  SimulateUserInfoSuccess(kTestInvalidPictureURL);
+  AccountInfo account_info =
+      identity_test_env_->MakeAccountAvailable(kTestEmail);
+  SimulateUserInfoSuccess(kTestInvalidPictureURL, account_info);
 
-  profile_downloader_->StartForAccount(account_id);
+  base::RunLoop run_loop;
+  set_on_access_token_requested_callback(run_loop.QuitClosure());
+  profile_downloader_->StartForAccount(account_info.account_id);
+  run_loop.Run();
   profile_downloader_->StartFetchingImage();
 
   EXPECT_TRUE(profile_downloader_->GetProfilePictureURL().empty());
diff --git a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html
index 8c0a896..85f2f5f 100644
--- a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html
+++ b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.html
@@ -85,6 +85,7 @@
     </style>
     <multidevice-setup delegate="[[delegate_]]"
         on-setup-exited="onExitRequested_"
+        on-forward-button-focus-requested="onForwardButtonFocusRequested_"
         forward-button-text="{{forwardButtonText_}}"
         forward-button-disabled="{{forwardButtonDisabled_}}"
         cancel-button-text="{{cancelButtonText_}}">
diff --git a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
index 29217ce1..fb210cc 100644
--- a/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
+++ b/chrome/browser/resources/chromeos/login/multidevice_setup_first_run.js
@@ -111,12 +111,9 @@
     /** @override */
     attached: function() {
       this.delegate_ = new MultiDeviceSetupFirstRunDelegate();
-      this.addWebUIListener(
-          'multidevice_setup.initializeSetupFlow',
-          this.initializeSetupFlow.bind(this));
     },
 
-    initializeSetupFlow: function() {
+    onForwardButtonFocusRequested_: function() {
       this.$$('#next-button').focus();
     },
 
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js
index ab7b55c..25e6ea2a 100644
--- a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js
+++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_post_oobe.js
@@ -73,7 +73,6 @@
   attached: function() {
     this.delegate_ = new multidevice_setup.PostOobeDelegate();
     this.$$('multidevice-setup').initializeSetupFlow();
-    this.onForwardButtonFocusRequested_();
   },
 
   /** @private */
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.js b/chrome/browser/resources/chromeos/network_ui/network_ui.js
index 62a6f3452..067fe5b 100644
--- a/chrome/browser/resources/chromeos/network_ui/network_ui.js
+++ b/chrome/browser/resources/chromeos/network_ui/network_ui.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/**
+ * @fileoverview Builds UI elements shown in chrome://networks debugging page.
+ */
 var networkUI = {};
 
 /** @typedef {CrOnc.NetworkStateProperties|CrOnc.DeviceStateProperties} */
diff --git a/chrome/browser/resources/local_ntp/doodles.css b/chrome/browser/resources/local_ntp/doodles.css
index db16857..6e70f2b5 100644
--- a/chrome/browser/resources/local_ntp/doodles.css
+++ b/chrome/browser/resources/local_ntp/doodles.css
@@ -76,11 +76,11 @@
 }
 
 #logo-default,
-.non-white-bg:not(.show-doodle) #logo-non-white {
+.use-notifier #logo-non-white {
   display: block;
 }
 #logo-non-white,
-.non-white-bg:not(.show-doodle) #logo-default {
+.use-notifier #logo-default {
   display: none;
 }
 
@@ -95,8 +95,8 @@
   text-align: text-center;
 }
 
-.non-white-bg:not(.show-doodle) #logo-doodle-container,
-.non-white-bg:not(.show-doodle) #logo-doodle-iframe {
+.use-notifier #logo-doodle-container,
+.use-notifier #logo-doodle-iframe {
   display: none;
 }
 
@@ -113,7 +113,7 @@
 #logo-doodle-notifier {
   display: none;
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier {
+.use-notifier #logo-doodle-notifier {
   background: transparent;
   border: 0;
   cursor: pointer;
@@ -133,7 +133,7 @@
   0% { z-index: 100; }
   100% { z-index: 1; }
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .outer {
+.use-notifier #logo-doodle-notifier .outer {
   animation: anim-z-order 3520ms linear infinite;
   height: 37.5%;
   left: 50%;
@@ -143,7 +143,7 @@
   top: 50%;
   width: 37.5%;
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .inner {
+.use-notifier #logo-doodle-notifier .inner {
   animation: anim-pos 880ms cubic-bezier(0.445, 0.05, 0.55, 0.95)
       infinite alternate;
   border-radius: 50%;
@@ -152,34 +152,34 @@
   transform: rotate(90deg);
   width: 100%;
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball0 {
+.use-notifier #logo-doodle-notifier .ball0 {
   animation-delay: 2640ms;
   transform: rotate(45deg);
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball1 {
+.use-notifier #logo-doodle-notifier .ball1 {
   animation-delay: 1760ms;
   transform: rotate(135deg);
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball2 {
+.use-notifier #logo-doodle-notifier .ball2 {
   transform: rotate(225deg);
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball3 {
+.use-notifier #logo-doodle-notifier .ball3 {
   animation-delay: 880ms;
   transform: rotate(315deg);
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball0 .inner {
+.use-notifier #logo-doodle-notifier .ball0 .inner {
   background: linear-gradient(
       315deg, rgb(0, 85, 221), rgb(0, 119, 255), rgb(0, 119, 255));
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball1 .inner {
+.use-notifier #logo-doodle-notifier .ball1 .inner {
   background: linear-gradient(
       225deg, rgb(221, 0, 0), rgb(238, 51, 51), rgb(255, 119, 85));
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball2 .inner {
+.use-notifier #logo-doodle-notifier .ball2 .inner {
   background: linear-gradient(
       90deg, rgb(0, 119, 68), rgb(0, 153, 68), rgb(85, 187, 85));
 }
-.non-white-bg:not(.show-doodle) #logo-doodle-notifier .ball3 .inner {
+.use-notifier #logo-doodle-notifier .ball3 .inner {
   background: linear-gradient(
       0deg, rgb(255, 170, 51), rgb(255, 204, 0), rgb(255, 221, 102));
 }
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html
index d663892..5e2e845f 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -30,7 +30,7 @@
   <meta name="referrer" content="strict-origin">
 </head>
 <!-- Remember to update the test HTML files in chrome/test/data/local_ntp/
-   whenever making changes to this file.-->
+     whenever making changes to this file.-->
 <body>
   <div id="custom-bg"></div>
   <!-- Container for the OneGoogleBar HTML. -->
@@ -50,7 +50,8 @@
           </button>
         </div>
         <iframe id="logo-doodle-iframe" scrolling="no"></iframe>
-        <!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
+        <!-- A spinner, prompting the doodle. Visible on NTPs with customized
+             backgrounds. -->
         <button id="logo-doodle-notifier">
           <div class="outer ball0"><div class="inner"></div></div>
           <div class="outer ball1"><div class="inner"></div></div>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index d585c33..ea1e0b8 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -96,7 +96,8 @@
   NON_GOOGLE_PAGE: 'non-google-page',
   NON_WHITE_BG: 'non-white-bg',
   RTL: 'rtl',  // Right-to-left language text.
-  SHOW_DOODLE: 'show-doodle',
+  // Applied when the doodle notifier should be shown instead of the doodle.
+  USE_NOTIFIER: 'use-notifier',
 };
 
 
@@ -199,10 +200,9 @@
 
 
 /**
- * Background colors considered "white". Used to determine if it is possible
- * to display a Google Doodle, or if the notifier should be used instead (Note:
- * this only applies if a theme/custom background is set). Also used to
- * determine if a colored or white logo should be used.
+ * Background colors considered "white". Used to determine if it is possible to
+ * display a Google Doodle, or if the notifier should be used instead. Also used
+ * to determine if a colored or white logo should be used.
  * @type {Array<string>}
  * @const
  */
@@ -210,7 +210,8 @@
 
 
 /**
- * Background color for Chrome dark mode.
+ * Background color for Chrome dark mode. Used to determine if it is possible to
+ * display a Google Doodle, or if the notifier should be used instead.
  * @type {string}
  * @const
  */
@@ -286,19 +287,23 @@
 
 /**
  * Returns theme background info, first checking for history.state.notheme. If
- * the page has notheme set, returns a fallback light-colored theme.
+ * the page has notheme set, returns a fallback light-colored theme (or dark-
+ * colored theme if dark mode is enabled). This is used when the doodle is
+ * displayed after clicking the notifier.
  */
 function getThemeBackgroundInfo() {
   if (history.state && history.state.notheme) {
     return {
       alternateLogo: false,
-      backgroundColorRgba: [255, 255, 255, 255],
+      backgroundColorRgba:
+          (isDarkModeEnabled ? [50, 54, 57, 255] : [255, 255, 255, 255]),
       colorRgba: [255, 255, 255, 255],
       headerColorRgba: [150, 150, 150, 255],
       linkColorRgba: [6, 55, 116, 255],
       sectionBorderColorRgba: [150, 150, 150, 255],
       textColorLightRgba: [102, 102, 102, 255],
       textColorRgba: [0, 0, 0, 255],
+      usingDarkMode: isDarkModeEnabled,
       usingDefaultTheme: true,
     };
   }
@@ -352,10 +357,8 @@
   }
 
   var background = [
-    (isDarkModeEnabled ? DARK_MODE_BACKGROUND_COLOR :
-                         convertToRGBAColor(info.backgroundColorRgba)),
-    info.imageUrl, info.imageTiling, info.imageHorizontalAlignment,
-    info.imageVerticalAlignment
+    convertToRGBAColor(info.backgroundColorRgba), info.imageUrl,
+    info.imageTiling, info.imageHorizontalAlignment, info.imageVerticalAlignment
   ].join(' ').trim();
 
   // If a custom background has been selected the image will be applied to the
@@ -370,9 +373,13 @@
   document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, useWhiteLogo);
   const isNonWhiteBackground = !WHITE_BACKGROUND_COLORS.includes(background);
   document.body.classList.toggle(CLASSES.NON_WHITE_BG, isNonWhiteBackground);
-  // Show the doodle if this is the default NTP.
-  const showDoodle = info.usingDefaultTheme && !info.customBackgroundConfigured;
-  document.body.classList.toggle(CLASSES.SHOW_DOODLE, showDoodle);
+
+  // The doodle notifier should be shown for non-default backgrounds. This
+  // includes non-white backgrounds, excluding dark mode gray if dark mode is
+  // enabled.
+  const isDefaultBackground = WHITE_BACKGROUND_COLORS.includes(background) ||
+      (isDarkModeEnabled && background === DARK_MODE_BACKGROUND_COLOR);
+  document.body.classList.toggle(CLASSES.USE_NOTIFIER, !isDefaultBackground);
 
   updateThemeAttribution(info.attributionUrl, info.imageHorizontalAlignment);
   setCustomThemeStyle(info);
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index cf5b485eb..e04e3b5 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -1148,6 +1148,14 @@
 
     chrome.fileSystem.chooseEntry(
         {type: 'saveFile', suggestedName: fileName}, entry => {
+          if (chrome.runtime.lastError) {
+            if (chrome.runtime.lastError.message != 'User cancelled') {
+              console.log(
+                  'chrome.fileSystem.chooseEntry failed: ' +
+                  chrome.runtime.lastError.message);
+            }
+            return;
+          }
           entry.createWriter(writer => {
             writer.write(
                 new Blob([result.dataToSave], {type: 'application/pdf'}));
diff --git a/chrome/browser/resources/print_preview/data/cloud_parsers.js b/chrome/browser/resources/print_preview/data/cloud_parsers.js
index 2648923..996ddfca 100644
--- a/chrome/browser/resources/print_preview/data/cloud_parsers.js
+++ b/chrome/browser/resources/print_preview/data/cloud_parsers.js
@@ -120,8 +120,7 @@
     };
     const cloudDest = new print_preview.Destination(
         id, parseType(json[CloudDestinationField.TYPE]), origin,
-        json[CloudDestinationField.DISPLAY_NAME],
-        tags.includes(RECENT_TAG) /*isRecent*/, connectionStatus,
+        json[CloudDestinationField.DISPLAY_NAME], connectionStatus,
         optionalParams);
     if (json.hasOwnProperty(CloudDestinationField.CAPABILITIES)) {
       cloudDest.capabilities = /** @type {!print_preview.Cdd} */ (
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js
index 0748439f..1d38102 100644
--- a/chrome/browser/resources/print_preview/data/destination.js
+++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -263,7 +263,6 @@
      * @param {!print_preview.DestinationOrigin} origin Origin of the
      *     destination.
      * @param {string} displayName Display name of the destination.
-     * @param {boolean} isRecent Whether the destination has been used recently.
      * @param {!print_preview.DestinationConnectionStatus} connectionStatus
      *     Connection status of the print destination.
      * @param {{tags: (Array<string>|undefined),
@@ -283,8 +282,7 @@
      *         }=} opt_params Optional
      *     parameters for the destination.
      */
-    constructor(
-        id, type, origin, displayName, isRecent, connectionStatus, opt_params) {
+    constructor(id, type, origin, displayName, connectionStatus, opt_params) {
       /**
        * ID of the destination.
        * @private {string}
@@ -310,12 +308,6 @@
       this.displayName_ = displayName || '';
 
       /**
-       * Whether the destination has been used recently.
-       * @private {boolean}
-       */
-      this.isRecent_ = isRecent;
-
-      /**
        * Tags associated with the destination.
        * @private {!Array<string>}
        */
@@ -459,18 +451,6 @@
       return this.displayName_;
     }
 
-    /** @return {boolean} Whether the destination has been used recently. */
-    get isRecent() {
-      return this.isRecent_;
-    }
-
-    /**
-     * @param {boolean} isRecent Whether the destination has been used recently.
-     */
-    set isRecent(isRecent) {
-      this.isRecent_ = isRecent;
-    }
-
     /**
      * @return {boolean} Whether the user owns the destination. Only applies to
      *     cloud-based destinations.
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js
index 8df823b2..bc5c9814 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -235,12 +235,6 @@
           print_preview.DestinationOrigin.LOCAL;
 
       /**
-       * The recent print destinations, set when the store is initialized.
-       * @private {!Array<!print_preview.RecentDestination>}
-       */
-      this.recentDestinations_ = [];
-
-      /**
        * Currently selected destination.
        * @private {print_preview.Destination}
        */
@@ -378,7 +372,6 @@
         return;
       }
 
-      this.recentDestinations_ = recentDestinations;
       const serializedDestination = {
         id: '',
         origin: this.platformOrigin_,
@@ -398,7 +391,6 @@
         const candidate = this.destinationMap_.get(
             print_preview.createRecentDestinationKey(destination));
         if (candidate != undefined) {
-          candidate.isRecent = true;
           if (!foundDestination && !this.useSystemDefaultAsDefault_) {
             this.selectDestination(candidate);
           }
@@ -507,7 +499,7 @@
             };
         this.selectedDestination_ = new print_preview.Destination(
             id, print_preview.DestinationType.LOCAL, origin,
-            serializedDestination.displayName, false /*isRecent*/,
+            serializedDestination.displayName,
             print_preview.DestinationConnectionStatus.ONLINE, params);
 
         if (serializedDestination.capabilities) {
@@ -698,7 +690,6 @@
 
       // Update and persist selected destination.
       this.selectedDestination_ = destination;
-      this.selectedDestination_.isRecent = true;
       // Adjust metrics.
       if (destination.cloudID &&
           this.destinations_.some(function(otherDestination) {
@@ -1103,12 +1094,6 @@
       const key = destination.key;
       const existingDestination = this.destinationMap_.get(key);
       if (existingDestination == undefined) {
-        destination.isRecent = destination.isRecent ||
-            this.recentDestinations_.some(function(recent) {
-              return (
-                  destination.id == recent.id &&
-                  destination.origin == recent.origin);
-            }, this);
         this.destinations_.push(destination);
         this.destinationMap_.set(key, destination);
         return true;
@@ -1135,7 +1120,7 @@
             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
             print_preview.DestinationType.LOCAL,
             print_preview.DestinationOrigin.LOCAL,
-            loadTimeData.getString('printToPDF'), false /*isRecent*/,
+            loadTimeData.getString('printToPDF'),
             print_preview.DestinationConnectionStatus.ONLINE));
       }
     }
diff --git a/chrome/browser/resources/print_preview/data/local_parsers.js b/chrome/browser/resources/print_preview/data/local_parsers.js
index e986f7c..9716c128 100644
--- a/chrome/browser/resources/print_preview/data/local_parsers.js
+++ b/chrome/browser/resources/print_preview/data/local_parsers.js
@@ -57,7 +57,7 @@
         destinationInfo.deviceName, print_preview.DestinationType.LOCAL,
         cr.isChromeOS ? print_preview.DestinationOrigin.CROS :
                         print_preview.DestinationOrigin.LOCAL,
-        destinationInfo.printerName, false /*isRecent*/,
+        destinationInfo.printerName,
         print_preview.DestinationConnectionStatus.ONLINE, options);
   }
 
@@ -71,7 +71,7 @@
     return new print_preview.Destination(
         destinationInfo.serviceName, print_preview.DestinationType.LOCAL,
         print_preview.DestinationOrigin.PRIVET, destinationInfo.name,
-        false /*isRecent*/, print_preview.DestinationConnectionStatus.ONLINE,
+        print_preview.DestinationConnectionStatus.ONLINE,
         {cloudID: destinationInfo.cloudID});
   }
 
@@ -90,8 +90,7 @@
     return new print_preview.Destination(
         destinationInfo.id, print_preview.DestinationType.LOCAL,
         print_preview.DestinationOrigin.EXTENSION, destinationInfo.name,
-        false /* isRecent */, print_preview.DestinationConnectionStatus.ONLINE,
-        {
+        print_preview.DestinationConnectionStatus.ONLINE, {
           description: destinationInfo.description || '',
           extensionId: destinationInfo.extensionId,
           extensionName: destinationInfo.extensionName || '',
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
index 73eca38..6d19d33 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
@@ -18,6 +18,7 @@
 #include "net/url_request/url_request_interceptor.h"
 #include "net/url_request/url_request_job.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 
 namespace net {
 class NetworkDelegate;
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index b06a19c..1d55e53 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -428,10 +428,14 @@
 }
 
 std::unique_ptr<base::DictionaryValue> ConvertSearchSuggestDataToDict(
-    const SearchSuggestData& data) {
+    const base::Optional<SearchSuggestData>& data) {
   auto result = std::make_unique<base::DictionaryValue>();
-  result->SetString("suggestionsHtml", data.suggestions_html);
-  result->SetString("suggestionsEndOfBodyScript", data.end_of_body_script);
+  if (data.has_value()) {
+    result->SetString("suggestionsHtml", data->suggestions_html);
+    result->SetString("suggestionsEndOfBodyScript", data->end_of_body_script);
+  } else {
+    result->SetString("suggestionsHtml", std::string());
+  }
   return result;
 }
 
@@ -1301,16 +1305,11 @@
     const content::URLDataSource::GotDataCallback& callback) {
   base::Optional<SearchSuggestData> data =
       search_suggest_service_->search_suggest_data();
-  if (!data.has_value()) {
-    callback.Run(nullptr);
-    return;
-  }
 
-  SearchSuggestData suggest_data = *data;
   search_suggest_service_->SuggestionsDisplayed();
   scoped_refptr<base::RefCountedString> result;
   std::string js;
-  base::JSONWriter::Write(*ConvertSearchSuggestDataToDict(suggest_data), &js);
+  base::JSONWriter::Write(*ConvertSearchSuggestDataToDict(data), &js);
   js = "var search_suggestions  = " + js + ";";
   result = base::RefCountedString::TakeString(&js);
   callback.Run(result);
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 3d8427d..158fcf1 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -1622,10 +1622,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SmartSessionRestoreTest, MAYBE_CorrectLoadingOrder) {
-  // TODO(https://crbug.com/923051): Flaky in single process mash.
-  if (features::IsSingleProcessMash())
-    return;
-
   const int activation_order[] = {4, 2, 5, 0, 3, 1};
   Profile* profile = browser()->profile();
 
diff --git a/chrome/browser/supervised_user/supervised_user_browsertest.cc b/chrome/browser/supervised_user/supervised_user_browsertest.cc
index 3bdf775..447a060 100644
--- a/chrome/browser/supervised_user/supervised_user_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_browsertest.cc
@@ -286,11 +286,11 @@
   DISALLOW_COPY_AND_ASSIGN(TabClosingObserver);
 };
 
-INSTANTIATE_TEST_CASE_P(, SupervisedUserTest, ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(, SupervisedUserTest, ::testing::Values(false, true));
 
-INSTANTIATE_TEST_CASE_P(,
-                        SupervisedUserBlockModeTest,
-                        ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(,
+                         SupervisedUserBlockModeTest,
+                         ::testing::Values(false, true));
 
 // Navigates to a blocked URL.
 IN_PROC_BROWSER_TEST_P(SupervisedUserBlockModeTest,
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
index 932e0cd..6e726536 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -120,9 +120,9 @@
 #endif
 }
 
-INSTANTIATE_TEST_CASE_P(,
-                        SupervisedUserNavigationThrottleTest,
-                        ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(,
+                         SupervisedUserNavigationThrottleTest,
+                         ::testing::Values(false, true));
 
 // Tests that navigating to a blocked page simply fails if there is no
 // SupervisedUserNavigationObserver.
@@ -198,9 +198,9 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {}
 };
 
-INSTANTIATE_TEST_CASE_P(,
-                        SupervisedUserNavigationThrottleNotSupervisedTest,
-                        ::testing::Values(false, true));
+INSTANTIATE_TEST_SUITE_P(,
+                         SupervisedUserNavigationThrottleNotSupervisedTest,
+                         ::testing::Values(false, true));
 
 IN_PROC_BROWSER_TEST_P(SupervisedUserNavigationThrottleNotSupervisedTest,
                        DontBlock) {
diff --git a/chrome/browser/ui/views/frame/taskbar_decorator_win.cc b/chrome/browser/taskbar/taskbar_decorator_win.cc
similarity index 74%
rename from chrome/browser/ui/views/frame/taskbar_decorator_win.cc
rename to chrome/browser/taskbar/taskbar_decorator_win.cc
index d8d16962..49f4046 100644
--- a/chrome/browser/ui/views/frame/taskbar_decorator_win.cc
+++ b/chrome/browser/taskbar/taskbar_decorator_win.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/views/frame/taskbar_decorator_win.h"
+#include "chrome/browser/taskbar/taskbar_decorator_win.h"
 
 #include <objbase.h>
 #include <shobjidl.h>
@@ -10,9 +10,15 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/task/post_task.h"
 #include "base/win/scoped_gdi_object.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/avatar_menu.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "skia/ext/image_operations.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -27,7 +33,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/views/win/hwnd_util.h"
 
-namespace chrome {
+namespace taskbar {
 
 namespace {
 
@@ -62,9 +68,8 @@
     DCHECK_GE(kOverlayIconSize, resized_height);
     // Since the target size is so small, we use our best resizer.
     SkBitmap sk_icon = skia::ImageOperations::Resize(
-        *bitmap.get(),
-        skia::ImageOperations::RESIZE_LANCZOS3,
-        kOverlayIconSize, resized_height);
+        *bitmap.get(), skia::ImageOperations::RESIZE_LANCZOS3, kOverlayIconSize,
+        resized_height);
 
     // Paint the resized icon onto a 16x16 canvas otherwise Windows will badly
     // hammer it to 16x16. We'll use a circular clip to be consistent with the
@@ -162,11 +167,48 @@
   // gfx::Image isn't thread safe.
   std::unique_ptr<SkBitmap> bitmap;
   if (image) {
-    bitmap.reset(new SkBitmap(
-        profiles::GetAvatarIconAsSquare(*image->ToSkBitmap(), 1)));
+    bitmap.reset(
+        new SkBitmap(profiles::GetAvatarIconAsSquare(*image->ToSkBitmap(), 1)));
   }
 
   PostSetOverlayIcon(hwnd, std::move(bitmap));
 }
 
-}  // namespace chrome
+void UpdateTaskbarDecoration(Profile* profile, gfx::NativeWindow window) {
+  if (profile->IsGuestSession() ||
+      // Browser process and profile manager may be null in tests.
+      (g_browser_process && g_browser_process->profile_manager() &&
+       g_browser_process->profile_manager()
+               ->GetProfileAttributesStorage()
+               .GetNumberOfProfiles() <= 1)) {
+    taskbar::DrawTaskbarDecoration(window, nullptr);
+    return;
+  }
+
+  // We need to draw the taskbar decoration. Even though we have an icon on the
+  // window's relaunch details, we draw over it because the user may have
+  // pinned the badge-less Chrome shortcut which will cause Windows to ignore
+  // the relaunch details.
+  // TODO(calamity): ideally this should not be necessary but due to issues
+  // with the default shortcut being pinned, we add the runtime badge for
+  // safety. See crbug.com/313800.
+  gfx::Image decoration;
+  AvatarMenu::ImageLoadStatus status =
+      AvatarMenu::GetImageForMenuButton(profile->GetPath(), &decoration);
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "Profile.AvatarLoadStatus", status,
+      static_cast<int>(AvatarMenu::ImageLoadStatus::MAX) + 1);
+
+  // If the user is using a Gaia picture and the picture is still being loaded,
+  // wait until the load finishes. This taskbar decoration will be triggered
+  // again upon the finish of the picture load.
+  if (status == AvatarMenu::ImageLoadStatus::LOADING ||
+      status == AvatarMenu::ImageLoadStatus::PROFILE_DELETED) {
+    return;
+  }
+
+  taskbar::DrawTaskbarDecoration(window, &decoration);
+}
+
+}  // namespace taskbar
diff --git a/chrome/browser/taskbar/taskbar_decorator_win.h b/chrome/browser/taskbar/taskbar_decorator_win.h
new file mode 100644
index 0000000..3ed6b46
--- /dev/null
+++ b/chrome/browser/taskbar/taskbar_decorator_win.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium 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_TASKBAR_TASKBAR_DECORATOR_WIN_H_
+#define CHROME_BROWSER_TASKBAR_TASKBAR_DECORATOR_WIN_H_
+
+#include <string>
+
+#include "ui/gfx/native_widget_types.h"
+
+class Profile;
+
+namespace gfx {
+class Image;
+}
+
+namespace taskbar {
+
+// Add a numeric badge to the taskbar.
+void DrawTaskbarDecorationString(gfx::NativeWindow window,
+                                 const std::string& content);
+
+// Draws a scaled version of the avatar in |image| on the taskbar button
+// associated with top level, visible |window|. Currently only implemented
+// for Windows 7 and above.
+void DrawTaskbarDecoration(gfx::NativeWindow window, const gfx::Image* image);
+
+// Draws a taskbar icon for non-guest sessions, erases it otherwise. Note: This
+// will clear any badge that has been set on the window.
+void UpdateTaskbarDecoration(Profile* profile, gfx::NativeWindow window);
+
+}  // namespace taskbar
+
+#endif  // CHROME_BROWSER_TASKBAR_TASKBAR_DECORATOR_WIN_H_
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index c209374..3364625e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2192,8 +2192,6 @@
       "views/frame/native_browser_frame_factory_aurawin.cc",
       "views/frame/system_menu_insertion_delegate_win.cc",
       "views/frame/system_menu_insertion_delegate_win.h",
-      "views/frame/taskbar_decorator_win.cc",
-      "views/frame/taskbar_decorator_win.h",
       "views/frame/windows_10_caption_button.cc",
       "views/frame/windows_10_caption_button.h",
       "views/network_profile_bubble_view.cc",
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
index 41c3ecf..e1d87fd 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
@@ -16,6 +16,7 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "ui/keyboard/public/keyboard_config.mojom.h"
 #include "url/gurl.h"
 
 class ChromeKeyboardWebContents;
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index 312fd9a..63f694b3 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/chromeos/login/discover/discover_window_manager.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/system_web_app_manager.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -48,11 +49,22 @@
 // The tab-index flag for browser window menu items that do not specify a tab.
 constexpr uint16_t kNoTab = std::numeric_limits<uint16_t>::max();
 
-bool IsSettingsBrowser(Browser* browser) {
+bool IsManagedBrowser(Browser* browser) {
+  // System Web Apps use the chrome://scheme and rely on the Bookmark App path
+  // to associate WebContents with ShelfIDs.
+  if (web_app::SystemWebAppManager::IsEnabled())
+    return false;
+
   // Normally this test is sufficient. TODO(stevenjb): Replace this with a
   // better mechanism (Settings WebUI or Browser type).
   if (chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme))
     return true;
+
+  if (chromeos::DiscoverWindowManager::GetInstance()->IsDiscoverBrowser(
+          browser)) {
+    return true;
+  }
+
   // If a settings window navigates away from a kChromeUIScheme (e.g. after a
   // crash), the above may not be true, so also test against the known list
   // of settings browsers (which will not be valid during chrome::Navigate
@@ -122,9 +134,7 @@
 
   // Settings and Discover browsers have their own item; all others should be
   // represented.
-  return !IsSettingsBrowser(browser) &&
-         !chromeos::DiscoverWindowManager::GetInstance()->IsDiscoverBrowser(
-             browser);
+  return !IsManagedBrowser(browser);
 }
 
 // Gets a list of active browsers.
@@ -202,7 +212,7 @@
   // The browser window may not exist in unit tests.
   if (!browser || !browser->window() || !browser->window()->GetNativeWindow() ||
       !multi_user_util::IsProfileFromActiveUser(browser->profile()) ||
-      IsSettingsBrowser(browser)) {
+      IsManagedBrowser(browser)) {
     return;
   }
 
diff --git a/chrome/browser/ui/ash/launcher/browser_status_monitor.cc b/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
index fe6245ba..0e9ead3 100644
--- a/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
+++ b/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
@@ -271,11 +271,6 @@
   webcontents_to_observer_map_.erase(contents);
 }
 
-ash::ShelfID BrowserStatusMonitor::GetShelfIDForWebContents(
-    content::WebContents* contents) {
-  return launcher_controller_->GetShelfIDForWebContents(contents);
-}
-
 void BrowserStatusMonitor::SetShelfIDForBrowserWindowContents(
     Browser* browser,
     content::WebContents* web_contents) {
diff --git a/chrome/browser/ui/ash/launcher/browser_status_monitor.h b/chrome/browser/ui/ash/launcher/browser_status_monitor.h
index 329a8177..e8083c62 100644
--- a/chrome/browser/ui/ash/launcher/browser_status_monitor.h
+++ b/chrome/browser/ui/ash/launcher/browser_status_monitor.h
@@ -96,9 +96,6 @@
   // Remove LocalWebContentsObserver for |contents|.
   void RemoveWebContentsObserver(content::WebContents* contents);
 
-  // Returns the ShelfID for |contents|.
-  ash::ShelfID GetShelfIDForWebContents(content::WebContents* contents);
-
   // Sets the shelf id for browsers represented by the browser shortcut item.
   void SetShelfIDForBrowserWindowContents(Browser* browser,
                                           content::WebContents* web_contents);
diff --git a/chrome/browser/ui/ash/test_ime_controller.cc b/chrome/browser/ui/ash/test_ime_controller.cc
index a97ea5d0..a49f01b 100644
--- a/chrome/browser/ui/ash/test_ime_controller.cc
+++ b/chrome/browser/ui/ash/test_ime_controller.cc
@@ -8,8 +8,6 @@
 #include <string>
 #include <utility>
 
-#include "ash/public/interfaces/ime_controller.mojom.h"
-
 TestImeController::TestImeController() : binding_(this) {}
 TestImeController::~TestImeController() = default;
 
diff --git a/chrome/browser/ui/ash/test_ime_controller.h b/chrome/browser/ui/ash/test_ime_controller.h
index 6f8f3af..205d504c 100644
--- a/chrome/browser/ui/ash/test_ime_controller.h
+++ b/chrome/browser/ui/ash/test_ime_controller.h
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "ash/public/interfaces/ime_controller.mojom.h"
+#include "ash/public/interfaces/ime_info.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 class TestImeController : ash::mojom::ImeController {
diff --git a/chrome/browser/ui/views/badge_service_delegate_impl.cc b/chrome/browser/ui/views/badge_service_delegate_impl.cc
index 86cfc4e..ce72410 100644
--- a/chrome/browser/ui/views/badge_service_delegate_impl.cc
+++ b/chrome/browser/ui/views/badge_service_delegate_impl.cc
@@ -10,13 +10,12 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/strings/grit/ui_strings.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/ui/views/frame/taskbar_decorator_win.h"
+#include "chrome/browser/taskbar/taskbar_decorator_win.h"
 #elif defined(OS_MACOSX)
 #include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
@@ -64,7 +63,7 @@
 #if defined(OS_WIN)
   Browser* browser = chrome::FindBrowserWithWebContents(contents);
   auto* window = browser->window()->GetNativeWindow();
-  chrome::DrawTaskbarDecorationString(window, GetBadgeString(badge_content));
+  taskbar::DrawTaskbarDecorationString(window, GetBadgeString(badge_content));
 #elif defined(OS_MACOSX)
   SetAppShimBadgeLabel(contents, GetBadgeString(badge_content));
 #endif
@@ -73,11 +72,11 @@
 void ClearBadgeImpl(content::WebContents* contents) {
 #if defined(OS_WIN)
   Browser* browser = chrome::FindBrowserWithWebContents(contents);
-  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
 
   // Restore the decoration to whatever it is naturally (either nothing or a
   // profile picture badge).
-  browser_view->frame()->GetFrameView()->UpdateTaskbarDecoration();
+  taskbar::UpdateTaskbarDecoration(browser->profile(),
+                                   browser->window()->GetNativeWindow());
 #elif defined(OS_MACOSX)
   SetAppShimBadgeLabel(contents, "");
 #endif
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 b84e89db..943a1f0 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
@@ -32,7 +32,7 @@
 #include "ui/views/window/hit_test_utils.h"
 
 #if defined(OS_WIN)
-#include "chrome/browser/ui/views/frame/taskbar_decorator_win.h"
+#include "chrome/browser/taskbar/taskbar_decorator_win.h"
 #endif
 
 // static
@@ -241,45 +241,6 @@
   SchedulePaint();
 }
 
-void BrowserNonClientFrameView::UpdateTaskbarDecoration() {
-#if defined(OS_WIN)
-  if (browser_view_->browser()->profile()->IsGuestSession() ||
-      // Browser process and profile manager may be null in tests.
-      (g_browser_process && g_browser_process->profile_manager() &&
-       g_browser_process->profile_manager()
-               ->GetProfileAttributesStorage()
-               .GetNumberOfProfiles() <= 1)) {
-    chrome::DrawTaskbarDecoration(frame_->GetNativeWindow(), nullptr);
-    return;
-  }
-
-  // We need to draw the taskbar decoration. Even though we have an icon on the
-  // window's relaunch details, we draw over it because the user may have
-  // pinned the badge-less Chrome shortcut which will cause Windows to ignore
-  // the relaunch details.
-  // TODO(calamity): ideally this should not be necessary but due to issues
-  // with the default shortcut being pinned, we add the runtime badge for
-  // safety. See crbug.com/313800.
-  gfx::Image decoration;
-  AvatarMenu::ImageLoadStatus status = AvatarMenu::GetImageForMenuButton(
-      browser_view_->browser()->profile()->GetPath(), &decoration);
-
-  UMA_HISTOGRAM_ENUMERATION(
-      "Profile.AvatarLoadStatus", status,
-      static_cast<int>(AvatarMenu::ImageLoadStatus::MAX) + 1);
-
-  // If the user is using a Gaia picture and the picture is still being loaded,
-  // wait until the load finishes. This taskbar decoration will be triggered
-  // again upon the finish of the picture load.
-  if (status == AvatarMenu::ImageLoadStatus::LOADING ||
-      status == AvatarMenu::ImageLoadStatus::PROFILE_DELETED) {
-    return;
-  }
-
-  chrome::DrawTaskbarDecoration(frame_->GetNativeWindow(), &decoration);
-#endif
-}
-
 bool BrowserNonClientFrameView::IsSingleTabModeAvailable() const {
   // Single-tab mode is only available in when the window is active.  The
   // special color we use won't be visible if there's a frame image, but since
@@ -432,12 +393,18 @@
 
 void BrowserNonClientFrameView::OnProfileAvatarChanged(
     const base::FilePath& profile_path) {
-  UpdateTaskbarDecoration();
+#if defined(OS_WIN)
+  taskbar::UpdateTaskbarDecoration(browser_view()->browser()->profile(),
+                                   frame_->GetNativeWindow());
+#endif
 }
 
 void BrowserNonClientFrameView::OnProfileHighResAvatarLoaded(
     const base::FilePath& profile_path) {
-  UpdateTaskbarDecoration();
+#if defined(OS_WIN)
+  taskbar::UpdateTaskbarDecoration(browser_view()->browser()->profile(),
+                                   frame_->GetNativeWindow());
+#endif
 }
 
 void BrowserNonClientFrameView::MaybeObserveTabstrip() {
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 84df4fe..82aa86f 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
@@ -139,9 +139,6 @@
     return hosted_app_button_container_;
   }
 
-  // Draws a taskbar icon for non-guest sessions, erases it otherwise.
-  void UpdateTaskbarDecoration();
-
  protected:
   // Whether the frame should be painted with theming.
   // By default, tabbed browser windows are themed but popup and app windows are
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 7848560..9299322d 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -188,7 +188,7 @@
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
-#include "chrome/browser/ui/views/frame/taskbar_decorator_win.h"
+#include "chrome/browser/taskbar/taskbar_decorator_win.h"
 #include "chrome/browser/win/jumplist.h"
 #include "chrome/browser/win/jumplist_factory.h"
 #include "ui/gfx/color_palette.h"
diff --git a/chrome/browser/ui/views/frame/taskbar_decorator_win.h b/chrome/browser/ui/views/frame/taskbar_decorator_win.h
deleted file mode 100644
index e514388b..0000000
--- a/chrome/browser/ui/views/frame/taskbar_decorator_win.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_TASKBAR_DECORATOR_WIN_H_
-#define CHROME_BROWSER_UI_VIEWS_FRAME_TASKBAR_DECORATOR_WIN_H_
-
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Image;
-}
-
-namespace chrome {
-
-// Add a numeric badge to the taskbar.
-void DrawTaskbarDecorationString(gfx::NativeWindow window,
-                                 const std::string& content);
-
-// Draws a scaled version of the avatar in |image| on the taskbar button
-// associated with top level, visible |window|. Currently only implemented
-// for Windows 7 and above.
-void DrawTaskbarDecoration(gfx::NativeWindow window, const gfx::Image* image);
-}  // namespace chrome
-
-#endif  // CHROME_BROWSER_UI_VIEWS_FRAME_TASKBAR_DECORATOR_WIN_H_
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
index c0dfec5..43a2410 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -185,7 +185,7 @@
               request_->spec(), request_->state(), this,
               request_->web_contents(), GetProfile(), url, std::move(callback)),
           &controller_map_),
-      /* animate = */ true);
+      /* animate = */ !request_->skipped_payment_request_ui());
   HideProcessingSpinner();
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 660b87c..263ad4ec 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -97,6 +97,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -309,6 +310,11 @@
   return policy_manager && policy_manager->IsRemoraRequisition();
 }
 
+void DisablePolymer2(content::URLDataSource* shared_source) {
+  if (shared_source)
+    shared_source->DisablePolymer2ForHost(chrome::kChromeUIOobeHost);
+}
+
 }  // namespace
 
 // static
@@ -501,6 +507,17 @@
       CreateOobeUIDataSource(localized_strings, display_type_);
   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source);
 
+  // If allowed, request that the shared resources send this page Polymer 1
+  // resources instead of Polymer 2.
+  // TODO (https://crbug.com/739611): Remove this exception by migrating to
+  // Polymer 2.
+  if (base::FeatureList::IsEnabled(features::kWebUIPolymer2Exceptions)) {
+    content::URLDataSource::GetSourceForURL(
+        Profile::FromWebUI(web_ui),
+        GURL("chrome://resources/polymer/v1_0/polymer/polymer.html"),
+        base::BindOnce(DisablePolymer2));
+  }
+
   AddHandlerToRegistry(base::BindRepeating(&OobeUI::BindMultiDeviceSetup,
                                            base::Unretained(this)));
   AddHandlerToRegistry(base::BindRepeating(
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h
index e06e6344..b75aac8 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -14,6 +14,7 @@
 
 namespace chromeos {
 
+// WebUI controller for chrome://network debugging page.
 class NetworkUI : public content::WebUIController {
  public:
   explicit NetworkUI(content::WebUI* web_ui);
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index d5dcbf49..6e577089 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -382,7 +382,7 @@
 
 #if defined(OS_CHROMEOS)
   // Add the System Web App resources for Settings.
-  if (web_app::SystemWebAppManager::ShouldEnableForProfile(profile)) {
+  if (web_app::SystemWebAppManager::IsEnabled()) {
     html_source->AddResourcePath("icon-192.png", IDR_SETTINGS_LOGO_192);
     html_source->AddResourcePath("pwa.html", IDR_PWA_HTML);
 #if BUILDFLAG(OPTIMIZE_WEBUI)
diff --git a/chrome/browser/usb/usb_chooser_context.h b/chrome/browser/usb/usb_chooser_context.h
index ffe6b11b..aed3fa3 100644
--- a/chrome/browser/usb/usb_chooser_context.h
+++ b/chrome/browser/usb/usb_chooser_context.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/permissions/chooser_context_base.h"
 #include "chrome/browser/usb/usb_policy_allowed_devices.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
+#include "device/usb/public/mojom/device_manager_client.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 
 class UsbChooserContext : public ChooserContextBase,
diff --git a/chrome/browser/usb/usb_chooser_context_mock_device_observer.cc b/chrome/browser/usb/usb_chooser_context_mock_device_observer.cc
index 6672d46..5c63ab3 100644
--- a/chrome/browser/usb/usb_chooser_context_mock_device_observer.cc
+++ b/chrome/browser/usb/usb_chooser_context_mock_device_observer.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/usb/usb_chooser_context_mock_device_observer.h"
 
+#include "device/usb/public/mojom/device.mojom.h"
+
 MockDeviceObserver::MockDeviceObserver() {}
 
 MockDeviceObserver::~MockDeviceObserver() {}
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc
index 9e6b132..2fffee4 100644
--- a/chrome/browser/usb/usb_chooser_controller.cc
+++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -20,6 +20,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "device/usb/public/cpp/usb_utils.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc
index e02ce0b9..dfa6dc1 100644
--- a/chrome/browser/usb/usb_chooser_controller_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/public/test/web_contents_tester.h"
 #include "device/usb/public/cpp/fake_usb_device_manager.h"
 #include "device/usb/public/mojom/device.mojom.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/usb/usb_policy_allowed_devices.cc b/chrome/browser/usb/usb_policy_allowed_devices.cc
index 1867f15..397ee1f 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices.cc
+++ b/chrome/browser/usb/usb_policy_allowed_devices.cc
@@ -12,6 +12,7 @@
 #include "base/values.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "device/usb/public/mojom/device.mojom.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 
 namespace {
diff --git a/chrome/browser/usb/web_usb_chooser.cc b/chrome/browser/usb/web_usb_chooser.cc
index a636f534..09d01f4 100644
--- a/chrome/browser/usb/web_usb_chooser.cc
+++ b/chrome/browser/usb/web_usb_chooser.cc
@@ -13,6 +13,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 
 WebUsbChooser::WebUsbChooser(content::RenderFrameHost* render_frame_host)
     : render_frame_host_(render_frame_host) {
diff --git a/chrome/browser/usb/web_usb_detector.h b/chrome/browser/usb/web_usb_detector.h
index 96ad098..b53a780 100644
--- a/chrome/browser/usb/web_usb_detector.h
+++ b/chrome/browser/usb/web_usb_detector.h
@@ -9,7 +9,9 @@
 
 #include "base/macros.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
+#include "device/usb/public/mojom/device_manager_client.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "url/gurl.h"
 
 class WebUsbDetector : public device::mojom::UsbDeviceManagerClient {
  public:
diff --git a/chrome/browser/usb/web_usb_service_impl.cc b/chrome/browser/usb/web_usb_service_impl.cc
index 268f397db..586a6c6 100644
--- a/chrome/browser/usb/web_usb_service_impl.cc
+++ b/chrome/browser/usb/web_usb_service_impl.cc
@@ -14,6 +14,8 @@
 #include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/browser/usb/usb_tab_helper.h"
 #include "content/public/browser/browser_thread.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
+#include "media/mojo/interfaces/remoting_common.mojom.h"
 
 WebUsbServiceImpl::WebUsbServiceImpl(
     content::RenderFrameHost* render_frame_host,
diff --git a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_browsertest.cc
index 2ab4890..b5615984 100644
--- a/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/bookmark_apps/system_web_app_manager_browsertest.cc
@@ -145,7 +145,7 @@
     content::BrowserContext* context) {
   Profile* profile = Profile::FromBrowserContext(context);
 
-  if (!SystemWebAppManager::ShouldEnableForProfile(profile))
+  if (!SystemWebAppManager::IsEnabled())
     return nullptr;
 
   auto provider = std::make_unique<TestWebAppProvider>(profile);
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index 0fa6f80..52532435 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -51,14 +51,13 @@
 }
 
 // static
-bool SystemWebAppManager::ShouldEnableForProfile(Profile* profile) {
-  return AreWebAppsEnabled(profile) &&
-         base::FeatureList::IsEnabled(features::kSystemWebApps);
+bool SystemWebAppManager::IsEnabled() {
+  return base::FeatureList::IsEnabled(features::kSystemWebApps);
 }
 
 void SystemWebAppManager::StartAppInstallation() {
   std::vector<GURL> urls_to_install;
-  if (ShouldEnableForProfile(profile_)) {
+  if (AreWebAppsEnabled(profile_) && IsEnabled()) {
     // Skipping this will uninstall all System Apps currently installed.
     urls_to_install = CreateSystemWebApps();
   }
diff --git a/chrome/browser/web_applications/system_web_app_manager.h b/chrome/browser/web_applications/system_web_app_manager.h
index 615b30d..9da5b83 100644
--- a/chrome/browser/web_applications/system_web_app_manager.h
+++ b/chrome/browser/web_applications/system_web_app_manager.h
@@ -27,7 +27,7 @@
 
   void Start();
 
-  static bool ShouldEnableForProfile(Profile* profile);
+  static bool IsEnabled();
 
  protected:
   // Overridden in tests.
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index a3203da..ca214540 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -209,7 +209,7 @@
 // Determines whether out of scope pages in the hosted app will use the
 // custom tab UI.
 const base::Feature kDesktopPWAsCustomTabUI{"DesktopPWAsCustomTabUI",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Determines whether in scope requests are always opened in the same window.
 const base::Feature kDesktopPWAsStayInWindow{"DesktopPWAsStayInWindow",
diff --git a/chrome/services/app_service/app_service_impl.cc b/chrome/services/app_service/app_service_impl.cc
index dffd2af..5c62ace7 100644
--- a/chrome/services/app_service/app_service_impl.cc
+++ b/chrome/services/app_service/app_service_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "chrome/services/app_service/public/mojom/types.mojom.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
 namespace {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ed862d53..309436d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1775,6 +1775,8 @@
         "../browser/chromeos/login/session_login_browsertest.cc",
         "../browser/chromeos/login/signin/device_id_browsertest.cc",
         "../browser/chromeos/login/signin/oauth2_browsertest.cc",
+        "../browser/chromeos/login/test/hid_controller_mixin.cc",
+        "../browser/chromeos/login/test/hid_controller_mixin.h",
         "../browser/chromeos/login/test/https_forwarder.cc",
         "../browser/chromeos/login/test/https_forwarder.h",
         "../browser/chromeos/login/test/oobe_base_test.cc",
diff --git a/chrome/test/chromedriver/session.cc b/chrome/test/chromedriver/session.cc
index bb1c357..a4327f0 100644
--- a/chrome/test/chromedriver/session.cc
+++ b/chrome/test/chromedriver/session.cc
@@ -29,6 +29,28 @@
       frame_id(frame_id),
       chromedriver_frame_id(chromedriver_frame_id) {}
 
+InputCancelListEntry::InputCancelListEntry(base::DictionaryValue* input_state,
+                                           const MouseEvent* mouse_event,
+                                           const TouchEvent* touch_event,
+                                           const KeyEvent* key_event)
+    : input_state(input_state) {
+  if (mouse_event != nullptr) {
+    this->mouse_event = std::make_unique<MouseEvent>(*mouse_event);
+    this->mouse_event->type = kReleasedMouseEventType;
+  } else if (touch_event != nullptr) {
+    this->touch_event = std::make_unique<TouchEvent>(*touch_event);
+    this->touch_event->type = kTouchEnd;
+  } else if (key_event != nullptr) {
+    this->key_event = std::make_unique<KeyEvent>(*key_event);
+    this->key_event->type = kKeyUpEventType;
+  }
+}
+
+InputCancelListEntry::InputCancelListEntry(InputCancelListEntry&& other) =
+    default;
+
+InputCancelListEntry::~InputCancelListEntry() = default;
+
 // The default timeout values came from W3C spec.
 const base::TimeDelta Session::kDefaultImplicitWaitTimeout =
     base::TimeDelta::FromSeconds(0);
diff --git a/chrome/test/chromedriver/session.h b/chrome/test/chromedriver/session.h
index bcbbbad..2a22061 100644
--- a/chrome/test/chromedriver/session.h
+++ b/chrome/test/chromedriver/session.h
@@ -49,6 +49,20 @@
   std::string chromedriver_frame_id;
 };
 
+struct InputCancelListEntry {
+  InputCancelListEntry(base::DictionaryValue* input_state,
+                       const MouseEvent* mouse_event,
+                       const TouchEvent* touch_event,
+                       const KeyEvent* key_event);
+  InputCancelListEntry(InputCancelListEntry&& other);
+  ~InputCancelListEntry();
+
+  base::DictionaryValue* input_state;
+  std::unique_ptr<MouseEvent> mouse_event;
+  std::unique_ptr<TouchEvent> touch_event;
+  std::unique_ptr<KeyEvent> key_event;
+};
+
 struct Session {
   static const base::TimeDelta kDefaultImplicitWaitTimeout;
   static const base::TimeDelta kDefaultPageLoadTimeout;
@@ -82,6 +96,8 @@
   // Map between input id and input source state for the corresponding input
   // source. One entry for each item in active_input_sources
   base::DictionaryValue input_state_table;
+  // List of actions for Release Actions command.
+  std::vector<InputCancelListEntry> input_cancel_list;
   // List of |FrameInfo|s for each frame to the current target frame from the
   // first frame element in the root document. If target frame is window.top,
   // this list will be empty.
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc
index 7fa9c24f..eab685d 100644
--- a/chrome/test/chromedriver/window_commands.cc
+++ b/chrome/test/chromedriver/window_commands.cc
@@ -893,6 +893,13 @@
   std::list<MouseEvent> events;
   events.push_back(
       MouseEvent(kPressedMouseEventType, button, session->mouse_position.x,
+                 session->mouse_position.y, session->sticky_modifiers, 0, 1));
+  events.push_back(
+      MouseEvent(kReleasedMouseEventType, button, session->mouse_position.x,
+                 session->mouse_position.y, session->sticky_modifiers,
+                 MouseButtonToButtons(button), 1));
+  events.push_back(
+      MouseEvent(kPressedMouseEventType, button, session->mouse_position.x,
                  session->mouse_position.y, session->sticky_modifiers, 0, 2));
   events.push_back(
       MouseEvent(kReleasedMouseEventType, button, session->mouse_position.x,
@@ -1243,6 +1250,7 @@
   std::vector<std::vector<MouseEvent>> mouse_events_list;
   std::vector<std::vector<TouchEvent>> touch_events_list;
   std::vector<std::vector<KeyEvent>> key_events_list;
+  std::vector<base::DictionaryValue*> key_input_states;
   size_t longest_mouse_list_size = 0;
   size_t longest_touch_list_size = 0;
   size_t longest_key_list_size = 0;
@@ -1254,6 +1262,13 @@
     DCHECK(actions);
     action_sequence->GetString("sourceType", &type);
 
+    std::string id;
+    action_sequence->GetString("id", &id);
+
+    base::DictionaryValue* input_state;
+    if (!session->input_state_table.GetDictionary(id, &input_state))
+      return Status(kUnknownError, "missing input state");
+
     // key actions
     if (type == "key") {
       KeyEventBuilder builder;
@@ -1263,12 +1278,6 @@
         actions->GetDictionary(j, &action);
         std::string subtype;
         action->GetString("subtype", &subtype);
-        std::string id;
-        action->GetString("id", &id);
-
-        base::DictionaryValue* input_state;
-        if (!session->input_state_table.GetDictionary(id, &input_state))
-          return Status(kUnknownError, "missing input state");
 
         if (subtype == "pause") {
           key_events.push_back(builder.SetType(kPauseEventType)->Build());
@@ -1283,6 +1292,7 @@
       longest_key_list_size =
           std::max(key_events.size(), longest_key_list_size);
       key_events_list.push_back(key_events);
+      key_input_states.push_back(input_state);
     } else if (type == "pointer") {
       std::string pointer_type;
       action_sequence->GetString("pointerType", &pointer_type);
@@ -1434,7 +1444,12 @@
     for (size_t j = 0; j < key_events_list.size(); j++) {
       if (i < key_events_list[j].size() &&
           key_events_list[j][i].type != kPauseEventType) {
-        dispatch_key_events.push_back(key_events_list[j][i]);
+        const KeyEvent& event = key_events_list[j][i];
+        dispatch_key_events.push_back(event);
+        if (event.type == kKeyDownEventType) {
+          session->input_cancel_list.emplace_back(key_input_states[j], nullptr,
+                                                  nullptr, &event);
+        }
       }
     }
     if (dispatch_key_events.size() > 0) {
@@ -1455,8 +1470,21 @@
                              const base::DictionaryValue& params,
                              std::unique_ptr<base::Value>* value,
                              Timeout* timeout) {
-  // TODO(https://crbug.com/chromedriver/1897): Process "input cancel list".
+  // TODO(https://crbug.com/chromedriver/1897): Process "input cancel list" for
+  // mouse and touch events.
+  for (auto it = session->input_cancel_list.rbegin();
+       it != session->input_cancel_list.rend(); ++it) {
+    if (it->key_event) {
+      base::DictionaryValue* pressed;
+      it->input_state->GetDictionary("pressed", &pressed);
+      if (!pressed->HasKey(it->key_event->key))
+        continue;
+      web_view->DispatchKeyEvents({*it->key_event});
+      pressed->Remove(it->key_event->key, nullptr);
+    }
+  }
 
+  session->input_cancel_list.clear();
   session->input_state_table.Clear();
   session->active_input_sources.Clear();
 
diff --git a/chrome/test/data/webui/print_preview/advanced_dialog_test.js b/chrome/test/data/webui/print_preview/advanced_dialog_test.js
index 7db075e..4cc49a8 100644
--- a/chrome/test/data/webui/print_preview/advanced_dialog_test.js
+++ b/chrome/test/data/webui/print_preview/advanced_dialog_test.js
@@ -32,7 +32,6 @@
       destination = new print_preview.Destination(
           printerId, print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, printerName,
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       PolymerTest.clearBody();
       dialog = document.createElement('print-preview-advanced-dialog');
diff --git a/chrome/test/data/webui/print_preview/destination_item_test.js b/chrome/test/data/webui/print_preview/destination_item_test.js
index be23bad..124e4c01 100644
--- a/chrome/test/data/webui/print_preview/destination_item_test.js
+++ b/chrome/test/data/webui/print_preview/destination_item_test.js
@@ -32,7 +32,6 @@
       item.destination = new print_preview.Destination(
           printerId, print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, printerName,
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       item.searchQuery = null;
       document.body.appendChild(item);
@@ -64,7 +63,6 @@
       item.destination = new print_preview.Destination(
           printerId, print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, printerName,
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.OFFLINE,
           {lastAccessTime: twoMonthsAgo.getTime()});
 
@@ -124,8 +122,7 @@
       item.destination = new print_preview.Destination(
           printerId, print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, printerName,
-          true /* isRecent */, print_preview.DestinationConnectionStatus.ONLINE,
-          params);
+          print_preview.DestinationConnectionStatus.ONLINE, params);
       item.searchQuery = /(ABC)/i;
 
       // No highlighting on name.
diff --git a/chrome/test/data/webui/print_preview/destination_list_test.js b/chrome/test/data/webui/print_preview/destination_list_test.js
index 53a1e0e..ce61011c 100644
--- a/chrome/test/data/webui/print_preview/destination_list_test.js
+++ b/chrome/test/data/webui/print_preview/destination_list_test.js
@@ -21,30 +21,27 @@
       const destinations = [
         new print_preview.Destination(
             'id1', print_preview.DestinationType.LOCAL,
-            print_preview.DestinationOrigin.LOCAL, 'One', true /* isRecent */,
+            print_preview.DestinationOrigin.LOCAL, 'One',
             print_preview.DestinationConnectionStatus.ONLINE,
             {description: 'ABC'}),
         new print_preview.Destination(
             'id2', print_preview.DestinationType.LOCAL,
-            print_preview.DestinationOrigin.LOCAL, 'Two', true /* isRecent */,
+            print_preview.DestinationOrigin.LOCAL, 'Two',
             print_preview.DestinationConnectionStatus.ONLINE,
             {description: 'XYZ'}),
         new print_preview.Destination(
             'id3', print_preview.DestinationType.GOOGLE,
             print_preview.DestinationOrigin.COOKIES, 'Three',
-            true /* isRecent */,
             print_preview.DestinationConnectionStatus.ONLINE,
             {description: 'ABC', tags: ['__cp__location=123']}),
         new print_preview.Destination(
             'id4', print_preview.DestinationType.GOOGLE,
             print_preview.DestinationOrigin.COOKIES, 'Four',
-            true /* isRecent */,
             print_preview.DestinationConnectionStatus.ONLINE,
             {description: 'XYZ', tags: ['__cp__location=123']}),
         new print_preview.Destination(
             'id5', print_preview.DestinationType.GOOGLE,
             print_preview.DestinationOrigin.COOKIES, 'Five',
-            true /* isRecent */,
             print_preview.DestinationConnectionStatus.ONLINE,
             {description: 'XYZ', tags: ['__cp__location=123']})
       ];
diff --git a/chrome/test/data/webui/print_preview/destination_select_test.js b/chrome/test/data/webui/print_preview/destination_select_test.js
index 62b3102..c5f7cdd 100644
--- a/chrome/test/data/webui/print_preview/destination_select_test.js
+++ b/chrome/test/data/webui/print_preview/destination_select_test.js
@@ -124,7 +124,7 @@
     /**
      * Tests that if the user has multiple valid recent destination the most
      * recent destination is automatically reselected and the remaining
-     * destinations are marked as recent in the store.
+     * destinations are prefetched.
      */
     test(assert(TestNames.MultipleRecentDestinations), function() {
       const recentDestinations = destinations.slice(0, 3).map(
@@ -144,11 +144,6 @@
             assertEquals('ID1', page.destination_.id);
             return assertPrinterDisplay('One');
           })
-          .then(() => {
-            // Load all local destinations.
-            page.destinationStore_.startLoadAllDestinations();
-            return nativeLayer.whenCalled('getPrinters');
-          })
           .then(function() {
             // Verify the correct printers are marked as recent in the store.
             const reportedPrinters = page.destinationStore_.destinations();
@@ -156,8 +151,7 @@
               const match = reportedPrinters.find((reportedPrinter) => {
                 return reportedPrinter.id == destination.id;
               });
-              assertFalse(typeof match === 'undefined');
-              assertEquals(index < 3, match.isRecent);
+              assertEquals(index >= 3, typeof match === 'undefined');
             });
           });
     });
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js
index 98a9b92..4e5e315d 100644
--- a/chrome/test/data/webui/print_preview/destination_settings_test.js
+++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -99,8 +99,7 @@
       // is enabled.
       destinationSettings.destination = new print_preview.Destination(
           'FooDevice', print_preview.DestinationType.LOCAL, getLocalOrigin(),
-          'FooName', true /* isRecent */,
-          print_preview.DestinationConnectionStatus.ONLINE);
+          'FooName', print_preview.DestinationConnectionStatus.ONLINE);
       destinationSettings.recentDestinations = [
         print_preview.makeRecentDestination(destinationSettings.destination),
       ];
@@ -162,8 +161,7 @@
           'FooName';
       destinationSettings.destination = new print_preview.Destination(
           defaultId, print_preview.DestinationType.LOCAL, getLocalOrigin(),
-          defaultName, true /* isRecent */,
-          print_preview.DestinationConnectionStatus.ONLINE);
+          defaultName, print_preview.DestinationConnectionStatus.ONLINE);
       destinationSettings.destinationStore = destinationStore;
       destinationSettings.invitationStore = new print_preview.InvitationStore();
       destinationSettings.recentDestinations = recentDestinations;
diff --git a/chrome/test/data/webui/print_preview/header_test.js b/chrome/test/data/webui/print_preview/header_test.js
index c147e42..14776a5 100644
--- a/chrome/test/data/webui/print_preview/header_test.js
+++ b/chrome/test/data/webui/print_preview/header_test.js
@@ -73,7 +73,6 @@
       header.destination = new print_preview.Destination(
           'FooDevice', print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, 'FooName',
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       header.errorMessage = '';
       header.state = print_preview_new.State.READY;
@@ -87,7 +86,7 @@
               print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
               print_preview.DestinationType.LOCAL,
               print_preview.DestinationOrigin.LOCAL,
-              loadTimeData.getString('printToPDF'), false,
+              loadTimeData.getString('printToPDF'),
               print_preview.DestinationConnectionStatus.ONLINE));
     }
 
diff --git a/chrome/test/data/webui/print_preview/link_container_test.js b/chrome/test/data/webui/print_preview/link_container_test.js
index afe4006..20dc37d 100644
--- a/chrome/test/data/webui/print_preview/link_container_test.js
+++ b/chrome/test/data/webui/print_preview/link_container_test.js
@@ -26,7 +26,6 @@
       const fooDestination = new print_preview.Destination(
           'FooPrinter', print_preview.DestinationType.LOCAL,
           print_preview.DestinationOrigin.LOCAL, 'Foo Printer',
-          false /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       fooDestination.capabilities =
           print_preview_test_utils.getCddTemplate(fooDestination.id)
diff --git a/chrome/test/data/webui/print_preview/model_test.js b/chrome/test/data/webui/print_preview/model_test.js
index 5756f35e..7f90b01a 100644
--- a/chrome/test/data/webui/print_preview/model_test.js
+++ b/chrome/test/data/webui/print_preview/model_test.js
@@ -221,7 +221,7 @@
     test(assert(TestNames.GetPrintTicket), function() {
       const testDestination = new print_preview.Destination(
           'FooDevice', print_preview.DestinationType.LOCAL,
-          print_preview.DestinationOrigin.LOCAL, 'FooName', true /* isRecent */,
+          print_preview.DestinationOrigin.LOCAL, 'FooName',
           print_preview.DestinationConnectionStatus.ONLINE);
       testDestination.capabilities =
           print_preview_test_utils.getCddTemplateWithAdvancedSettings(2)
@@ -315,7 +315,6 @@
       const testDestination = new print_preview.Destination(
           'FooCloudDevice', print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, 'FooCloudName',
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       testDestination.capabilities =
           print_preview_test_utils.getCddTemplateWithAdvancedSettings(2)
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.js b/chrome/test/data/webui/print_preview/preview_generation_test.js
index f31d2c52..c20103ec 100644
--- a/chrome/test/data/webui/print_preview/preview_generation_test.js
+++ b/chrome/test/data/webui/print_preview/preview_generation_test.js
@@ -301,7 +301,6 @@
             const barDestination = new print_preview.Destination(
                 'BarDevice', print_preview.DestinationType.LOCAL,
                 print_preview.DestinationOrigin.LOCAL, 'BarName',
-                false /*isRecent*/,
                 print_preview.DestinationConnectionStatus.ONLINE);
             barDestination.capabilities =
                 print_preview_test_utils.getCddTemplate(barDestination.id)
diff --git a/chrome/test/data/webui/print_preview/print_header_interactive_test.js b/chrome/test/data/webui/print_preview/print_header_interactive_test.js
index dd5704c..68f59e1 100644
--- a/chrome/test/data/webui/print_preview/print_header_interactive_test.js
+++ b/chrome/test/data/webui/print_preview/print_header_interactive_test.js
@@ -68,7 +68,6 @@
       header.destination = new print_preview.Destination(
           'FooDevice', print_preview.DestinationType.GOOGLE,
           print_preview.DestinationOrigin.COOKIES, 'FooName',
-          true /* isRecent */,
           print_preview.DestinationConnectionStatus.ONLINE);
       header.errorMessage = '';
       header.state = print_preview_new.State.NOT_READY;
diff --git a/chrome/test/data/webui/print_preview/print_preview_test_utils.js b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
index ac96c53..3f1052c 100644
--- a/chrome/test/data/webui/print_preview/print_preview_test_utils.js
+++ b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
@@ -165,7 +165,7 @@
     };
     const dest = new print_preview.Destination(
         id, print_preview.DestinationType.GOOGLE,
-        print_preview.DestinationOrigin.COOKIES, name, true /* isRecent */,
+        print_preview.DestinationOrigin.COOKIES, name,
         print_preview.DestinationConnectionStatus.ONLINE, tags);
     return dest;
   }
@@ -247,7 +247,7 @@
         .forEach((info, index) => {
           const destination = new print_preview.Destination(
               info.id, print_preview.DestinationType.LOCAL, origin, info.name,
-              false, print_preview.DestinationConnectionStatus.ONLINE);
+              print_preview.DestinationConnectionStatus.ONLINE);
           if (nativeLayer) {
             nativeLayer.setLocalDestinationCapabilities(
                 print_preview_test_utils.getCddTemplate(info.id, info.name));
@@ -321,7 +321,7 @@
         print_preview.Destination.GooglePromotedId.DOCS,
         print_preview.DestinationType.GOOGLE,
         print_preview.DestinationOrigin.COOKIES,
-        print_preview.Destination.GooglePromotedId.DOCS, true /* isRecent */,
+        print_preview.Destination.GooglePromotedId.DOCS,
         print_preview.DestinationConnectionStatus.ONLINE,
         {account: 'foo@chromium.org'});
   }
@@ -332,7 +332,7 @@
         print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
         print_preview.DestinationType.LOCAL,
         print_preview.DestinationOrigin.LOCAL,
-        loadTimeData.getString('printToPDF'), false /*isRecent*/,
+        loadTimeData.getString('printToPDF'),
         print_preview.DestinationConnectionStatus.ONLINE);
   }
 
diff --git a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
index f197d97..40b5c1e 100644
--- a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
@@ -235,12 +235,17 @@
   RunTestViaHTTP("FileChooser_SaveAsCancel");
 }
 
-#if defined(OS_WIN) || defined(OS_MACOSX)
-// On Windows and macOS, tests that a file downloaded via PPAPI FileChooser API
-// has the mark-of-the-web. The PPAPI FileChooser implementation invokes
-// QuarantineFile in order to mark the file as being downloaded from the web as
-// soon as the file is created. This MotW prevents the file being opened without
-// due security warnings if the file is executable.
+#if defined(OS_WIN) || defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// On Windows, tests that a file downloaded via PPAPI FileChooser API has the
+// mark-of-the-web. The PPAPI FileChooser implementation invokes QuarantineFile
+// in order to mark the file as being downloaded from the web as soon as the
+// file is created. This MOTW prevents the file being opened without due
+// security warnings if the file is executable.
+//
+// On Linux Desktop, the setxattr call is made to set 'user.xdg.origin.url' and
+// the non-standard 'user.xdg.referrer.url' extended attributes to accomplish
+// the same thing. See
+// https://www.freedesktop.org/wiki/CommonExtendedAttributes/.
 IN_PROC_BROWSER_TEST_F(PPAPIFileChooserTest, FileChooser_Quarantine) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   base::ScopedTempDir temp_dir;
@@ -260,7 +265,7 @@
   ASSERT_TRUE(base::PathExists(actual_filename));
   EXPECT_TRUE(download::IsFileQuarantined(actual_filename, GURL(), GURL()));
 }
-#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+#endif  // defined(OS_WIN) || defined(OS_LINUX) && !defined(OS_CHROMEOS)
 
 #if defined(FULL_SAFE_BROWSING)
 // These tests only make sense when SafeBrowsing is enabled. They verify
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index f7ecfb6..1bcfb84d 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -14,6 +14,17 @@
   }
 }
 
+source_set("common") {
+  sources = [
+    "updater.cc",
+    "updater.h",
+  ]
+
+  deps = [
+    "//base",
+  ]
+}
+
 source_set("updater_tests") {
   testonly = true
   if (is_win) {
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc
new file mode 100644
index 0000000..3b4b973
--- /dev/null
+++ b/chrome/updater/updater.cc
@@ -0,0 +1,83 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/updater/updater.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/at_exit.h"
+#include "base/callback_forward.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/initialization_util.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "base/task_runner.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+
+namespace updater {
+
+namespace {
+
+void TaskSchedulerStart() {
+  base::TaskScheduler::Create("Updater");
+  const auto task_scheduler_init_params =
+      std::make_unique<base::TaskScheduler::InitParams>(
+          base::SchedulerWorkerPoolParams(
+              base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
+              base::TimeDelta::FromSeconds(30)),
+          base::SchedulerWorkerPoolParams(
+              base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
+              base::TimeDelta::FromSeconds(40)),
+          base::SchedulerWorkerPoolParams(
+              base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
+              base::TimeDelta::FromSeconds(30)),
+          base::SchedulerWorkerPoolParams(
+              base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
+              base::TimeDelta::FromSeconds(60)));
+  base::TaskScheduler::GetInstance()->Start(*task_scheduler_init_params);
+}
+
+void TaskSchedulerStop() {
+  base::TaskScheduler::GetInstance()->Shutdown();
+}
+
+void QuitLoop(base::OnceClosure quit_closure) {
+  std::move(quit_closure).Run();
+}
+
+}  // namespace
+
+int UpdaterMain() {
+  base::AtExitManager exit_manager;
+
+  TaskSchedulerStart();
+
+  base::MessageLoopForUI message_loop;
+  DCHECK(base::ThreadTaskRunnerHandle::IsSet());
+  base::PlatformThread::SetName("UpdaterMain");
+
+  // Post a task through the task scheduler to this thread's task runner
+  // to make it quit the runloop and exit main.
+  base::RunLoop runloop;
+  auto quit_closure = base::BindOnce(
+      [](scoped_refptr<base::TaskRunner> task_runner,
+         base::OnceClosure quit_closure) {
+        task_runner->PostTask(FROM_HERE, std::move(quit_closure));
+      },
+      base::ThreadTaskRunnerHandle::Get(), runloop.QuitClosure());
+  base::PostTask(FROM_HERE, base::BindOnce(&QuitLoop, std::move(quit_closure)));
+
+  runloop.Run();
+
+  TaskSchedulerStop();
+  return 0;
+}
+
+}  // namespace updater
diff --git a/chrome/updater/updater.h b/chrome/updater/updater.h
new file mode 100644
index 0000000..565758c02
--- /dev/null
+++ b/chrome/updater/updater.h
@@ -0,0 +1,14 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_UPDATER_UPDATER_H_
+#define CHROME_UPDATER_UPDATER_H_
+
+namespace updater {
+
+int UpdaterMain();
+
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_UPDATER_H_
diff --git a/chrome/updater/win/BUILD.gn b/chrome/updater/win/BUILD.gn
index d89de9363..61a1b5b 100644
--- a/chrome/updater/win/BUILD.gn
+++ b/chrome/updater/win/BUILD.gn
@@ -21,6 +21,7 @@
   deps = [
     ":version_resources",
     "//build/win:default_exe_manifest",
+    "//chrome/updater:common",
   ]
 }
 
diff --git a/chrome/updater/win/main.cc b/chrome/updater/win/main.cc
index 0937c5d..86923a9 100644
--- a/chrome/updater/win/main.cc
+++ b/chrome/updater/win/main.cc
@@ -4,6 +4,8 @@
 
 #include <windows.h>
 
+#include "chrome/updater/updater.h"
+
 int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
-  return 0;
+  return updater::UpdaterMain();
 }
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc
index aecde65f..7ebcf27 100644
--- a/chromecast/browser/cast_media_blocker_unittest.cc
+++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -37,10 +37,8 @@
   MOCK_METHOD1(SetDuckingVolumeMultiplier, void(double));
   MOCK_METHOD1(DidReceiveAction,
                void(media_session::mojom::MediaSessionAction));
-  MOCK_METHOD1(AddObserver, void(content::MediaSessionObserver*));
   MOCK_METHOD1(AddObserver,
                void(media_session::mojom::MediaSessionObserverPtr));
-  MOCK_METHOD1(RemoveObserver, void(content::MediaSessionObserver*));
   MOCK_METHOD1(GetMediaSessionInfo, void(GetMediaSessionInfoCallback));
   MOCK_METHOD1(GetDebugInfo, void(GetDebugInfoCallback));
   MOCK_METHOD0(PreviousTrack, void());
diff --git a/chromecast/net/connectivity_checker_impl.cc b/chromecast/net/connectivity_checker_impl.cc
index 8644b00..c3772b7 100644
--- a/chromecast/net/connectivity_checker_impl.cc
+++ b/chromecast/net/connectivity_checker_impl.cc
@@ -232,7 +232,9 @@
   }
   DCHECK(task_runner_->BelongsToCurrentThread());
   LOG(ERROR) << "OnSSLCertificateError: cert_status=" << ssl_info.cert_status;
-  net::SSLClientSocket::ClearSessionCache();
+  url_request_context_->http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
   OnUrlRequestError(ErrorType::SSL_CERTIFICATE_ERROR);
   timeout_.Cancel();
 }
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 8c5de56..dfaa0fb 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -78,6 +78,11 @@
 const base::Feature kUseMessagesGoogleComDomain{
     "UseMessagesGoogleComDomain", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Use the staging URL as part of the "Messages" feature under "Connected
+// Devices" settings.
+const base::Feature kUseMessagesStagingUrl{"UseMessagesStagingUrl",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables or disables user activity prediction for power management on
 // Chrome OS.
 // Defined here rather than in //chrome alongside other related features so that
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 84dbc4f6..cc30749 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -31,6 +31,7 @@
 CHROMEOS_EXPORT extern const base::Feature kInstantTethering;
 CHROMEOS_EXPORT extern const base::Feature kVideoPlayerNativeControls;
 CHROMEOS_EXPORT extern const base::Feature kUseMessagesGoogleComDomain;
+CHROMEOS_EXPORT extern const base::Feature kUseMessagesStagingUrl;
 CHROMEOS_EXPORT extern const base::Feature kUserActivityPrediction;
 CHROMEOS_EXPORT extern const base::Feature kUserActivityPredictionMlService;
 
diff --git a/chromeos/services/device_sync/cryptauth_client.h b/chromeos/services/device_sync/cryptauth_client.h
index 953eb6e..f6537b6 100644
--- a/chromeos/services/device_sync/cryptauth_client.h
+++ b/chromeos/services/device_sync/cryptauth_client.h
@@ -30,6 +30,13 @@
 class FindEligibleForPromotionResponse;
 }  // namespace cryptauth
 
+namespace cryptauthv2 {
+class SyncKeysRequest;
+class SyncKeysResponse;
+class EnrollKeysRequest;
+class EnrollKeysResponse;
+}  // namespace cryptauthv2
+
 namespace chromeos {
 
 namespace device_sync {
@@ -106,6 +113,20 @@
       const FinishEnrollmentCallback& callback,
       const ErrorCallback& error_callback) = 0;
 
+  // SyncKeys (CryptAuth v2 Enrollment)
+  typedef base::Callback<void(const cryptauthv2::SyncKeysResponse&)>
+      SyncKeysCallback;
+  virtual void SyncKeys(const cryptauthv2::SyncKeysRequest& request,
+                        const SyncKeysCallback& callback,
+                        const ErrorCallback& error_callback) = 0;
+
+  // EnrollKeys (CryptAuth v2 Enrollment)
+  typedef base::Callback<void(const cryptauthv2::EnrollKeysResponse&)>
+      EnrollKeysCallback;
+  virtual void EnrollKeys(const cryptauthv2::EnrollKeysRequest& request,
+                          const EnrollKeysCallback& callback,
+                          const ErrorCallback& error_callback) = 0;
+
   // Returns the access token used to make the request. If no request has been
   // made yet, this function will return an empty string.
   virtual std::string GetAccessTokenUsed() = 0;
diff --git a/chromeos/services/device_sync/cryptauth_client_impl.cc b/chromeos/services/device_sync/cryptauth_client_impl.cc
index c00414b..ca3ff48 100644
--- a/chromeos/services/device_sync/cryptauth_client_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_client_impl.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "chromeos/components/multidevice/logging/logging.h"
+#include "chromeos/services/device_sync/proto/cryptauth_enrollment.pb.h"
 #include "chromeos/services/device_sync/switches.h"
 #include "services/identity/public/cpp/identity_manager.h"
 #include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
@@ -22,13 +23,13 @@
 
 namespace {
 
-// Default URL of Google APIs endpoint hosting CryptAuth.
-const char kDefaultCryptAuthHTTPHost[] = "https://www.googleapis.com";
+// Default URL of Google APIs endpoint hosting CryptAuth v1.
+const char kDefaultCryptAuthV1HTTPHost[] = "https://www.googleapis.com";
 
-// URL subpath hosting the CryptAuth service.
-const char kCryptAuthPath[] = "cryptauth/v1/";
+// URL subpath hosting the CryptAuth v1 service.
+const char kCryptAuthV1Path[] = "cryptauth/v1/";
 
-// URL subpaths for each CryptAuth API.
+// URL subpaths for each CryptAuth v1 API.
 const char kGetMyDevicesPath[] = "deviceSync/getmydevices";
 const char kFindEligibleUnlockDevicesPath[] =
     "deviceSync/findeligibleunlockdevices";
@@ -39,21 +40,48 @@
 const char kSetupEnrollmentPath[] = "enrollment/setup";
 const char kFinishEnrollmentPath[] = "enrollment/finish";
 
+// Default URL of Google APIs endpoint hosting CryptAuth v2 Enrollment.
+const char kDefaultCryptAuthV2EnrollmentHTTPHost[] =
+    "https://cryptauthenrollment.googleapis.com";
+
+// URL subpaths for each CryptAuth v2 API.
+// Note: Although "v1" is part of the path names, these are in fact v2 API
+//       endpoints. Also, the "/" is necessary for GURL::Resolve() to parse the
+//       paths correctly; otherwise, ":" is interpreted as a scheme delimiter.
+const char kSyncKeysPath[] = "/v1:syncKeys";
+const char kEnrollKeysPath[] = "/v1:enrollKeys";
+
 // Query string of the API URL indicating that the response should be in a
 // serialized protobuf format.
 const char kQueryProtobuf[] = "?alt=proto";
 
-// Creates the full CryptAuth URL for endpoint to the API with |request_path|.
-GURL CreateRequestUrl(const std::string& request_path) {
+const char kCryptAuthOAuth2Scope[] =
+    "https://www.googleapis.com/auth/cryptauth";
+
+// Creates the full CryptAuth v1 URL for endpoint to the API with
+// |request_path|.
+GURL CreateV1RequestUrl(const std::string& request_path) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   GURL google_apis_url =
       GURL(command_line->HasSwitch(switches::kCryptAuthHTTPHost)
                ? command_line->GetSwitchValueASCII(switches::kCryptAuthHTTPHost)
-               : kDefaultCryptAuthHTTPHost);
-  return google_apis_url.Resolve(kCryptAuthPath + request_path +
+               : kDefaultCryptAuthV1HTTPHost);
+  return google_apis_url.Resolve(kCryptAuthV1Path + request_path +
                                  kQueryProtobuf);
 }
 
+// Creates the full URL for endpoint to the CryptAuth v2 Enrollment API with
+// |request_path|.
+GURL CreateV2EnrollmentRequestUrl(const std::string& request_path) {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  GURL google_apis_url =
+      GURL(command_line->HasSwitch(switches::kCryptAuthV2EnrollmentHTTPHost)
+               ? command_line->GetSwitchValueASCII(
+                     switches::kCryptAuthV2EnrollmentHTTPHost)
+               : kDefaultCryptAuthV2EnrollmentHTTPHost);
+  return google_apis_url.Resolve(request_path + kQueryProtobuf);
+}
+
 }  // namespace
 
 CryptAuthClientImpl::CryptAuthClientImpl(
@@ -75,7 +103,8 @@
     const GetMyDevicesCallback& callback,
     const ErrorCallback& error_callback,
     const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
-  MakeApiCall(kGetMyDevicesPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kGetMyDevicesPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -108,7 +137,8 @@
           }
         }
       })");
-  MakeApiCall(kFindEligibleUnlockDevicesPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kFindEligibleUnlockDevicesPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -138,7 +168,8 @@
           }
         }
       })");
-  MakeApiCall(kFindEligibleForPromotionPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kFindEligibleForPromotionPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -147,7 +178,8 @@
     const SendDeviceSyncTickleCallback& callback,
     const ErrorCallback& error_callback,
     const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
-  MakeApiCall(kSendDeviceSyncTicklePath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kSendDeviceSyncTicklePath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -178,7 +210,8 @@
           }
         }
       })");
-  MakeApiCall(kToggleEasyUnlockPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kToggleEasyUnlockPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -212,7 +245,8 @@
           }
         }
       })");
-  MakeApiCall(kSetupEnrollmentPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kSetupEnrollmentPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
@@ -243,17 +277,86 @@
           }
         }
       })");
-  MakeApiCall(kFinishEnrollmentPath, request, callback, error_callback,
+  MakeApiCall(CreateV1RequestUrl(kFinishEnrollmentPath),
+              RequestWithDeviceClassifierSet(request), callback, error_callback,
               partial_traffic_annotation);
 }
 
+void CryptAuthClientImpl::SyncKeys(const cryptauthv2::SyncKeysRequest& request,
+                                   const SyncKeysCallback& callback,
+                                   const ErrorCallback& error_callback) {
+  net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
+      net::DefinePartialNetworkTrafficAnnotation(
+          "cryptauth_v2_enrollment_flow_sync_keys", "oauth2_api_call_flow", R"(
+      semantics {
+        sender: "CryptAuth V2 Enroller"
+        description: "Starts the CryptAuth v2 Enrollment flow."
+        trigger:
+          "Occurs periodically at a period provided by CryptAuth in the "
+          "previous SyncKeysResponse's ClientDirective. The client can also "
+          "bypass the periodic schedule and immediately trigger a "
+          "SyncKeysRequest."
+        data:
+          "A list of all keys used by the client; metadata about the "
+          "local device's feature support, hardware, etc.; and an OAuth 2.0 "
+          "token."
+        destination: GOOGLE_OWNED_SERVICE
+      }
+      policy {
+        setting:
+          "This feature cannot be disabled by settings. However, this request "
+          "is made only for signed-in users."
+        chrome_policy {
+          SigninAllowed {
+            SigninAllowed: false
+          }
+        }
+      })");
+  MakeApiCall(CreateV2EnrollmentRequestUrl(kSyncKeysPath), request, callback,
+              error_callback, partial_traffic_annotation);
+}
+
+void CryptAuthClientImpl::EnrollKeys(
+    const cryptauthv2::EnrollKeysRequest& request,
+    const EnrollKeysCallback& callback,
+    const ErrorCallback& error_callback) {
+  net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
+      net::DefinePartialNetworkTrafficAnnotation(
+          "cryptauth_v2_enrollment_flow_enroll_keys", "oauth2_api_call_flow",
+          R"(
+      semantics {
+        sender: "CryptAuth V2 Enroller"
+        description: "Finishes the CryptAuth v2 Enrollment flow."
+        trigger:
+          "The second part of the v2 Enrollment flow. Sent after the client "
+          "receives a SyncKeysResponse from CryptAuth, requesting the client "
+          "create new keys."
+        data:
+          "A list of newly created key material and necessary proofs for "
+          "verifying the keys."
+        destination: GOOGLE_OWNED_SERVICE
+      }
+      policy {
+        setting:
+          "This feature cannot be disabled by settings. However, this request "
+          "is made only for signed-in users."
+        chrome_policy {
+          SigninAllowed {
+            SigninAllowed: false
+          }
+        }
+      })");
+  MakeApiCall(CreateV2EnrollmentRequestUrl(kEnrollKeysPath), request, callback,
+              error_callback, partial_traffic_annotation);
+}
+
 std::string CryptAuthClientImpl::GetAccessTokenUsed() {
   return access_token_used_;
 }
 
 template <class RequestProto, class ResponseProto>
 void CryptAuthClientImpl::MakeApiCall(
-    const std::string& request_path,
+    const GURL& request_url,
     const RequestProto& request_proto,
     const base::Callback<void(const ResponseProto&)>& response_callback,
     const ErrorCallback& error_callback,
@@ -269,23 +372,19 @@
   api_call_flow_->SetPartialNetworkTrafficAnnotation(
       partial_traffic_annotation);
 
-  // The |device_classifier| field must be present for all CryptAuth requests.
-  RequestProto request_copy(request_proto);
-  request_copy.mutable_device_classifier()->CopyFrom(device_classifier_);
-
   std::string serialized_request;
-  if (!request_copy.SerializeToString(&serialized_request)) {
+  if (!request_proto.SerializeToString(&serialized_request)) {
     PA_LOG(ERROR) << "CryptAuthClientImpl::MakeApiCall(): Failure serializing "
                   << "request proto.";
     NOTREACHED();
     return;
   }
 
-  request_path_ = request_path;
+  request_url_ = request_url;
   error_callback_ = error_callback;
 
   OAuth2TokenService::ScopeSet scopes;
-  scopes.insert("https://www.googleapis.com/auth/cryptauth");
+  scopes.insert(kCryptAuthOAuth2Scope);
 
   access_token_fetcher_ = std::make_unique<
       identity::PrimaryAccountAccessTokenFetcher>(
@@ -311,8 +410,7 @@
   access_token_used_ = access_token_info.token;
 
   api_call_flow_->Start(
-      CreateRequestUrl(request_path_), url_loader_factory_, access_token_used_,
-      serialized_request,
+      request_url_, url_loader_factory_, access_token_used_, serialized_request,
       base::Bind(&CryptAuthClientImpl::OnFlowSuccess<ResponseProto>,
                  weak_ptr_factory_.GetWeakPtr(), response_callback),
       base::Bind(&CryptAuthClientImpl::OnApiCallFailed,
@@ -335,6 +433,15 @@
   error_callback_.Run(error);
 }
 
+template <class RequestProto>
+RequestProto CryptAuthClientImpl::RequestWithDeviceClassifierSet(
+    const RequestProto& request) {
+  RequestProto request_copy(request);
+  request_copy.mutable_device_classifier()->CopyFrom(device_classifier_);
+
+  return request_copy;
+}
+
 // CryptAuthClientFactoryImpl
 CryptAuthClientFactoryImpl::CryptAuthClientFactoryImpl(
     identity::IdentityManager* identity_manager,
diff --git a/chromeos/services/device_sync/cryptauth_client_impl.h b/chromeos/services/device_sync/cryptauth_client_impl.h
index a7e5ad4..a940a706 100644
--- a/chromeos/services/device_sync/cryptauth_client_impl.h
+++ b/chromeos/services/device_sync/cryptauth_client_impl.h
@@ -36,6 +36,8 @@
   // Creates the client using |url_request_context| to make the HTTP request
   // through |api_call_flow|. The |device_classifier| argument contains basic
   // device information of the caller (e.g. version and device type).
+  // TODO(nohle): Remove the |device_classifier| argument when the CryptAuth v1
+  // methods are no longer needed.
   CryptAuthClientImpl(
       std::unique_ptr<CryptAuthApiCallFlow> api_call_flow,
       identity::IdentityManager* identity_manager,
@@ -72,15 +74,21 @@
   void FinishEnrollment(const cryptauth::FinishEnrollmentRequest& request,
                         const FinishEnrollmentCallback& callback,
                         const ErrorCallback& error_callback) override;
+  void SyncKeys(const cryptauthv2::SyncKeysRequest& request,
+                const SyncKeysCallback& callback,
+                const ErrorCallback& error_callback) override;
+  void EnrollKeys(const cryptauthv2::EnrollKeysRequest& request,
+                  const EnrollKeysCallback& callback,
+                  const ErrorCallback& error_callback) override;
   std::string GetAccessTokenUsed() override;
 
  private:
-  // Starts a call to the API given by |request_path|, with the templated
+  // Starts a call to the API given by |request_url|, with the templated
   // request and response types. The client first fetches the access token and
   // then makes the HTTP request.
   template <class RequestProto, class ResponseProto>
   void MakeApiCall(
-      const std::string& request_path,
+      const GURL& request_url,
       const RequestProto& request_proto,
       const base::Callback<void(const ResponseProto&)>& response_callback,
       const ErrorCallback& error_callback,
@@ -105,6 +113,11 @@
   // Called when the current API call fails at any step.
   void OnApiCallFailed(NetworkRequestError error);
 
+  // Returns a copy of the input request with the device classifier field set.
+  // Only used for CryptAuth v1 protos.
+  template <class RequestProto>
+  RequestProto RequestWithDeviceClassifierSet(const RequestProto& request);
+
   // Constructs and executes the actual HTTP request.
   std::unique_ptr<CryptAuthApiCallFlow> api_call_flow_;
 
@@ -125,8 +138,8 @@
   // completes.
   bool has_call_started_;
 
-  // URL path of the current request.
-  std::string request_path_;
+  // URL of the current request.
+  GURL request_url_;
 
   // The access token fetched by |access_token_fetcher_|.
   std::string access_token_used_;
diff --git a/chromeos/services/device_sync/cryptauth_client_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_client_impl_unittest.cc
index 347dfaa..4c7fd0b 100644
--- a/chromeos/services/device_sync/cryptauth_client_impl_unittest.cc
+++ b/chromeos/services/device_sync/cryptauth_client_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/services/device_sync/cryptauth_api_call_flow.h"
 #include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_enrollment.pb.h"
 #include "chromeos/services/device_sync/proto/enum_util.h"
 #include "chromeos/services/device_sync/switches.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -35,6 +36,8 @@
 namespace {
 
 const char kTestGoogleApisUrl[] = "https://www.testgoogleapis.com";
+const char kTestCryptAuthV2EnrollmentUrl[] =
+    "https://cryptauthenrollment.testgoogleapis.com";
 const char kAccessToken[] = "access_token";
 const char kEmail[] = "test@gmail.com";
 const char kPublicKey1[] = "public_key1";
@@ -111,6 +114,9 @@
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kCryptAuthHTTPHost, kTestGoogleApisUrl);
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kCryptAuthV2EnrollmentHTTPHost,
+        kTestCryptAuthV2EnrollmentUrl);
 
     cryptauth::DeviceClassifier device_classifier;
     device_classifier.set_device_os_version_code(kDeviceOsVersionCode);
@@ -459,6 +465,76 @@
   EXPECT_EQ("OK", result_proto.status());
 }
 
+TEST_F(CryptAuthClientTest, SyncKeysSuccess) {
+  ExpectRequest(
+      "https://cryptauthenrollment.testgoogleapis.com/v1:syncKeys?alt=proto");
+
+  const char kApplicationName[] = "application_name";
+  const char kRandomSessionId[] = "random_session_id";
+
+  cryptauthv2::SyncKeysRequest request_proto;
+  request_proto.set_application_name(kApplicationName);
+
+  cryptauthv2::SyncKeysResponse result_proto;
+  client_->SyncKeys(
+      request_proto,
+      base::Bind(&SaveResultConstRef<cryptauthv2::SyncKeysResponse>,
+                 &result_proto),
+      base::Bind(&NotCalled<NetworkRequestError>));
+  identity_test_environment_
+      .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+          kAccessToken, base::Time::Max());
+
+  cryptauthv2::SyncKeysRequest expected_request;
+  EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
+  EXPECT_EQ(kApplicationName, expected_request.application_name());
+
+  {
+    cryptauthv2::SyncKeysResponse response_proto;
+    response_proto.set_random_session_id(kRandomSessionId);
+    FinishApiCallFlow(&response_proto);
+  }
+  EXPECT_EQ(kRandomSessionId, result_proto.random_session_id());
+}
+
+TEST_F(CryptAuthClientTest, EnrollKeysSuccess) {
+  ExpectRequest(
+      "https://cryptauthenrollment.testgoogleapis.com/v1:enrollKeys?alt=proto");
+
+  const char kRandomSessionId[] = "random_session_id";
+  const char kCertificateName[] = "certificate_name";
+
+  cryptauthv2::EnrollKeysRequest request_proto;
+  request_proto.set_random_session_id(kRandomSessionId);
+
+  cryptauthv2::EnrollKeysResponse result_proto;
+  client_->EnrollKeys(
+      request_proto,
+      base::Bind(&SaveResultConstRef<cryptauthv2::EnrollKeysResponse>,
+                 &result_proto),
+      base::Bind(&NotCalled<NetworkRequestError>));
+  identity_test_environment_
+      .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+          kAccessToken, base::Time::Max());
+
+  cryptauthv2::EnrollKeysRequest expected_request;
+  EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
+  EXPECT_EQ(kRandomSessionId, expected_request.random_session_id());
+
+  {
+    cryptauthv2::EnrollKeysResponse response_proto;
+    response_proto.add_enroll_single_key_responses()
+        ->add_certificate()
+        ->set_common_name(kCertificateName);
+    FinishApiCallFlow(&response_proto);
+  }
+  ASSERT_EQ(1, result_proto.enroll_single_key_responses_size());
+  ASSERT_EQ(1, result_proto.enroll_single_key_responses(0).certificate_size());
+  EXPECT_EQ(
+      kCertificateName,
+      result_proto.enroll_single_key_responses(0).certificate(0).common_name());
+}
+
 TEST_F(CryptAuthClientTest, FetchAccessTokenFailure) {
   NetworkRequestError error;
   client_->GetMyDevices(
diff --git a/chromeos/services/device_sync/mock_cryptauth_client.h b/chromeos/services/device_sync/mock_cryptauth_client.h
index 61c447a..72c3132 100644
--- a/chromeos/services/device_sync/mock_cryptauth_client.h
+++ b/chromeos/services/device_sync/mock_cryptauth_client.h
@@ -9,6 +9,7 @@
 #include "base/observer_list.h"
 #include "chromeos/services/device_sync/cryptauth_client.h"
 #include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
+#include "chromeos/services/device_sync/proto/cryptauth_enrollment.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace chromeos {
@@ -53,6 +54,14 @@
                void(const cryptauth::FinishEnrollmentRequest& request,
                     const FinishEnrollmentCallback& callback,
                     const ErrorCallback& error_callback));
+  MOCK_METHOD3(SyncKeys,
+               void(const cryptauthv2::SyncKeysRequest& request,
+                    const SyncKeysCallback& callback,
+                    const ErrorCallback& error_callback));
+  MOCK_METHOD3(EnrollKeys,
+               void(const cryptauthv2::EnrollKeysRequest& request,
+                    const EnrollKeysCallback& callback,
+                    const ErrorCallback& error_callback));
   MOCK_METHOD0(GetAccessTokenUsed, std::string());
 
  private:
diff --git a/chromeos/services/device_sync/switches.cc b/chromeos/services/device_sync/switches.cc
index b57b0ee..47c2ecf 100644
--- a/chromeos/services/device_sync/switches.cc
+++ b/chromeos/services/device_sync/switches.cc
@@ -14,6 +14,11 @@
 // by CryptAuth.
 const char kCryptAuthHTTPHost[] = "cryptauth-http-host";
 
+// Overrides the default URL for CryptAuth v2 Enrollment:
+// https://cryptauthenrollment.googleapis.com.
+const char kCryptAuthV2EnrollmentHTTPHost[] =
+    "cryptauth-v2-enrollment-http-host";
+
 }  // namespace switches
 
 }  // namespace device_sync
diff --git a/chromeos/services/device_sync/switches.h b/chromeos/services/device_sync/switches.h
index 74fe0e7..b557d9b 100644
--- a/chromeos/services/device_sync/switches.h
+++ b/chromeos/services/device_sync/switches.h
@@ -14,6 +14,7 @@
 // All switches in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
 extern const char kCryptAuthHTTPHost[];
+extern const char kCryptAuthV2EnrollmentHTTPHost[];
 
 }  // namespace switches
 
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection.cc b/chromeos/services/machine_learning/public/cpp/service_connection.cc
index 3aa7c8a..d749cce7 100644
--- a/chromeos/services/machine_learning/public/cpp/service_connection.cc
+++ b/chromeos/services/machine_learning/public/cpp/service_connection.cc
@@ -9,6 +9,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/machine_learning_client.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
+#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
index 4c37c50..67d148a 100644
--- a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
+++ b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/threading/thread.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
+#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
diff --git a/components/cast_channel/cast_socket.h b/components/cast_channel/cast_socket.h
index 8a65fa2..79e7620 100644
--- a/components/cast_channel/cast_socket.h
+++ b/components/cast_channel/cast_socket.h
@@ -27,6 +27,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/log/net_log_source.h"
 #include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 
 namespace net {
 class X509Certificate;
diff --git a/components/cast_channel/cast_socket_unittest.cc b/components/cast_channel/cast_socket_unittest.cc
index c50c037..69300b4e 100644
--- a/components/cast_channel/cast_socket_unittest.cc
+++ b/components/cast_channel/cast_socket_unittest.cc
@@ -352,7 +352,6 @@
     NOTIMPLEMENTED();
     return nullptr;
   }
-  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
 
   net::IPEndPoint ip_;
   // Simulated connect data
diff --git a/components/download/quarantine/BUILD.gn b/components/download/quarantine/BUILD.gn
index 4ce7b5b..fafcb749 100644
--- a/components/download/quarantine/BUILD.gn
+++ b/components/download/quarantine/BUILD.gn
@@ -14,6 +14,7 @@
     "quarantine.h",
     "quarantine_features_win.cc",
     "quarantine_features_win.h",
+    "quarantine_linux.cc",
     "quarantine_mac.mm",
     "quarantine_win.cc",
   ]
@@ -35,6 +36,8 @@
 
 source_set("common") {
   sources = [
+    "common_linux.cc",
+    "common_linux.h",
     "common_mac.h",
     "common_mac.mm",
     "common_win.cc",
@@ -59,6 +62,7 @@
   sources = [
     "test_support.cc",
     "test_support.h",
+    "test_support_linux.cc",
     "test_support_mac.mm",
     "test_support_win.cc",
   ]
@@ -82,6 +86,7 @@
   testonly = true
 
   sources = [
+    "quarantine_linux_unittest.cc",
     "quarantine_mac_unittest.mm",
     "quarantine_win_unittest.cc",
   ]
diff --git a/components/download/quarantine/common_linux.cc b/components/download/quarantine/common_linux.cc
new file mode 100644
index 0000000..3674c8c
--- /dev/null
+++ b/components/download/quarantine/common_linux.cc
@@ -0,0 +1,12 @@
+// 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/download/quarantine/common_linux.h"
+
+namespace download {
+
+const char kSourceURLExtendedAttrName[] = "user.xdg.origin.url";
+const char kReferrerURLExtendedAttrName[] = "user.xdg.referrer.url";
+
+}  // namespace download
diff --git a/components/download/quarantine/common_linux.h b/components/download/quarantine/common_linux.h
new file mode 100644
index 0000000..6b52b1b4
--- /dev/null
+++ b/components/download/quarantine/common_linux.h
@@ -0,0 +1,21 @@
+// 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_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
+#define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
+
+namespace download {
+
+// Attribute names to be used with setxattr and friends.
+//
+// The source URL attribute is part of the XDG standard.
+// The referrer URL attribute is not part of the XDG standard,
+// but it is used to keep the naming consistent.
+// http://freedesktop.org/wiki/CommonExtendedAttributes
+extern const char kSourceURLExtendedAttrName[];
+extern const char kReferrerURLExtendedAttrName[];
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_LINUX_H_
diff --git a/components/download/quarantine/quarantine.cc b/components/download/quarantine/quarantine.cc
index ac5b109..48a2c59 100644
--- a/components/download/quarantine/quarantine.cc
+++ b/components/download/quarantine/quarantine.cc
@@ -6,7 +6,7 @@
 
 #include "build/build_config.h"
 
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
+#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
 
 namespace download {
 
@@ -19,4 +19,4 @@
 
 }  // namespace download
 
-#endif  // !WIN && !MAC
+#endif  // !WIN && !MAC && !LINUX
diff --git a/components/download/quarantine/quarantine_linux.cc b/components/download/quarantine/quarantine_linux.cc
new file mode 100644
index 0000000..8683056
--- /dev/null
+++ b/components/download/quarantine/quarantine_linux.cc
@@ -0,0 +1,64 @@
+// 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 "components/download/quarantine/quarantine.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "components/download/quarantine/common_linux.h"
+#include "url/gurl.h"
+
+namespace download {
+
+namespace {
+
+bool SetExtendedFileAttribute(const char* path,
+                              const char* name,
+                              const char* value,
+                              size_t value_size,
+                              int flags) {
+// On Chrome OS, there is no component that can validate these extended
+// attributes so there is no need to set them.
+#if !defined(OS_CHROMEOS)
+  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
+  int result = setxattr(path, name, value, value_size, flags);
+  if (result) {
+    DPLOG(ERROR) << "Could not set extended attribute " << name << " on file "
+                 << path;
+    return false;
+  }
+#endif  // !defined(OS_CHROMEOS)
+  return true;
+}
+
+}  // namespace
+
+QuarantineFileResult QuarantineFile(const base::FilePath& file,
+                                    const GURL& source_url,
+                                    const GURL& referrer_url,
+                                    const std::string& client_guid) {
+  bool source_succeeded =
+      source_url.is_valid() &&
+      SetExtendedFileAttribute(file.value().c_str(), kSourceURLExtendedAttrName,
+                               source_url.spec().c_str(),
+                               source_url.spec().length(), 0);
+
+  // Referrer being empty is not considered an error. This could happen if the
+  // referrer policy resulted in an empty referrer for the download request.
+  bool referrer_succeeded =
+      !referrer_url.is_valid() ||
+      SetExtendedFileAttribute(
+          file.value().c_str(), kReferrerURLExtendedAttrName,
+          referrer_url.spec().c_str(), referrer_url.spec().length(), 0);
+  return source_succeeded && referrer_succeeded
+             ? QuarantineFileResult::OK
+             : QuarantineFileResult::ANNOTATION_FAILED;
+}
+
+}  // namespace download
diff --git a/components/download/quarantine/quarantine_linux_unittest.cc b/components/download/quarantine/quarantine_linux_unittest.cc
new file mode 100644
index 0000000..3216420
--- /dev/null
+++ b/components/download/quarantine/quarantine_linux_unittest.cc
@@ -0,0 +1,183 @@
+// 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 "components/download/quarantine/quarantine.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_split.h"
+#include "components/download/quarantine/common_linux.h"
+#include "components/download/quarantine/test_support.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace download {
+namespace {
+
+using std::istringstream;
+using std::string;
+using std::vector;
+
+class QuarantineLinuxTest : public testing::Test {
+ public:
+  QuarantineLinuxTest()
+      : source_url_("http://www.source.com"),
+        referrer_url_("http://www.referrer.com"),
+        is_xattr_supported_(false) {}
+
+  const base::FilePath& test_file() const { return test_file_; }
+
+  const base::FilePath& test_dir() const { return temp_dir_.GetPath(); }
+
+  const GURL& source_url() const { return source_url_; }
+
+  const GURL& referrer_url() const { return referrer_url_; }
+
+  bool is_xattr_supported() const { return is_xattr_supported_; }
+
+ protected:
+  void SetUp() override {
+#if !defined(OS_CHROMEOS)
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    ASSERT_TRUE(
+        base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &test_file_));
+    int result =
+        setxattr(test_file_.value().c_str(), "user.test", "test", 4, 0);
+    is_xattr_supported_ = (!result) || (errno != ENOTSUP);
+#endif  // !defined(OS_CHROMEOS)
+    if (!is_xattr_supported_) {
+      LOG(WARNING) << "Test will be skipped because extended attributes are "
+                      "not supported on this OS/file system.";
+    }
+  }
+
+  void GetExtendedAttributeNames(vector<string>* attr_names) const {
+    ssize_t len = listxattr(test_file().value().c_str(), nullptr, 0);
+    if (len <= static_cast<ssize_t>(0))
+      return;
+    char* buffer = new char[len];
+    len = listxattr(test_file().value().c_str(), buffer, len);
+    *attr_names =
+        base::SplitString(string(buffer, len), std::string(1, '\0'),
+                          base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    delete[] buffer;
+  }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+  base::FilePath test_file_;
+  GURL source_url_;
+  GURL referrer_url_;
+  bool is_xattr_supported_;
+};
+
+}  // namespace
+
+TEST_F(QuarantineLinuxTest, CheckMetadataSetCorrectly) {
+  if (!is_xattr_supported())
+    return;
+  EXPECT_EQ(
+      QuarantineFileResult::OK,
+      QuarantineFile(test_file(), source_url(), referrer_url(), std::string()));
+  EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), referrer_url()));
+}
+
+TEST_F(QuarantineLinuxTest, SetMetadataMultipleTimes) {
+  if (!is_xattr_supported())
+    return;
+  GURL dummy_url("http://www.dummy.com");
+  EXPECT_EQ(QuarantineFileResult::OK,
+            QuarantineFile(test_file(), dummy_url, dummy_url, std::string()));
+  EXPECT_EQ(
+      QuarantineFileResult::OK,
+      QuarantineFile(test_file(), source_url(), referrer_url(), std::string()));
+  EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), referrer_url()));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidSourceURLTest) {
+  if (!is_xattr_supported())
+    return;
+  GURL invalid_url;
+  vector<string> attr_names;
+  EXPECT_EQ(
+      QuarantineFileResult::ANNOTATION_FAILED,
+      QuarantineFile(test_file(), invalid_url, referrer_url(), std::string()));
+  GetExtendedAttributeNames(&attr_names);
+  EXPECT_FALSE(base::ContainsValue(attr_names, kSourceURLExtendedAttrName));
+  EXPECT_TRUE(base::ContainsValue(attr_names, kReferrerURLExtendedAttrName));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidReferrerURLTest) {
+  if (!is_xattr_supported())
+    return;
+  GURL invalid_url;
+  vector<string> attr_names;
+  EXPECT_EQ(
+      QuarantineFileResult::OK,
+      QuarantineFile(test_file(), source_url(), invalid_url, std::string()));
+  GetExtendedAttributeNames(&attr_names);
+  EXPECT_FALSE(base::ContainsValue(attr_names, kReferrerURLExtendedAttrName));
+  EXPECT_TRUE(IsFileQuarantined(test_file(), source_url(), GURL()));
+}
+
+TEST_F(QuarantineLinuxTest, InvalidURLsTest) {
+  if (!is_xattr_supported())
+    return;
+  GURL invalid_url;
+  vector<string> attr_names;
+  EXPECT_EQ(
+      QuarantineFileResult::ANNOTATION_FAILED,
+      QuarantineFile(test_file(), invalid_url, invalid_url, std::string()));
+  GetExtendedAttributeNames(&attr_names);
+  EXPECT_FALSE(base::ContainsValue(attr_names, kSourceURLExtendedAttrName));
+  EXPECT_FALSE(base::ContainsValue(attr_names, kReferrerURLExtendedAttrName));
+  EXPECT_FALSE(IsFileQuarantined(test_file(), GURL(), GURL()));
+}
+
+TEST_F(QuarantineLinuxTest, IsFileQuarantined) {
+  if (!is_xattr_supported())
+    return;
+  base::FilePath does_not_exist = test_dir().AppendASCII("a.jar");
+  EXPECT_FALSE(IsFileQuarantined(does_not_exist, GURL(), GURL()));
+
+  base::FilePath no_annotations = test_dir().AppendASCII("b.jar");
+  ASSERT_EQ(5, base::WriteFile(no_annotations, "Hello", 5));
+  EXPECT_FALSE(IsFileQuarantined(no_annotations, GURL(), GURL()));
+
+  base::FilePath source_only = test_dir().AppendASCII("c.jar");
+  ASSERT_EQ(5, base::WriteFile(source_only, "Hello", 5));
+  ASSERT_EQ(QuarantineFileResult::OK,
+            QuarantineFile(source_only, source_url(), GURL(), std::string()));
+  EXPECT_TRUE(IsFileQuarantined(source_only, source_url(), GURL()));
+  EXPECT_TRUE(IsFileQuarantined(source_only, GURL(), GURL()));
+  EXPECT_TRUE(IsFileQuarantined(source_only, GURL(), referrer_url()));
+  EXPECT_FALSE(IsFileQuarantined(source_only, referrer_url(), GURL()));
+
+  base::FilePath fully_annotated = test_dir().AppendASCII("d.jar");
+  ASSERT_EQ(5, base::WriteFile(fully_annotated, "Hello", 5));
+  ASSERT_EQ(QuarantineFileResult::OK,
+            QuarantineFile(fully_annotated, source_url(), referrer_url(),
+                           std::string()));
+  EXPECT_TRUE(IsFileQuarantined(fully_annotated, GURL(), GURL()));
+  EXPECT_TRUE(IsFileQuarantined(fully_annotated, source_url(), GURL()));
+  EXPECT_TRUE(IsFileQuarantined(fully_annotated, source_url(), referrer_url()));
+  EXPECT_TRUE(IsFileQuarantined(fully_annotated, GURL(), referrer_url()));
+  EXPECT_FALSE(IsFileQuarantined(fully_annotated, source_url(), source_url()));
+  EXPECT_FALSE(
+      IsFileQuarantined(fully_annotated, referrer_url(), referrer_url()));
+}
+
+}  // namespace download
diff --git a/components/download/quarantine/test_support.cc b/components/download/quarantine/test_support.cc
index 55ef062..e158051ae 100644
--- a/components/download/quarantine/test_support.cc
+++ b/components/download/quarantine/test_support.cc
@@ -6,7 +6,7 @@
 
 #include "build/build_config.h"
 
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
+#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
 
 namespace download {
 
@@ -18,4 +18,4 @@
 
 }  // namespace download
 
-#endif  // !WIN && !MAC
+#endif  // !WIN && !MAC && !LINUX
diff --git a/components/download/quarantine/test_support_linux.cc b/components/download/quarantine/test_support_linux.cc
new file mode 100644
index 0000000..63f8020
--- /dev/null
+++ b/components/download/quarantine/test_support_linux.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/quarantine/test_support.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "components/download/quarantine/common_linux.h"
+#include "url/gurl.h"
+
+namespace download {
+
+namespace {
+
+std::string GetExtendedFileAttribute(const char* path, const char* name) {
+  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
+  ssize_t len = getxattr(path, name, nullptr, 0);
+  if (len <= 0)
+    return std::string();
+
+  std::vector<char> buffer(len);
+  len = getxattr(path, name, buffer.data(), buffer.size());
+  if (len < static_cast<ssize_t>(buffer.size()))
+    return std::string();
+  return std::string(buffer.begin(), buffer.end());
+}
+
+}  // namespace
+
+bool IsFileQuarantined(const base::FilePath& file,
+                       const GURL& source_url,
+                       const GURL& referrer_url) {
+  if (!base::PathExists(file))
+    return false;
+
+  std::string url_value = GetExtendedFileAttribute(file.value().c_str(),
+                                                   kSourceURLExtendedAttrName);
+  if (source_url.is_empty())
+    return !url_value.empty();
+
+  if (source_url != GURL(url_value))
+    return false;
+
+  return !referrer_url.is_valid() ||
+         GURL(GetExtendedFileAttribute(file.value().c_str(),
+                                       kReferrerURLExtendedAttrName)) ==
+             referrer_url;
+}
+
+}  // namespace download
diff --git a/components/password_manager/core/browser/DEPS b/components/password_manager/core/browser/DEPS
index 305b6738..d17be605 100644
--- a/components/password_manager/core/browser/DEPS
+++ b/components/password_manager/core/browser/DEPS
@@ -10,6 +10,7 @@
   "+components/sync/driver",
   "+components/sync/engine",
   "+components/sync/model_impl",
+  "+components/sync/test",
   "+components/sync_preferences",
   "+components/url_formatter",
   "+components/variations",
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 0fd9e5e..23bbc35f 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -1568,6 +1568,23 @@
   return encrypted_password;
 }
 
+std::unique_ptr<syncer::MetadataBatch> LoginDatabase::GetAllSyncMetadata() {
+  std::unique_ptr<syncer::MetadataBatch> metadata_batch =
+      GetAllSyncEntityMetadata();
+  if (metadata_batch == nullptr) {
+    return nullptr;
+  }
+
+  std::unique_ptr<sync_pb::ModelTypeState> model_type_state =
+      GetModelTypeState();
+  if (model_type_state == nullptr) {
+    return nullptr;
+  }
+
+  metadata_batch->SetModelTypeState(*model_type_state);
+  return metadata_batch;
+}
+
 bool LoginDatabase::UpdateSyncMetadata(
     syncer::ModelType model_type,
     const std::string& storage_key,
@@ -1663,25 +1680,7 @@
 }
 
 std::unique_ptr<syncer::MetadataBatch>
-LoginDatabase::GetAllSyncMetadataForTesting() {
-  std::unique_ptr<syncer::MetadataBatch> metadata_batch =
-      GetAllSyncEntityMetadataForTesting();
-  if (metadata_batch == nullptr) {
-    return nullptr;
-  }
-
-  std::unique_ptr<sync_pb::ModelTypeState> model_type_state =
-      GetModelTypeStateForTesting();
-  if (model_type_state == nullptr) {
-    return nullptr;
-  }
-
-  metadata_batch->SetModelTypeState(*model_type_state);
-  return metadata_batch;
-}
-
-std::unique_ptr<syncer::MetadataBatch>
-LoginDatabase::GetAllSyncEntityMetadataForTesting() {
+LoginDatabase::GetAllSyncEntityMetadata() {
   auto metadata_batch = std::make_unique<syncer::MetadataBatch>();
   sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
                                           "SELECT storage_key, metadata FROM "
@@ -1705,8 +1704,7 @@
   return metadata_batch;
 }
 
-std::unique_ptr<sync_pb::ModelTypeState>
-LoginDatabase::GetModelTypeStateForTesting() {
+std::unique_ptr<sync_pb::ModelTypeState> LoginDatabase::GetModelTypeState() {
   auto state = std::make_unique<sync_pb::ModelTypeState>();
   sql::Statement s(db_.GetCachedStatement(
       SQL_FROM_HERE,
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h
index 7fceb88..dfa165b 100644
--- a/components/password_manager/core/browser/login_database.h
+++ b/components/password_manager/core/browser/login_database.h
@@ -17,10 +17,10 @@
 #include "build/build_config.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_change.h"
+#include "components/password_manager/core/browser/password_store_sync.h"
 #include "components/password_manager/core/browser/psl_matching_helper.h"
 #include "components/password_manager/core/browser/statistics_table.h"
 #include "components/sync/model/metadata_batch.h"
-#include "components/sync/model/sync_metadata_store.h"
 #include "components/sync/protocol/model_type_state.pb.h"
 #include "sql/database.h"
 #include "sql/meta_table.h"
@@ -43,7 +43,7 @@
 // Interface to the database storage of login information, intended as a helper
 // for PasswordStore on platforms that need internal storage of some or all of
 // the login information.
-class LoginDatabase : public syncer::SyncMetadataStore {
+class LoginDatabase : public PasswordStoreSync::MetadataStore {
  public:
   explicit LoginDatabase(const base::FilePath& db_path);
   ~LoginDatabase() override;
@@ -180,7 +180,8 @@
   // empty string if the row for this |form| is not found.
   std::string GetEncryptedPassword(const autofill::PasswordForm& form) const;
 
-  // syncer::SyncMetadataStore implementation.
+  // PasswordStoreSync::MetadataStore implementation.
+  std::unique_ptr<syncer::MetadataBatch> GetAllSyncMetadata() override;
   bool UpdateSyncMetadata(syncer::ModelType model_type,
                           const std::string& storage_key,
                           const sync_pb::EntityMetadata& metadata) override;
@@ -197,9 +198,6 @@
   bool BeginTransaction();
   bool CommitTransaction();
 
-  // Returns all the stored sync metadata. Returns null in case of failure.
-  std::unique_ptr<syncer::MetadataBatch> GetAllSyncMetadataForTesting();
-
   StatisticsTable& stats_table() { return stats_table_; }
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
@@ -287,10 +285,10 @@
 
   // Reads all the stored sync entities metadata in a MetadataBatch. Returns
   // nullptr in case of failure.
-  std::unique_ptr<syncer::MetadataBatch> GetAllSyncEntityMetadataForTesting();
+  std::unique_ptr<syncer::MetadataBatch> GetAllSyncEntityMetadata();
 
   // Reads the stored ModelTypeState. Returns nullptr in case of failure.
-  std::unique_ptr<sync_pb::ModelTypeState> GetModelTypeStateForTesting();
+  std::unique_ptr<sync_pb::ModelTypeState> GetModelTypeState();
 
   // Overwrites |forms| with credentials retrieved from |statement|. If
   // |matched_form| is not null, filters out all results but those PSL-matching
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index 34ef63fd..6868002ba 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -1874,7 +1874,7 @@
 
 TEST_F(LoginDatabaseTest, NoMetadata) {
   std::unique_ptr<syncer::MetadataBatch> metadata_batch =
-      db().GetAllSyncMetadataForTesting();
+      db().GetAllSyncMetadata();
   ASSERT_THAT(metadata_batch, testing::NotNull());
   EXPECT_EQ(0u, metadata_batch->TakeAllMetadata().size());
   EXPECT_EQ(sync_pb::ModelTypeState().SerializeAsString(),
@@ -1901,7 +1901,7 @@
       db().UpdateSyncMetadata(syncer::PASSWORDS, kStorageKey2, metadata));
 
   std::unique_ptr<syncer::MetadataBatch> metadata_batch =
-      db().GetAllSyncMetadataForTesting();
+      db().GetAllSyncMetadata();
   ASSERT_THAT(metadata_batch, testing::NotNull());
 
   EXPECT_TRUE(metadata_batch->GetModelTypeState().initial_sync_done());
@@ -1917,7 +1917,7 @@
   model_type_state.set_initial_sync_done(false);
   EXPECT_TRUE(db().UpdateModelTypeState(syncer::PASSWORDS, model_type_state));
 
-  metadata_batch = db().GetAllSyncMetadataForTesting();
+  metadata_batch = db().GetAllSyncMetadata();
   ASSERT_THAT(metadata_batch, testing::NotNull());
   EXPECT_FALSE(metadata_batch->GetModelTypeState().initial_sync_done());
 }
@@ -1939,7 +1939,7 @@
   EXPECT_TRUE(db().ClearSyncMetadata(syncer::PASSWORDS, kStorageKey));
 
   std::unique_ptr<syncer::MetadataBatch> metadata_batch =
-      db().GetAllSyncMetadataForTesting();
+      db().GetAllSyncMetadata();
   ASSERT_THAT(metadata_batch, testing::NotNull());
 
   // It shouldn't be there any more.
@@ -1949,7 +1949,7 @@
 
   // Now delete the model type state.
   EXPECT_TRUE(db().ClearModelTypeState(syncer::PASSWORDS));
-  metadata_batch = db().GetAllSyncMetadataForTesting();
+  metadata_batch = db().GetAllSyncMetadata();
   ASSERT_THAT(metadata_batch, testing::NotNull());
 
   EXPECT_EQ(sync_pb::ModelTypeState().SerializeAsString(),
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h
index 3437806..e18bd59c 100644
--- a/components/password_manager/core/browser/mock_password_store.h
+++ b/components/password_manager/core/browser/mock_password_store.h
@@ -92,7 +92,7 @@
   MOCK_METHOD0(CommitTransaction, bool());
   MOCK_METHOD1(ReadAllLogins, bool(PrimaryKeyToFormMap*));
   MOCK_METHOD1(RemoveLoginByPrimaryKeySync, PasswordStoreChangeList(int));
-  MOCK_METHOD0(GetMetadataStore, syncer::SyncMetadataStore*());
+  MOCK_METHOD0(GetMetadataStore, PasswordStoreSync::MetadataStore*());
 
   PasswordStoreSync* GetSyncInterface() { return this; }
 
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc
index ee67edb..8c894ae 100644
--- a/components/password_manager/core/browser/password_store_default.cc
+++ b/components/password_manager/core/browser/password_store_default.cc
@@ -254,7 +254,7 @@
   return PasswordStoreChangeList();
 }
 
-syncer::SyncMetadataStore* PasswordStoreDefault::GetMetadataStore() {
+PasswordStoreSync::MetadataStore* PasswordStoreDefault::GetMetadataStore() {
   return login_db_.get();
 }
 
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h
index ecc4e98..6b981af 100644
--- a/components/password_manager/core/browser/password_store_default.h
+++ b/components/password_manager/core/browser/password_store_default.h
@@ -89,7 +89,7 @@
   bool CommitTransaction() override;
   bool ReadAllLogins(PrimaryKeyToFormMap* key_to_form_map) override;
   PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
-  syncer::SyncMetadataStore* GetMetadataStore() override;
+  PasswordStoreSync::MetadataStore* GetMetadataStore() override;
 
   inline bool DeleteAndRecreateDatabaseFile() {
     return login_db_->DeleteAndRecreateDatabaseFile();
diff --git a/components/password_manager/core/browser/password_store_sync.h b/components/password_manager/core/browser/password_store_sync.h
index d570401b..6a93de3 100644
--- a/components/password_manager/core/browser/password_store_sync.h
+++ b/components/password_manager/core/browser/password_store_sync.h
@@ -12,13 +12,14 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "components/password_manager/core/browser/password_store_change.h"
+#include "components/sync/model/sync_metadata_store.h"
 
 namespace autofill {
 struct PasswordForm;
 }
 
 namespace syncer {
-class SyncMetadataStore;
+class MetadataBatch;
 }
 
 namespace password_manager {
@@ -41,6 +42,13 @@
 // thread only.
 class PasswordStoreSync {
  public:
+  class MetadataStore : public syncer::SyncMetadataStore {
+   public:
+    // Read all the stored metadata for passwords and fill |metadata_batch|
+    // with it.
+    virtual std::unique_ptr<syncer::MetadataBatch> GetAllSyncMetadata() = 0;
+  };
+
   PasswordStoreSync();
 
   // TODO(http://crbug.com/925307) Move the following 2 APIs to PasswordStore
@@ -95,7 +103,7 @@
 
   // Returns a SyncMetadataStore that sync machinery would use to persist the
   // sync metadata.
-  virtual syncer::SyncMetadataStore* GetMetadataStore() = 0;
+  virtual MetadataStore* GetMetadataStore() = 0;
 
  protected:
   virtual ~PasswordStoreSync();
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc
index fffe796..d6c41f9 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge.cc
+++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -135,10 +135,15 @@
     : ModelTypeSyncBridge(std::move(change_processor)),
       password_store_sync_(password_store_sync) {
   DCHECK(password_store_sync_);
-  // TODO(crbug.com/902349): Read the actual metadata from the PasswordStoreSync
-  // be introducing a new API to read them.
-  this->change_processor()->ModelReadyToSync(
-      std::make_unique<syncer::MetadataBatch>());
+  DCHECK(password_store_sync_->GetMetadataStore());
+  std::unique_ptr<syncer::MetadataBatch> batch =
+      password_store_sync_->GetMetadataStore()->GetAllSyncMetadata();
+  if (!batch) {
+    this->change_processor()->ReportError(
+        {FROM_HERE, "Failed reading passwords metadata from password store."});
+    return;
+  }
+  this->change_processor()->ModelReadyToSync(std::move(batch));
 }
 
 PasswordSyncBridge::~PasswordSyncBridge() = default;
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
index a0c6f79f..3f38d40 100644
--- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
+++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -18,6 +18,7 @@
 #include "components/sync/model/mock_model_type_change_processor.h"
 #include "components/sync/model_impl/in_memory_metadata_change_list.h"
 #include "components/sync/model_impl/sync_metadata_store_change_list.h"
+#include "components/sync/test/test_matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -167,11 +168,12 @@
   DISALLOW_COPY_AND_ASSIGN(FakeDatabase);
 };
 
-class MockSyncMetadataStore : public syncer::SyncMetadataStore {
+class MockSyncMetadataStore : public PasswordStoreSync::MetadataStore {
  public:
   MockSyncMetadataStore() = default;
   ~MockSyncMetadataStore() = default;
 
+  MOCK_METHOD0(GetAllSyncMetadata, std::unique_ptr<syncer::MetadataBatch>());
   MOCK_METHOD3(UpdateSyncMetadata,
                bool(syncer::ModelType,
                     const std::string&,
@@ -203,16 +205,14 @@
   MOCK_METHOD1(NotifyLoginsChanged, void(const PasswordStoreChangeList&));
   MOCK_METHOD0(BeginTransaction, bool());
   MOCK_METHOD0(CommitTransaction, bool());
-  MOCK_METHOD0(GetMetadataStore, syncer::SyncMetadataStore*());
+  MOCK_METHOD0(GetMetadataStore, PasswordStoreSync::MetadataStore*());
 };
 
 }  // namespace
 
 class PasswordSyncBridgeTest : public testing::Test {
  public:
-  PasswordSyncBridgeTest()
-      : bridge_(mock_processor_.CreateForwardingProcessor(),
-                &mock_password_store_sync_) {
+  PasswordSyncBridgeTest() {
     ON_CALL(mock_password_store_sync_, GetMetadataStore())
         .WillByDefault(testing::Return(&mock_sync_metadata_store_sync_));
     ON_CALL(mock_password_store_sync_, ReadAllLogins(_))
@@ -223,6 +223,11 @@
         .WillByDefault(Invoke(&fake_db_, &FakeDatabase::UpdateLogin));
     ON_CALL(mock_password_store_sync_, RemoveLoginByPrimaryKeySync(_))
         .WillByDefault(Invoke(&fake_db_, &FakeDatabase::RemoveLogin));
+
+    bridge_ = std::make_unique<PasswordSyncBridge>(
+        mock_processor_.CreateForwardingProcessor(),
+        &mock_password_store_sync_);
+
     // It's the responsibility of the PasswordStoreSync to inform the bridge
     // about changes in the password store. The bridge notifies the
     // PasswordStoreSync about the new changes even if they are initiated by the
@@ -231,6 +236,9 @@
         .WillByDefault(
             Invoke(bridge(), &PasswordSyncBridge::ActOnPasswordStoreChanges));
 
+    ON_CALL(mock_sync_metadata_store_sync_, GetAllSyncMetadata())
+        .WillByDefault(
+            []() { return std::make_unique<syncer::MetadataBatch>(); });
     ON_CALL(mock_sync_metadata_store_sync_, UpdateSyncMetadata(_, _, _))
         .WillByDefault(testing::Return(true));
     ON_CALL(mock_sync_metadata_store_sync_, ClearSyncMetadata(_, _))
@@ -246,11 +254,11 @@
   base::Optional<sync_pb::PasswordSpecifics> GetDataFromBridge(
       const std::string& storage_key) {
     std::unique_ptr<syncer::DataBatch> batch;
-    bridge_.GetData({storage_key},
-                    base::BindLambdaForTesting(
-                        [&](std::unique_ptr<syncer::DataBatch> in_batch) {
-                          batch = std::move(in_batch);
-                        }));
+    bridge_->GetData({storage_key},
+                     base::BindLambdaForTesting(
+                         [&](std::unique_ptr<syncer::DataBatch> in_batch) {
+                           batch = std::move(in_batch);
+                         }));
     EXPECT_THAT(batch, NotNull());
     if (!batch || !batch->HasNext()) {
       return base::nullopt;
@@ -263,7 +271,7 @@
 
   FakeDatabase* fake_db() { return &fake_db_; }
 
-  PasswordSyncBridge* bridge() { return &bridge_; }
+  PasswordSyncBridge* bridge() { return bridge_.get(); }
 
   syncer::MockModelTypeChangeProcessor& mock_processor() {
     return mock_processor_;
@@ -282,7 +290,7 @@
   testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_;
   testing::NiceMock<MockSyncMetadataStore> mock_sync_metadata_store_sync_;
   testing::NiceMock<MockPasswordStoreSync> mock_password_store_sync_;
-  PasswordSyncBridge bridge_;
+  std::unique_ptr<PasswordSyncBridge> bridge_;
 };
 
 TEST_F(PasswordSyncBridgeTest, ShouldComputeClientTagHash) {
@@ -307,7 +315,7 @@
       PasswordStoreChange::UPDATE, MakePasswordForm(kSignonRealm2), /*id=*/2));
   changes.push_back(PasswordStoreChange(
       PasswordStoreChange::REMOVE, MakePasswordForm(kSignonRealm3), /*id=*/3));
-  syncer::SyncMetadataStore* store =
+  PasswordStoreSync::MetadataStore* store =
       mock_password_store_sync()->GetMetadataStore();
   EXPECT_CALL(mock_processor(),
               Put("1", EntityDataHasSignonRealm(kSignonRealm1),
@@ -580,4 +588,24 @@
   }
 }
 
+TEST_F(PasswordSyncBridgeTest,
+       ShouldCallModelReadyUponConstructionWithMetadata) {
+  ON_CALL(*mock_sync_metadata_store_sync(), GetAllSyncMetadata())
+      .WillByDefault([&]() {
+        sync_pb::ModelTypeState model_type_state;
+        model_type_state.set_initial_sync_done(true);
+        auto metadata_batch = std::make_unique<syncer::MetadataBatch>();
+        metadata_batch->SetModelTypeState(model_type_state);
+        metadata_batch->AddMetadata("storage_key", sync_pb::EntityMetadata());
+        return metadata_batch;
+      });
+
+  EXPECT_CALL(mock_processor(), ModelReadyToSync(MetadataBatchContains(
+                                    /*state=*/syncer::HasInitialSyncDone(),
+                                    /*entities=*/testing::SizeIs(1))));
+
+  PasswordSyncBridge bridge(mock_processor().CreateForwardingProcessor(),
+                            mock_password_store_sync());
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc
index 58ecf67..4d64475 100644
--- a/components/password_manager/core/browser/test_password_store.cc
+++ b/components/password_manager/core/browser/test_password_store.cc
@@ -231,7 +231,7 @@
   return PasswordStoreChangeList();
 }
 
-syncer::SyncMetadataStore* TestPasswordStore::GetMetadataStore() {
+PasswordStoreSync::MetadataStore* TestPasswordStore::GetMetadataStore() {
   NOTIMPLEMENTED();
   return nullptr;
 }
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h
index a7c6d71b..88d60c77 100644
--- a/components/password_manager/core/browser/test_password_store.h
+++ b/components/password_manager/core/browser/test_password_store.h
@@ -92,7 +92,7 @@
   bool CommitTransaction() override;
   bool ReadAllLogins(PrimaryKeyToFormMap* key_to_form_map) override;
   PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
-  syncer::SyncMetadataStore* GetMetadataStore() override;
+  PasswordStoreSync::MetadataStore* GetMetadataStore() override;
 
  private:
   PasswordMap stored_passwords_;
diff --git a/components/payments/core/currency_formatter_unittest.cc b/components/payments/core/currency_formatter_unittest.cc
index fa76a7e..491dd19 100644
--- a/components/payments/core/currency_formatter_unittest.cc
+++ b/components/payments/core/currency_formatter_unittest.cc
@@ -55,7 +55,7 @@
             formatter.formatted_currency_code());
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     CurrencyAmounts,
     PaymentsCurrencyFormatterTest,
     testing::Values(
diff --git a/components/payments/core/payment_details_validation_unittest.cc b/components/payments/core/payment_details_validation_unittest.cc
index 2dc3629..0f3bacb 100644
--- a/components/payments/core/payment_details_validation_unittest.cc
+++ b/components/payments/core/payment_details_validation_unittest.cc
@@ -56,7 +56,7 @@
   EXPECT_EQ(GetParam().expect_valid, ValidatePaymentDetails(details, &unused));
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     TestCases,
     PaymentDetailsValidationTest,
     ::testing::Values(PaymentDetailsValidationTestCase(R"(
diff --git a/components/payments/core/payments_validators_unittest.cc b/components/payments/core/payments_validators_unittest.cc
index 81a4eae1..e19f67d 100644
--- a/components/payments/core/payments_validators_unittest.cc
+++ b/components/payments/core/payments_validators_unittest.cc
@@ -43,7 +43,7 @@
                 GetParam().code, nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     CurrencyCodes,
     PaymentsCurrencyValidatorTest,
     testing::Values(
@@ -94,7 +94,7 @@
                                                               nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     Amounts,
     PaymentsAmountValidatorTest,
     testing::Values(TestCase("0", true),
@@ -139,15 +139,15 @@
                 GetParam().input, nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(CountryCodes,
-                        PaymentsRegionValidatorTest,
-                        testing::Values(TestCase("US", true),
-                                        // Invalid country code formats
-                                        TestCase("U1", false),
-                                        TestCase("U", false),
-                                        TestCase("us", false),
-                                        TestCase("USA", false),
-                                        TestCase("", false)));
+INSTANTIATE_TEST_SUITE_P(CountryCodes,
+                         PaymentsRegionValidatorTest,
+                         testing::Values(TestCase("US", true),
+                                         // Invalid country code formats
+                                         TestCase("U1", false),
+                                         TestCase("U", false),
+                                         TestCase("us", false),
+                                         TestCase("USA", false),
+                                         TestCase("", false)));
 
 class PaymentsLanguageValidatorTest : public testing::TestWithParam<TestCase> {
 };
@@ -165,17 +165,17 @@
                 GetParam().input, nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(LanguageCodes,
-                        PaymentsLanguageValidatorTest,
-                        testing::Values(TestCase("", true),
-                                        TestCase("en", true),
-                                        TestCase("eng", true),
-                                        // Invalid language code formats
-                                        TestCase("e1", false),
-                                        TestCase("en1", false),
-                                        TestCase("e", false),
-                                        TestCase("engl", false),
-                                        TestCase("EN", false)));
+INSTANTIATE_TEST_SUITE_P(LanguageCodes,
+                         PaymentsLanguageValidatorTest,
+                         testing::Values(TestCase("", true),
+                                         TestCase("en", true),
+                                         TestCase("eng", true),
+                                         // Invalid language code formats
+                                         TestCase("e1", false),
+                                         TestCase("en1", false),
+                                         TestCase("e", false),
+                                         TestCase("engl", false),
+                                         TestCase("EN", false)));
 
 class PaymentsScriptValidatorTest : public testing::TestWithParam<TestCase> {};
 
@@ -192,17 +192,17 @@
                 GetParam().input, nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(ScriptCodes,
-                        PaymentsScriptValidatorTest,
-                        testing::Values(TestCase("", true),
-                                        TestCase("Latn", true),
-                                        // Invalid script code formats
-                                        TestCase("Lat1", false),
-                                        TestCase("1lat", false),
-                                        TestCase("Latin", false),
-                                        TestCase("Lat", false),
-                                        TestCase("latn", false),
-                                        TestCase("LATN", false)));
+INSTANTIATE_TEST_SUITE_P(ScriptCodes,
+                         PaymentsScriptValidatorTest,
+                         testing::Values(TestCase("", true),
+                                         TestCase("Latn", true),
+                                         // Invalid script code formats
+                                         TestCase("Lat1", false),
+                                         TestCase("1lat", false),
+                                         TestCase("Latin", false),
+                                         TestCase("Lat", false),
+                                         TestCase("latn", false),
+                                         TestCase("LATN", false)));
 
 struct LanguageTagTestCase {
   LanguageTagTestCase(const char* language_tag,
@@ -236,7 +236,7 @@
       PaymentsValidators::IsValidScriptCodeFormat(script_code, nullptr));
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     LanguageTags,
     PaymentsLanguageTagSplitTest,
     testing::Values(LanguageTagTestCase("", "", ""),
@@ -324,7 +324,7 @@
       << error_message;
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     PaymentValidationErrorss,
     PaymentsErrorMessageValidatorTest,
     testing::Values(
diff --git a/components/safe_browsing/password_protection/BUILD.gn b/components/safe_browsing/password_protection/BUILD.gn
index c9303ff..2fc4240 100644
--- a/components/safe_browsing/password_protection/BUILD.gn
+++ b/components/safe_browsing/password_protection/BUILD.gn
@@ -11,6 +11,8 @@
       "password_protection_request.h",
       "password_protection_service.cc",
       "password_protection_service.h",
+      "visual_utils.cc",
+      "visual_utils.h",
     ]
 
     public_deps = [
@@ -60,6 +62,7 @@
   if (!is_android && !is_ios) {
     sources = [
       "password_protection_service_unittest.cc",
+      "visual_utils_unittest.cc",
     ]
     deps = [
       ":mock_password_protection",
diff --git a/components/safe_browsing/password_protection/DEPS b/components/safe_browsing/password_protection/DEPS
index 9fb70be..8c7bb1d 100644
--- a/components/safe_browsing/password_protection/DEPS
+++ b/components/safe_browsing/password_protection/DEPS
@@ -11,5 +11,6 @@
   "+services/network/public",
   "+services/network/test",
   "+ui/gfx/geometry",
+  "+third_party/skia/include",
 ]
 
diff --git a/components/safe_browsing/password_protection/visual_utils.cc b/components/safe_browsing/password_protection/visual_utils.cc
new file mode 100644
index 0000000..e24d3ad
--- /dev/null
+++ b/components/safe_browsing/password_protection/visual_utils.cc
@@ -0,0 +1,71 @@
+// 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 <unordered_map>
+
+#include "base/numerics/checked_math.h"
+#include "components/safe_browsing/password_protection/visual_utils.h"
+
+namespace safe_browsing {
+namespace visual_utils {
+
+// A QuantizedColor takes the highest 3 bits of R, G, and B, and concatenates
+// them.
+QuantizedColor SkColorToQuantizedColor(SkColor color) {
+  return (SkColorGetR(color) >> 5) << 6 | (SkColorGetG(color) >> 5) << 3 |
+         (SkColorGetB(color) >> 5);
+}
+
+int GetQuantizedR(QuantizedColor color) {
+  return color >> 6;
+}
+
+int GetQuantizedG(QuantizedColor color) {
+  return (color >> 3) & 7;
+}
+
+int GetQuantizedB(QuantizedColor color) {
+  return color & 7;
+}
+
+bool GetHistogramForImage(const SkBitmap& image,
+                          VisualFeatures::ColorHistogram* histogram) {
+  if (image.drawsNothing())
+    return false;
+
+  std::unordered_map<QuantizedColor, int> color_to_count;
+  std::unordered_map<QuantizedColor, double> color_to_total_x;
+  std::unordered_map<QuantizedColor, double> color_to_total_y;
+  for (int x = 0; x < image.width(); x++) {
+    for (int y = 0; y < image.height(); y++) {
+      QuantizedColor color = SkColorToQuantizedColor(image.getColor(x, y));
+      color_to_count[color]++;
+      color_to_total_x[color] += static_cast<float>(x) / image.width();
+      color_to_total_y[color] += static_cast<float>(y) / image.height();
+    }
+  }
+
+  int normalization_factor;
+  if (!base::CheckMul(image.width(), image.height())
+           .AssignIfValid(&normalization_factor))
+    return false;
+
+  for (const auto& entry : color_to_count) {
+    const QuantizedColor& color = entry.first;
+    int count = entry.second;
+
+    VisualFeatures::ColorHistogramBin* bin = histogram->add_bins();
+    bin->set_weight(static_cast<float>(count) / normalization_factor);
+    bin->set_centroid_x(color_to_total_x[color] / count);
+    bin->set_centroid_y(color_to_total_y[color] / count);
+    bin->set_quantized_r(GetQuantizedR(color));
+    bin->set_quantized_g(GetQuantizedG(color));
+    bin->set_quantized_b(GetQuantizedB(color));
+  }
+
+  return true;
+}
+
+}  // namespace visual_utils
+}  // namespace safe_browsing
diff --git a/components/safe_browsing/password_protection/visual_utils.h b/components/safe_browsing/password_protection/visual_utils.h
new file mode 100644
index 0000000..269fefe
--- /dev/null
+++ b/components/safe_browsing/password_protection/visual_utils.h
@@ -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.
+
+#ifndef COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_VISUAL_UTILS_H_
+#define COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_VISUAL_UTILS_H_
+
+#include "components/safe_browsing/proto/csd.pb.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace safe_browsing {
+namespace visual_utils {
+
+using QuantizedColor = uint32_t;
+
+// Utility methods for working with QuantizedColors.
+QuantizedColor SkColorToQuantizedColor(SkColor color);
+int GetQuantizedR(QuantizedColor color);
+int GetQuantizedG(QuantizedColor color);
+int GetQuantizedB(QuantizedColor color);
+
+// Computes the color histogram for the image. This buckets the pixels according
+// to their QuantizedColor, then reports their weight and centroid.
+bool GetHistogramForImage(const SkBitmap& image,
+                          VisualFeatures::ColorHistogram* histogram);
+
+}  // namespace visual_utils
+}  // namespace safe_browsing
+
+#endif  // COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_VISUAL_UTILS_H_
diff --git a/components/safe_browsing/password_protection/visual_utils_unittest.cc b/components/safe_browsing/password_protection/visual_utils_unittest.cc
new file mode 100644
index 0000000..049bfa7
--- /dev/null
+++ b/components/safe_browsing/password_protection/visual_utils_unittest.cc
@@ -0,0 +1,103 @@
+// 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 "components/safe_browsing/password_protection/visual_utils.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+namespace visual_utils {
+
+using ::testing::FloatEq;
+
+TEST(VisualUtilsTest, TestSkColorToQuantizedColor) {
+  // Test quantization
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 31)), 0u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 32)), 1u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 31, 0)), 0u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 32, 0)), 8u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(31, 0, 0)), 0u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(32, 0, 0)), 64u);
+
+  // Test composition of RGB quantized values
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 0)), 0u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 255)), 7u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 255, 255)), 63u);
+  EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(255, 255, 255)), 511u);
+}
+
+TEST(VisualUtilsTest, GetQuantizedR) {
+  EXPECT_EQ(GetQuantizedR(0), 0);
+  EXPECT_EQ(GetQuantizedR(64), 1);
+  EXPECT_EQ(GetQuantizedR(448), 7);
+}
+
+TEST(VisualUtilsTest, GetQuantizedG) {
+  EXPECT_EQ(GetQuantizedG(0), 0);
+  EXPECT_EQ(GetQuantizedG(8), 1);
+  EXPECT_EQ(GetQuantizedG(56), 7);
+}
+
+TEST(VisualUtilsTest, GetQuantizedB) {
+  EXPECT_EQ(GetQuantizedB(0), 0);
+  EXPECT_EQ(GetQuantizedB(1), 1);
+  EXPECT_EQ(GetQuantizedB(7), 7);
+}
+
+TEST(VisualUtilsTest, GetHistogramForImageWhite) {
+  VisualFeatures::ColorHistogram histogram;
+  SkBitmap bitmap;
+
+  bitmap.allocN32Pixels(200, 200);
+  for (int x = 0; x < 200; x++)
+    for (int y = 0; y < 200; y++)
+      *bitmap.getAddr32(x, y) = SkColorSetRGB(255, 255, 255);
+
+  ASSERT_TRUE(GetHistogramForImage(bitmap, &histogram));
+  ASSERT_EQ(histogram.bins_size(), 1);
+  EXPECT_THAT(histogram.bins(0).centroid_x(),
+              FloatEq(0.4975));  // All pixels are the same color, so centroid_x
+                                 // is (0+1+...+199)/200/200 = 0.4975
+  EXPECT_THAT(histogram.bins(0).centroid_y(), FloatEq(0.4975));
+  EXPECT_EQ(histogram.bins(0).quantized_r(), 7);
+  EXPECT_EQ(histogram.bins(0).quantized_g(), 7);
+  EXPECT_EQ(histogram.bins(0).quantized_b(), 7);
+  EXPECT_THAT(histogram.bins(0).weight(), FloatEq(1.0));
+}
+
+TEST(VisualUtilsTest, GetHistogramForImageHalfWhiteHalfBlack) {
+  VisualFeatures::ColorHistogram histogram;
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(200, 200);
+
+  // Draw black over half the image.
+  for (int x = 0; x < 200; x++)
+    for (int y = 0; y < 100; y++)
+      *bitmap.getAddr32(x, y) = SkColorSetRGB(0, 0, 0);
+
+  for (int x = 0; x < 200; x++)
+    for (int y = 100; y < 200; y++)
+      *bitmap.getAddr32(x, y) = SkColorSetRGB(255, 255, 255);
+
+  ASSERT_TRUE(GetHistogramForImage(bitmap, &histogram));
+  ASSERT_EQ(histogram.bins_size(), 2);
+
+  EXPECT_THAT(histogram.bins(0).centroid_x(), FloatEq(0.4975));
+  EXPECT_THAT(histogram.bins(0).centroid_y(), FloatEq(0.7475));
+  EXPECT_EQ(histogram.bins(0).quantized_r(), 7);
+  EXPECT_EQ(histogram.bins(0).quantized_g(), 7);
+  EXPECT_EQ(histogram.bins(0).quantized_b(), 7);
+  EXPECT_THAT(histogram.bins(0).weight(), FloatEq(0.5));
+
+  EXPECT_THAT(histogram.bins(1).centroid_x(), FloatEq(0.4975));
+  EXPECT_THAT(histogram.bins(1).centroid_y(), FloatEq(0.2475));
+  EXPECT_EQ(histogram.bins(1).quantized_r(), 0);
+  EXPECT_EQ(histogram.bins(1).quantized_g(), 0);
+  EXPECT_EQ(histogram.bins(1).quantized_b(), 0);
+  EXPECT_THAT(histogram.bins(1).weight(), FloatEq(0.5));
+}
+
+}  // namespace visual_utils
+}  // namespace safe_browsing
diff --git a/components/services/heap_profiling/heap_profiling_service.cc b/components/services/heap_profiling/heap_profiling_service.cc
index 40041f7..eb6a37a 100644
--- a/components/services/heap_profiling/heap_profiling_service.cc
+++ b/components/services/heap_profiling/heap_profiling_service.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
diff --git a/components/services/unzip/public/cpp/test_unzip_service.cc b/components/services/unzip/public/cpp/test_unzip_service.cc
index b884659..9f54cf61 100644
--- a/components/services/unzip/public/cpp/test_unzip_service.cc
+++ b/components/services/unzip/public/cpp/test_unzip_service.cc
@@ -4,6 +4,8 @@
 
 #include "components/services/unzip/public/cpp/test_unzip_service.h"
 
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+
 namespace unzip {
 
 CrashyUnzipService::CrashyUnzipService(
diff --git a/components/services/unzip/unzipper_impl.cc b/components/services/unzip/unzipper_impl.cc
index b9a5aa1..370b539 100644
--- a/components/services/unzip/unzipper_impl.cc
+++ b/components/services/unzip/unzipper_impl.cc
@@ -11,6 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "third_party/zlib/google/zip.h"
 #include "third_party/zlib/google/zip_reader.h"
 
diff --git a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
index bd425be..f669570 100644
--- a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
+++ b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
@@ -9,6 +9,8 @@
 #include <vector>
 
 #include "base/no_destructor.h"
+#include "services/device/public/mojom/mtp_file_entry.mojom.h"
+#include "services/device/public/mojom/mtp_storage_info.mojom.h"
 
 namespace storage_monitor {
 
diff --git a/components/translate/core/browser/resources/translate.js b/components/translate/core/browser/resources/translate.js
index fb37e42..802a2868 100644
--- a/components/translate/core/browser/resources/translate.js
+++ b/components/translate/core/browser/resources/translate.js
@@ -104,12 +104,18 @@
 
   /**
    * Callback invoked when Translate Element's ready state is known.
+   * Will only be invoked once to indicate successful or failed initialization.
+   * In the failure case, errorCode() and error() will indicate the reason.
+   * Only used on iOS.
    * @type {function}
    */
   var readyCallback;
 
   /**
    * Callback invoked when Translate Element's translation result is known.
+   * Will only be invoked once to indicate successful or failed translation.
+   * In the failure case, errorCode() and error() will indicate the reason.
+   * Only used on iOS.
    * @type {function}
    */
   var resultCallback;
@@ -150,6 +156,15 @@
       lib.restore();
       invokeResultCallback();
     }
+    // Translate works differently depending on the prescence of the native
+    // IntersectionObserver APIs.
+    // If it is available, translate will occur incrementally as the user
+    // scrolls elements into view, and this method will be called continuously
+    // with |opt_finished| always set as true.
+    // On the other hand, if it is unavailable, the entire page will be
+    // translated at once in a piece meal manner, and this method may still be
+    // called several times, though only the last call will have |opt_finished|
+    // set as true.
     if (finished) {
       endTime = performance.now();
       invokeResultCallback();
@@ -159,12 +174,14 @@
   function invokeReadyCallback() {
     if (readyCallback) {
       readyCallback();
+      readyCallback = null;
     }
   }
 
   function invokeResultCallback() {
     if (resultCallback) {
       resultCallback();
+      resultCallback = null;
     }
   }
 
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 3855b1a..1f4c047 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -698,9 +698,7 @@
 #endif  // !OS_ANDROID
 
 #if defined(OS_WIN)
-    // Enable exporting of events to ETW if requested on the command line.
-    if (command_line.HasSwitch(switches::kTraceExportEventsToETW))
-      base::trace_event::TraceEventETWExport::EnableETWExport();
+    base::trace_event::TraceEventETWExport::EnableETWExport();
 #endif  // OS_WIN
 
 #if !defined(OS_ANDROID)
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index c4d780c..b65ac6a 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -201,6 +201,7 @@
     "//ui/base",
     "//ui/base:buildflags",
     "//ui/base/clipboard",
+    "//ui/base/idle",
     "//ui/base/ime",
     "//ui/display",
     "//ui/display/types",
@@ -399,14 +400,10 @@
     "appcache/appcache_subresource_url_factory.h",
     "appcache/appcache_update_job.cc",
     "appcache/appcache_update_job.h",
-    "appcache/appcache_update_request_base.cc",
-    "appcache/appcache_update_request_base.h",
     "appcache/appcache_update_url_fetcher.cc",
     "appcache/appcache_update_url_fetcher.h",
     "appcache/appcache_update_url_loader_request.cc",
     "appcache/appcache_update_url_loader_request.h",
-    "appcache/appcache_update_url_request.cc",
-    "appcache/appcache_update_url_request.h",
     "appcache/appcache_url_loader_job.cc",
     "appcache/appcache_url_loader_job.h",
     "appcache/appcache_url_loader_request.cc",
@@ -1132,8 +1129,6 @@
     "manifest/manifest_manager_host.h",
     "media/android/browser_gpu_video_accelerator_factories.cc",
     "media/android/browser_gpu_video_accelerator_factories.h",
-    "media/android/browser_media_player_manager.cc",
-    "media/android/browser_media_player_manager.h",
     "media/android/media_player_renderer.cc",
     "media/android/media_player_renderer.h",
     "media/android/media_player_renderer_web_contents_observer.cc",
diff --git a/content/browser/appcache/appcache_host.cc b/content/browser/appcache/appcache_host.cc
index 501817f..51c066a 100644
--- a/content/browser/appcache/appcache_host.cc
+++ b/content/browser/appcache/appcache_host.cc
@@ -92,6 +92,17 @@
   storage()->CancelDelegateCallbacks(this);
   if (service()->quota_manager_proxy() && !origin_in_use_.opaque())
     service()->quota_manager_proxy()->NotifyOriginNoLongerInUse(origin_in_use_);
+
+  // Run pending callbacks in case we get destroyed with pending callbacks while
+  // the mojo connection is still open.
+  if (pending_get_status_callback_) {
+    std::move(pending_get_status_callback_)
+        .Run(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED);
+  }
+  if (pending_swap_cache_callback_)
+    std::move(pending_swap_cache_callback_).Run(false);
+  if (pending_start_update_callback_)
+    std::move(pending_start_update_callback_).Run(false);
 }
 
 void AppCacheHost::AddObserver(Observer* observer) {
diff --git a/content/browser/appcache/appcache_host.h b/content/browser/appcache/appcache_host.h
index ad140ba..315ab55 100644
--- a/content/browser/appcache/appcache_host.h
+++ b/content/browser/appcache/appcache_host.h
@@ -341,6 +341,10 @@
   // only be one type of callback pending. Also, we have to wait until we have a
   // cache selection prior to responding to these calls, as cache selection
   // involves async loading of a cache or a group from storage.
+  // If any of these callbacks are non-null at the time this AppCacheHost is
+  // destroyed, we have to make sure that they still get called, as the mojo
+  // pipe the callbacks are associated with will outlive this. So make sure to
+  // update the destructor if adding more callbacks here.
   GetStatusCallback pending_get_status_callback_;
   StartUpdateCallback pending_start_update_callback_;
   SwapCacheCallback pending_swap_cache_callback_;
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc
index 2a66add4..f472a55 100644
--- a/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -21,6 +21,8 @@
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task/post_task.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread.h"
@@ -34,6 +36,9 @@
 #include "content/browser/appcache/appcache_interceptor.h"
 #include "content/browser/appcache/appcache_request_handler.h"
 #include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_url_loader_request.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/net_errors.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_response_headers.h"
@@ -42,6 +47,9 @@
 #include "net/url_request/url_request_job_factory_impl.h"
 #include "net/url_request/url_request_test_job.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "services/network/test/test_utils.h"
 #include "sql/test/test_helpers.h"
 #include "storage/browser/quota/quota_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -61,109 +69,12 @@
 
 // The Reinitialize test needs some http accessible resources to run,
 // we mock stuff inprocess for that.
-class MockHttpServer {
- public:
-  static GURL GetMockUrl(const std::string& path) {
-    return GURL("http://mockhost/" + path);
-  }
-
-  static net::URLRequestJob* CreateJob(
-      net::URLRequest* request, net::NetworkDelegate* network_delegate) {
-    if (request->url().host() != "mockhost")
-      return new net::URLRequestErrorJob(request, network_delegate, -100);
-
-    std::string headers, body;
-    GetMockResponse(request->url().path(), &headers, &body);
-    return new net::URLRequestTestJob(
-        request, network_delegate, headers, body, true);
-  }
-
- private:
-  static void GetMockResponse(const std::string& path,
-                              std::string* headers,
-                              std::string* body) {
-    const char manifest_headers[] =
-        "HTTP/1.1 200 OK\n"
-        "Content-type: text/cache-manifest\n"
-        "\n";
-    const char page_headers[] =
-        "HTTP/1.1 200 OK\n"
-        "Content-type: text/html\n"
-        "\n";
-    const char not_found_headers[] =
-        "HTTP/1.1 404 NOT FOUND\n"
-        "\n";
-
-    if (path == "/manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = "CACHE MANIFEST\n";
-    } else if (path == "/empty.html") {
-      (*headers) = std::string(page_headers, base::size(page_headers));
-      (*body) = "";
-    } else {
-      (*headers) =
-          std::string(not_found_headers, base::size(not_found_headers));
-      (*body) = "";
-    }
-  }
-};
-
-class MockHttpServerJobFactory
-    : public net::URLRequestJobFactory::ProtocolHandler {
- public:
-  MockHttpServerJobFactory(
-      std::unique_ptr<net::URLRequestInterceptor> appcache_start_interceptor)
-      : appcache_start_interceptor_(std::move(appcache_start_interceptor)) {}
-
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const override {
-    net::URLRequestJob* appcache_job =
-        appcache_start_interceptor_->MaybeInterceptRequest(
-            request, network_delegate);
-    if (appcache_job)
-      return appcache_job;
-    return MockHttpServer::CreateJob(request, network_delegate);
-  }
- private:
-  std::unique_ptr<net::URLRequestInterceptor> appcache_start_interceptor_;
-};
-
-class IOThread : public base::Thread {
- public:
-  explicit IOThread(const char* name)
-      : base::Thread(name) {
-  }
-
-  ~IOThread() override { Stop(); }
-
-  net::URLRequestContext* request_context() {
-    return request_context_.get();
-  }
-
-  void Init() override {
-    std::unique_ptr<net::URLRequestJobFactoryImpl> factory(
-        new net::URLRequestJobFactoryImpl());
-    factory->SetProtocolHandler("http",
-                                std::make_unique<MockHttpServerJobFactory>(
-                                    std::make_unique<AppCacheInterceptor>()));
-    job_factory_ = std::move(factory);
-    request_context_.reset(new net::TestURLRequestContext());
-    request_context_->set_job_factory(job_factory_.get());
-  }
-
-  void CleanUp() override {
-    request_context_.reset();
-    job_factory_.reset();
-  }
-
- private:
-  std::unique_ptr<net::URLRequestJobFactory> job_factory_;
-  std::unique_ptr<net::URLRequestContext> request_context_;
-};
+static GURL GetMockUrl(const std::string& path) {
+  return GURL("http://mockhost/" + path);
+}
 
 std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment;
-std::unique_ptr<IOThread> io_thread;
+scoped_refptr<base::SingleThreadTaskRunner> io_runner;
 std::unique_ptr<base::Thread> background_thread;
 
 }  // namespace
@@ -255,7 +166,7 @@
     MockQuotaManager()
         : QuotaManager(true /* is_incognito */,
                        base::FilePath(),
-                       io_thread->task_runner().get(),
+                       io_runner.get(),
                        nullptr,
                        storage::GetQuotaSettingsFunc()),
           async_(false) {}
@@ -362,19 +273,21 @@
   }
 
   static void SetUpTestCase() {
-    scoped_task_environment.reset(new base::test::ScopedTaskEnvironment());
+    scoped_task_environment = std::make_unique<TestBrowserThreadBundle>(
+        TestBrowserThreadBundle::REAL_IO_THREAD);
 
-    // We start both threads as TYPE_IO because we also use the db_thead
-    // for the disk_cache which needs to be of TYPE_IO.
+    io_runner =
+        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
+
+    // We start the background thread as TYPE_IO because we also use the
+    // db_thread for the disk_cache which needs to be of TYPE_IO.
     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
-    io_thread.reset(new IOThread("AppCacheTest.IOThread"));
-    ASSERT_TRUE(io_thread->StartWithOptions(options));
     background_thread.reset(new base::Thread("AppCacheTest::BackgroundThread"));
     ASSERT_TRUE(background_thread->StartWithOptions(options));
   }
 
   static void TearDownTestCase() {
-    io_thread.reset();
+    io_runner.reset();
     background_thread.reset();
     scoped_task_environment.reset();
   }
@@ -382,7 +295,16 @@
   // Test harness --------------------------------------------------
 
   AppCacheStorageImplTest() {
-    request_delegate_.set_on_complete(base::DoNothing());
+    auto head = network::CreateResourceResponseHead(net::HTTP_OK);
+    network::URLLoaderCompletionStatus status;
+
+    head.mime_type = "text/cache-manifest";
+    mock_url_loader_factory_.AddResponse(GetMockUrl("manifest"), head,
+                                         "CACHE MANIFEST\n", status);
+
+    head.mime_type = "text/html";
+    mock_url_loader_factory_.AddResponse(GetMockUrl("empty.html"), head, "",
+                                         status);
   }
 
   template <class Method>
@@ -390,7 +312,7 @@
     test_finished_event_.reset(new base::WaitableEvent(
         base::WaitableEvent::ResetPolicy::AUTOMATIC,
         base::WaitableEvent::InitialState::NOT_SIGNALED));
-    io_thread->task_runner()->PostTask(
+    io_runner->PostTask(
         FROM_HERE,
         base::BindOnce(&AppCacheStorageImplTest::MethodWrapper<Method>,
                        base::Unretained(this), method));
@@ -398,7 +320,7 @@
   }
 
   void SetUpTest() {
-    DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
+    DCHECK(io_runner->BelongsToCurrentThread());
     service_.reset(new AppCacheServiceImpl(nullptr));
     service_->Initialize(base::FilePath());
     mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
@@ -407,7 +329,7 @@
   }
 
   void TearDownTest() {
-    DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
+    DCHECK(io_runner->BelongsToCurrentThread());
     scoped_refptr<base::SequencedTaskRunner> db_runner =
         storage()->db_task_runner_;
     storage()->CancelDelegateCallbacks(delegate());
@@ -425,7 +347,7 @@
   void TestFinished() {
     // We unwind the stack prior to finishing up to let stack
     // based objects get deleted.
-    DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
+    DCHECK(io_runner->BelongsToCurrentThread());
     base::SequencedTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheStorageImplTest::TestFinishedUnwound,
                                   base::Unretained(this)));
@@ -441,7 +363,7 @@
   }
 
   void ScheduleNextTask() {
-    DCHECK(io_thread->task_runner()->BelongsToCurrentThread());
+    DCHECK(io_runner->BelongsToCurrentThread());
     if (task_stack_.empty()) {
       return;
     }
@@ -1675,6 +1597,10 @@
   }
 
   void Reinitialize(ReinitTestCase test_case) {
+    // These tests use the network service code path when simulating requests
+    // to app cache.
+    feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+
     // Unlike all of the other tests, this one actually read/write files.
     ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
 
@@ -1706,7 +1632,7 @@
     // one entry for the manifest file resource.
     if (test_case == CORRUPT_CACHE_ON_LOAD_EXISTING) {
       AppCacheDatabase db(temp_directory_.GetPath().AppendASCII("Index"));
-      GURL manifest_url = MockHttpServer::GetMockUrl("manifest");
+      GURL manifest_url = GetMockUrl("manifest");
 
       AppCacheDatabase::GroupRecord group_record;
       group_record.group_id = 1;
@@ -1731,7 +1657,11 @@
 
     // Recreate the service to point at the db and corruption on disk.
     service_.reset(new AppCacheServiceImpl(nullptr));
-    service_->set_request_context(io_thread->request_context());
+    auto loader_factory_getter = base::MakeRefCounted<URLLoaderFactoryGetter>();
+    loader_factory_getter->SetNetworkFactoryForTesting(
+        &mock_url_loader_factory_);
+    service_->set_url_loader_factory_getter(loader_factory_getter.get());
+
     service_->Initialize(temp_directory_.GetPath());
     mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
     service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
@@ -1768,10 +1698,10 @@
       // eventually fail when it gets to disk cache initialization.
       backend_->RegisterHost(1);
       AppCacheHost* host1 = backend_->GetHost(1);
-      const GURL kEmptyPageUrl(MockHttpServer::GetMockUrl("empty.html"));
+      const GURL kEmptyPageUrl(GetMockUrl("empty.html"));
       host1->SetFirstPartyUrlForTesting(kEmptyPageUrl);
       host1->SelectCache(kEmptyPageUrl, blink::mojom::kAppCacheNoCacheId,
-                         MockHttpServer::GetMockUrl("manifest"));
+                         GetMockUrl("manifest"));
     } else {
       ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
       // Try to access the existing cache manifest.
@@ -1779,14 +1709,13 @@
       // cache initialization.
       backend_->RegisterHost(2);
       AppCacheHost* host2 = backend_->GetHost(2);
-      GURL manifest_url = MockHttpServer::GetMockUrl("manifest");
-      request_ = service()->request_context()->CreateRequest(
-          manifest_url, net::DEFAULT_PRIORITY, &request_delegate_,
-          TRAFFIC_ANNOTATION_FOR_TESTS);
-      AppCacheInterceptor::SetExtraRequestInfo(
-          request_.get(), service_.get(), backend_->process_id(),
-          host2->host_id(), RESOURCE_TYPE_MAIN_FRAME, false);
-      request_->Start();
+      network::ResourceRequest request;
+      request.url = GetMockUrl("manifest");
+      handler_ =
+          host2->CreateRequestHandler(AppCacheURLLoaderRequest::Create(request),
+                                      RESOURCE_TYPE_MAIN_FRAME, false);
+      handler_->MaybeCreateLoader(request, nullptr, base::DoNothing(),
+                                  base::DoNothing());
     }
 
     PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_Reinitialized,
@@ -1824,7 +1753,7 @@
 
     // Cleanup and claim victory.
     service_->RemoveObserver(observer_.get());
-    request_.reset();
+    handler_.reset();
     backend_.reset();
     observer_.reset();
     TestFinished();
@@ -1898,12 +1827,13 @@
   scoped_refptr<AppCache> cache2_;
 
   // Specifically for the Reinitalize test.
+  base::test::ScopedFeatureList feature_list_;
   base::ScopedTempDir temp_directory_;
   std::unique_ptr<MockServiceObserver> observer_;
   MockAppCacheFrontend frontend_;
   std::unique_ptr<AppCacheBackendImpl> backend_;
-  net::TestDelegate request_delegate_;
-  std::unique_ptr<net::URLRequest> request_;
+  std::unique_ptr<AppCacheRequestHandler> handler_;
+  network::TestURLLoaderFactory mock_url_loader_factory_;
 
   // Test data
   const base::Time kZeroTime;
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc
index 4e5342274..d85ad67c 100644
--- a/content/browser/appcache/appcache_update_job.cc
+++ b/content/browser/appcache/appcache_update_job.cc
@@ -15,8 +15,8 @@
 #include "content/browser/appcache/appcache_frontend.h"
 #include "content/browser/appcache/appcache_group.h"
 #include "content/browser/appcache/appcache_histograms.h"
-#include "content/browser/appcache/appcache_update_request_base.h"
 #include "content/browser/appcache/appcache_update_url_fetcher.h"
+#include "content/browser/appcache/appcache_update_url_loader_request.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
@@ -372,7 +372,7 @@
 
   manifest_fetcher_ = nullptr;
 
-  UpdateRequestBase* request = fetcher->request();
+  UpdateURLLoaderRequest* request = fetcher->request();
   int response_code = -1;
   bool is_valid_response_code = false;
   if (net_error == net::OK) {
@@ -508,7 +508,7 @@
                                                 int net_error) {
   DCHECK(internal_state_ == DOWNLOADING);
 
-  UpdateRequestBase* request = fetcher->request();
+  UpdateURLLoaderRequest* request = fetcher->request();
   const GURL& url = request->GetURL();
   pending_url_fetches_.erase(url);
   NotifyAllProgress(url);
@@ -609,7 +609,7 @@
   // master entry fetches when entering cache failure state so this will never
   // be called in CACHE_FAILURE state.
 
-  UpdateRequestBase* request = fetcher->request();
+  UpdateURLLoaderRequest* request = fetcher->request();
   const GURL& url = request->GetURL();
   master_entry_fetches_.erase(url);
   ++master_entries_completed_;
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc
index dedb55b5..f48f609 100644
--- a/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/content/browser/appcache/appcache_update_job_unittest.cc
@@ -20,7 +20,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/appcache/appcache_frontend.h"
@@ -712,20 +711,16 @@
         expect_non_null_update_time_(false),
         tested_manifest_(NONE),
         tested_manifest_path_override_(nullptr),
-        request_handler_type_(GetParam()),
         thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&IOThread::Init, base::Unretained(io_thread_.get())));
 
-    if (request_handler_type_ == URLLOADER) {
-      loader_factory_getter_ = new URLLoaderFactoryGetter();
-      feature_list_.InitAndEnableFeature(network::features::kNetworkService);
-      base::PostTaskWithTraits(
-          FROM_HERE, {BrowserThread::IO},
-          base::BindOnce(&AppCacheUpdateJobTest::InitializeFactory,
-                         base::Unretained(this)));
-    }
+    loader_factory_getter_ = base::MakeRefCounted<URLLoaderFactoryGetter>();
+    base::PostTaskWithTraits(
+        FROM_HERE, {BrowserThread::IO},
+        base::BindOnce(&AppCacheUpdateJobTest::InitializeFactory,
+                       base::Unretained(this)));
   }
 
   ~AppCacheUpdateJobTest() {
@@ -942,14 +937,6 @@
   void ManifestRedirectTest() {
     ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler("http",
-                                      base::WrapUnique(new RedirectFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(service_->storage(), GURL("http://testme"),
                                service_->storage()->NewGroupId());
@@ -2030,14 +2017,6 @@
     // Expect 1 manifest fetch and 3 retries.
     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new RetryRequestTestJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(service_->storage(),
                                RetryRequestTestJob::kRetryUrl,
@@ -2068,14 +2047,6 @@
     // Expect 1 manifest fetch and 0 retries.
     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new RetryRequestTestJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(service_->storage(),
                                RetryRequestTestJob::kRetryUrl,
@@ -2107,14 +2078,6 @@
     RetryRequestTestJob::Initialize(
         5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1);
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new RetryRequestTestJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(service_->storage(),
                                RetryRequestTestJob::kRetryUrl,
@@ -2145,14 +2108,6 @@
     // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
     RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new RetryRequestTestJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(service_->storage(),
                                RetryRequestTestJob::kRetryUrl,
@@ -2183,14 +2138,6 @@
     // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
     RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new RetryRequestTestJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ =
         new AppCacheGroup(service_->storage(), RetryRequestTestJob::kRetryUrl,
@@ -3192,14 +3139,6 @@
   void IfModifiedSinceTestCache() {
     ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(
         service_->storage(), GURL("http://headertest"), 111);
@@ -3215,16 +3154,12 @@
                       service_.get());
     update->StartUpdate(&host, GURL());
 
-    // If URLLoader based tests are enabled, we need to wait for the URL
-    // load requests to make it to the MockURLLoaderFactory.
-    if (request_handler_type_ == URLLOADER) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                         update));
-    } else {
-      VerifyHeadersAndDeleteUpdate(update);
-    }
+    // We need to wait for the URL load requests to make it to the
+    // MockURLLoaderFactory.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+                       update));
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
@@ -3234,14 +3169,6 @@
   void IfModifiedTestRefetch() {
     ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     // Now simulate a refetch manifest request. Will start fetch request
     // synchronously.
     const char data[] =
@@ -3266,16 +3193,12 @@
     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
     update->FetchManifest(false);  // not first request
 
-    // If URLLoader based tests are enabled, we need to wait for the URL
-    // load requests to make it to the MockURLLoaderFactory.
-    if (request_handler_type_ == URLLOADER) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                         update));
-    } else {
-      VerifyHeadersAndDeleteUpdate(update);
-    }
+    // We need to wait for the URL load requests to make it to the
+    // MockURLLoaderFactory.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+                       update));
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
@@ -3285,14 +3208,6 @@
   void IfModifiedTestLastModified() {
     ASSERT_TRUE(base::MessageLoopCurrentForIO::IsSet());
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     // Change the headers to include a Last-Modified header. Manifest refetch
     // should include If-Modified-Since header.
     const char data2[] =
@@ -3318,16 +3233,12 @@
     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
     update->FetchManifest(false);  // not first request
 
-    // If URLLoader based tests are enabled, we need to wait for the URL
-    // load requests to make it to the MockURLLoaderFactory.
-    if (request_handler_type_ == URLLOADER) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                         update));
-    } else {
-      VerifyHeadersAndDeleteUpdate(update);
-    }
+    // We need to wait for the URL load requests to make it to the
+    // MockURLLoaderFactory.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+                       update));
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
@@ -3340,14 +3251,6 @@
     HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
                                           std::string());
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(
         service_->storage(),
@@ -3416,14 +3319,6 @@
 
     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(
         service_->storage(),
@@ -3492,14 +3387,6 @@
 
     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(
         service_->storage(), GURL("http://headertest"), 111);
@@ -3522,16 +3409,12 @@
     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
     update->FetchManifest(false);  // not first request
 
-    // If URLLoader based tests are enabled, we need to wait for the URL
-    // load requests to make it to the MockURLLoaderFactory.
-    if (request_handler_type_ == URLLOADER) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                         update));
-    } else {
-      VerifyHeadersAndDeleteUpdate(update);
-    }
+    // We need to wait for the URL load requests to make it to the
+    // MockURLLoaderFactory.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+                       update));
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
@@ -3545,14 +3428,6 @@
     HttpHeadersRequestTestJob::Initialize(
         "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\"");
 
-    if (request_handler_type_ == URLREQUEST) {
-      net::URLRequestJobFactoryImpl* new_factory(
-          new net::URLRequestJobFactoryImpl);
-      new_factory->SetProtocolHandler(
-          "http", base::WrapUnique(new IfModifiedSinceJobFactory));
-      io_thread_->SetNewJobFactory(new_factory);
-    }
-
     MakeService();
     group_ = new AppCacheGroup(
         service_->storage(), GURL("http://headertest"), 111);
@@ -3576,16 +3451,12 @@
     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
     update->FetchManifest(false);  // not first request
 
-    // If URLLoader based tests are enabled, we need to wait for the URL
-    // load requests to make it to the MockURLLoaderFactory.
-    if (request_handler_type_ == URLLOADER) {
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                         update));
-    } else {
-      VerifyHeadersAndDeleteUpdate(update);
-    }
+    // We need to wait for the URL load requests to make it to the
+    // MockURLLoaderFactory.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
+                       update));
 
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
@@ -4084,14 +3955,12 @@
   AppCache::EntryMap expect_extra_entries_;
   std::map<GURL, int64_t> expect_response_ids_;
 
-  RequestHandlerType request_handler_type_;
-  base::test::ScopedFeatureList feature_list_;
   MockURLLoaderFactory mock_url_loader_factory_;
   scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
   content::TestBrowserThreadBundle thread_bundle_;
 };
 
-TEST_P(AppCacheUpdateJobTest, AlreadyChecking) {
+TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
   MockAppCacheService service;
   scoped_refptr<AppCacheGroup> group(
       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
@@ -4121,7 +3990,7 @@
   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
 }
 
-TEST_P(AppCacheUpdateJobTest, AlreadyDownloading) {
+TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
   MockAppCacheService service;
   scoped_refptr<AppCacheGroup> group(
       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
@@ -4158,236 +4027,232 @@
   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
 }
 
-TEST_P(AppCacheUpdateJobTest, StartCacheAttempt) {
+TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, StartUpgradeAttempt) {
+TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
+TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
+TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, ManifestRedirect) {
+TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
+TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, ManifestNotFound) {
+TEST_F(AppCacheUpdateJobTest, ManifestNotFound) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, ManifestGone) {
+TEST_F(AppCacheUpdateJobTest, ManifestGone) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, CacheAttemptNotModified) {
+TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeNotModified) {
+TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
+TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, Bug95101Test) {
+TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test);
 }
 
-TEST_P(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
+TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
+TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
+TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
+TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
+TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
+TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
   RunTestOnIOThread(
       &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheReuseVaryHeader) {
+TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheReuseVaryHeader) {
   RunTestOnIOThread(
       &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheReuseVaryHeaderTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
+TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
+TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
+TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
+TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, EmptyManifest) {
+TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, EmptyFile) {
+TEST_F(AppCacheUpdateJobTest, EmptyFile) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, RetryRequest) {
+TEST_F(AppCacheUpdateJobTest, RetryRequest) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, RetryNoRetryAfter) {
+TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
+TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, RetrySuccess) {
+TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, RetryUrl) {
+TEST_F(AppCacheUpdateJobTest, RetryUrl) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, FailStoreNewestCache) {
+TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
   RunTestOnIOThread(
       &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
+TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
+TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryBadManifest) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryAllFail) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
+TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntrySomeFail) {
+TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
+TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
+TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
+TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
+TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, StartUpdateMidDownload) {
+TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, QueueMasterEntry) {
+TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfModifiedSinceCache) {
+TEST_F(AppCacheUpdateJobTest, IfModifiedSinceCache) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTestCache);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfModifiedRefetch) {
+TEST_F(AppCacheUpdateJobTest, IfModifiedRefetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedTestRefetch);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfModifiedLastModified) {
+TEST_F(AppCacheUpdateJobTest, IfModifiedLastModified) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedTestLastModified);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
+TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
+TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
+TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
+TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
+TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
 }
 
-TEST_P(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
+TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
 }
 
-INSTANTIATE_TEST_CASE_P(,
-                        AppCacheUpdateJobTest,
-                        ::testing::Values(URLREQUEST, URLLOADER));
-
 }  // namespace appcache_update_job_unittest
 }  // namespace content
diff --git a/content/browser/appcache/appcache_update_request_base.cc b/content/browser/appcache/appcache_update_request_base.cc
deleted file mode 100644
index 194624f5..0000000
--- a/content/browser/appcache/appcache_update_request_base.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 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 "content/browser/appcache/appcache_update_request_base.h"
-#include "content/browser/appcache/appcache_update_url_loader_request.h"
-#include "content/browser/appcache/appcache_update_url_request.h"
-#include "content/public/common/content_features.h"
-#include "net/url_request/url_request_context.h"
-#include "services/network/public/cpp/features.h"
-
-namespace content {
-
-namespace {
-constexpr net::NetworkTrafficAnnotationTag kAppCacheTrafficAnnotation =
-    net::DefineNetworkTrafficAnnotation("appcache_update_job", R"(
-      semantics {
-        sender: "HTML5 AppCache System"
-        description:
-          "Web pages can include a link to a manifest file which lists "
-          "resources to be cached for offline access. The AppCache system"
-          "retrieves those resources in the background."
-        trigger:
-          "User visits a web page containing a <html manifest=manifestUrl> "
-          "tag, or navigates to a document retrieved from an existing appcache "
-          "and some resource should be updated."
-        data: "None"
-        destination: WEBSITE
-      }
-      policy {
-        cookies_allowed: YES
-        cookies_store: "user"
-        setting:
-          "Users can control this feature via the 'Cookies' setting under "
-          "'Privacy, Content settings'. If cookies are disabled for a single "
-          "site, appcaches are disabled for the site only. If they are totally "
-          "disabled, all appcache requests will be stopped."
-        chrome_policy {
-            DefaultCookiesSetting {
-              DefaultCookiesSetting: 2
-            }
-          }
-      })");
-}
-
-AppCacheUpdateJob::UpdateRequestBase::~UpdateRequestBase() {}
-
-// static
-std::unique_ptr<AppCacheUpdateJob::UpdateRequestBase>
-AppCacheUpdateJob::UpdateRequestBase::Create(
-    AppCacheServiceImpl* appcache_service,
-    const GURL& url,
-    int buffer_size,
-    URLFetcher* fetcher) {
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    return std::unique_ptr<UpdateRequestBase>(new UpdateURLRequest(
-        appcache_service->request_context(), url, buffer_size, fetcher));
-  } else {
-    return std::unique_ptr<UpdateRequestBase>(new UpdateURLLoaderRequest(
-        appcache_service->url_loader_factory_getter(), url, buffer_size,
-        fetcher));
-  }
-}
-
-AppCacheUpdateJob::UpdateRequestBase::UpdateRequestBase() {}
-
-net::NetworkTrafficAnnotationTag
-AppCacheUpdateJob::UpdateRequestBase::GetTrafficAnnotation() {
-  return kAppCacheTrafficAnnotation;
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_update_request_base.h b/content/browser/appcache/appcache_update_request_base.h
deleted file mode 100644
index b6a26e7b..0000000
--- a/content/browser/appcache/appcache_update_request_base.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 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 CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
-#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "content/browser/appcache/appcache_update_job.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_response_info.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-namespace content {
-
-class AppCacheUpdateJob::UpdateRequestBase {
- public:
-  virtual ~UpdateRequestBase();
-
-  // Creates an instance of the AppCacheUpdateRequestBase subclass.
-  static std::unique_ptr<UpdateRequestBase> Create(
-      AppCacheServiceImpl* appcache_service,
-      const GURL& url,
-      int buffer_size,
-      URLFetcher* fetcher);
-
-  // This method is called to start the request.
-  virtual void Start() = 0;
-
-  // Sets all extra request headers.  Any extra request headers set by other
-  // methods are overwritten by this method.  This method may only be called
-  // before Start() is called.  It is an error to call it later.
-  virtual void SetExtraRequestHeaders(
-      const net::HttpRequestHeaders& headers) = 0;
-
-  // Returns the request URL.
-  virtual GURL GetURL() const = 0;
-
-  // Sets flags which control the request load. e.g. if it can be loaded
-  // from cache, etc.
-  virtual void SetLoadFlags(int flags) = 0;
-
-  // Gets the load flags on the request.
-  virtual int GetLoadFlags() const = 0;
-
-  // Get the mime type.  This method may only be called after the response was
-  // started.
-  virtual std::string GetMimeType() const = 0;
-
-  // Cookie policy.
-  virtual void SetSiteForCookies(const GURL& site_for_cookies) = 0;
-
-  // Sets the origin of the context which initiated the request.
-  virtual void SetInitiator(const base::Optional<url::Origin>& initiator) = 0;
-
-  // Get all response headers, as a HttpResponseHeaders object.  See comments
-  // in HttpResponseHeaders class as to the format of the data.
-  virtual net::HttpResponseHeaders* GetResponseHeaders() const = 0;
-
-  // Returns the HTTP response code (e.g., 200, 404, and so on).  This method
-  // may only be called once the delegate's OnResponseStarted method has been
-  // called.  For non-HTTP requests, this method returns -1.
-  virtual int GetResponseCode() const = 0;
-
-  // Get the HTTP response info in its entirety.
-  virtual const net::HttpResponseInfo& GetResponseInfo() const = 0;
-
-  // Initiates an asynchronous read. Multiple concurrent reads are not
-  // supported.
-  virtual void Read() = 0;
-
-  // This method may be called at any time after Start() has been called to
-  // cancel the request.
-  // Returns net::ERR_ABORTED or any applicable net error.
-  virtual int Cancel() = 0;
-
- protected:
-  UpdateRequestBase();
-
-  // Returns the traffic annotation information to be used for the outgoing
-  // request.
-  static net::NetworkTrafficAnnotationTag GetTrafficAnnotation();
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_REQUEST_BASE_H_
diff --git a/content/browser/appcache/appcache_update_url_fetcher.cc b/content/browser/appcache/appcache_update_url_fetcher.cc
index e89b224c..59af1a1 100644
--- a/content/browser/appcache/appcache_update_url_fetcher.cc
+++ b/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -4,11 +4,13 @@
 
 #include "content/browser/appcache/appcache_update_url_fetcher.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/network_session_configurator/common/network_switches.h"
-#include "content/browser/appcache/appcache_update_request_base.h"
+#include "content/browser/appcache/appcache_update_url_loader_request.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
@@ -32,8 +34,11 @@
       job_(job),
       fetch_type_(fetch_type),
       retry_503_attempts_(0),
-      request_(
-          UpdateRequestBase::Create(job->service_, url, buffer_size, this)),
+      request_(std::make_unique<UpdateURLLoaderRequest>(
+          job->service_->url_loader_factory_getter(),
+          url,
+          buffer_size,
+          this)),
       result_(AppCacheUpdateJob::UPDATE_OK),
       redirect_response_code_(-1),
       buffer_size_(buffer_size) {}
@@ -245,8 +250,8 @@
   }
   ++retry_503_attempts_;
   result_ = AppCacheUpdateJob::UPDATE_OK;
-  request_ =
-      UpdateRequestBase::Create(job_->service_, url_, buffer_size_, this);
+  request_ = std::make_unique<UpdateURLLoaderRequest>(
+      job_->service_->url_loader_factory_getter(), url_, buffer_size_, this);
   Start();
   return true;
 }
diff --git a/content/browser/appcache/appcache_update_url_fetcher.h b/content/browser/appcache/appcache_update_url_fetcher.h
index a3d3d93..3368e36 100644
--- a/content/browser/appcache/appcache_update_url_fetcher.h
+++ b/content/browser/appcache/appcache_update_url_fetcher.h
@@ -33,7 +33,7 @@
   ~URLFetcher();
   void Start();
   FetchType fetch_type() const { return fetch_type_; }
-  UpdateRequestBase* request() const { return request_.get(); }
+  UpdateURLLoaderRequest* request() const { return request_.get(); }
   const AppCacheEntry& existing_entry() const { return existing_entry_; }
   const std::string& manifest_data() const { return manifest_data_; }
   AppCacheResponseWriter* response_writer() const {
@@ -60,14 +60,13 @@
   void OnResponseCompleted(int net_error);
   bool MaybeRetryRequest();
 
-  friend class UpdateURLRequest;
   friend class UpdateURLLoaderRequest;
 
   GURL url_;
   AppCacheUpdateJob* job_;
   FetchType fetch_type_;
   int retry_503_attempts_;
-  std::unique_ptr<UpdateRequestBase> request_;
+  std::unique_ptr<UpdateURLLoaderRequest> request_;
   AppCacheEntry existing_entry_;
   scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
   std::string manifest_data_;
@@ -79,4 +78,4 @@
 
 }  // namespace content.
 
-#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_FETCHER_H_
\ No newline at end of file
+#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_FETCHER_H_
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc
index 862c0c2..c22cb619 100644
--- a/content/browser/appcache/appcache_update_url_loader_request.cc
+++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -12,6 +12,38 @@
 
 namespace content {
 
+namespace {
+constexpr net::NetworkTrafficAnnotationTag kAppCacheTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("appcache_update_job", R"(
+      semantics {
+        sender: "HTML5 AppCache System"
+        description:
+          "Web pages can include a link to a manifest file which lists "
+          "resources to be cached for offline access. The AppCache system"
+          "retrieves those resources in the background."
+        trigger:
+          "User visits a web page containing a <html manifest=manifestUrl> "
+          "tag, or navigates to a document retrieved from an existing appcache "
+          "and some resource should be updated."
+        data: "None"
+        destination: WEBSITE
+      }
+      policy {
+        cookies_allowed: YES
+        cookies_store: "user"
+        setting:
+          "Users can control this feature via the 'Cookies' setting under "
+          "'Privacy, Content settings'. If cookies are disabled for a single "
+          "site, appcaches are disabled for the site only. If they are totally "
+          "disabled, all appcache requests will be stopped."
+        chrome_policy {
+            DefaultCookiesSetting {
+              DefaultCookiesSetting: 2
+            }
+          }
+      })");
+}
+
 AppCacheUpdateJob::UpdateURLLoaderRequest::~UpdateURLLoaderRequest() {}
 
 void AppCacheUpdateJob::UpdateURLLoaderRequest::Start() {
@@ -25,7 +57,7 @@
   loader_factory_getter_->GetNetworkFactory()->CreateLoaderAndStart(
       mojo::MakeRequest(&url_loader_), -1, -1,
       network::mojom::kURLLoadOptionNone, request_, std::move(client),
-      net::MutableNetworkTrafficAnnotationTag(GetTrafficAnnotation()));
+      net::MutableNetworkTrafficAnnotationTag(kAppCacheTrafficAnnotation));
 }
 
 void AppCacheUpdateJob::UpdateURLLoaderRequest::SetExtraRequestHeaders(
diff --git a/content/browser/appcache/appcache_update_url_loader_request.h b/content/browser/appcache/appcache_update_url_loader_request.h
index d826fc30..04e5f30 100644
--- a/content/browser/appcache/appcache_update_url_loader_request.h
+++ b/content/browser/appcache/appcache_update_url_loader_request.h
@@ -8,9 +8,10 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
-#include "content/browser/appcache/appcache_update_request_base.h"
+#include "content/browser/appcache/appcache_update_job.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/io_buffer.h"
@@ -31,25 +32,62 @@
 // functionality to update the AppCache using functionality provided by the
 // network URL loader.
 class AppCacheUpdateJob::UpdateURLLoaderRequest
-    : public AppCacheUpdateJob::UpdateRequestBase,
-      public network::mojom::URLLoaderClient {
+    : public network::mojom::URLLoaderClient {
  public:
+  UpdateURLLoaderRequest(URLLoaderFactoryGetter* loader_factory_getter,
+                         const GURL& url,
+                         int buffer_size,
+                         URLFetcher* fetcher);
   ~UpdateURLLoaderRequest() override;
 
-  // UpdateRequestBase overrides.
-  void Start() override;
-  void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
-  GURL GetURL() const override;
-  void SetLoadFlags(int flags) override;
-  int GetLoadFlags() const override;
-  std::string GetMimeType() const override;
-  void SetSiteForCookies(const GURL& site_for_cookies) override;
-  void SetInitiator(const base::Optional<url::Origin>& initiator) override;
-  net::HttpResponseHeaders* GetResponseHeaders() const override;
-  int GetResponseCode() const override;
-  const net::HttpResponseInfo& GetResponseInfo() const override;
-  void Read() override;
-  int Cancel() override;
+  // This method is called to start the request.
+  void Start();
+
+  // Sets all extra request headers.  Any extra request headers set by other
+  // methods are overwritten by this method.  This method may only be called
+  // before Start() is called.  It is an error to call it later.
+  void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers);
+
+  // Returns the request URL.
+  GURL GetURL() const;
+
+  // Sets flags which control the request load. e.g. if it can be loaded
+  // from cache, etc.
+  void SetLoadFlags(int flags);
+
+  // Gets the load flags on the request.
+  int GetLoadFlags() const;
+
+  // Get the mime type.  This method may only be called after the response was
+  // started.
+  std::string GetMimeType() const;
+
+  // Cookie policy.
+  void SetSiteForCookies(const GURL& site_for_cookies);
+
+  // Sets the origin of the context which initiated the request.
+  void SetInitiator(const base::Optional<url::Origin>& initiator);
+
+  // Get all response headers, as a HttpResponseHeaders object.  See comments
+  // in HttpResponseHeaders class as to the format of the data.
+  net::HttpResponseHeaders* GetResponseHeaders() const;
+
+  // Returns the HTTP response code (e.g., 200, 404, and so on).  This method
+  // may only be called once the delegate's OnResponseStarted method has been
+  // called.  For non-HTTP requests, this method returns -1.
+  int GetResponseCode() const;
+
+  // Get the HTTP response info in its entirety.
+  const net::HttpResponseInfo& GetResponseInfo() const;
+
+  // Initiates an asynchronous read. Multiple concurrent reads are not
+  // supported.
+  void Read();
+
+  // This method may be called at any time after Start() has been called to
+  // cancel the request.
+  // Returns net::ERR_ABORTED or any applicable net error.
+  int Cancel();
 
   // network::mojom::URLLoaderClient implementation.
   // These methods are called by the network loader.
@@ -68,11 +106,6 @@
   void OnComplete(const network::URLLoaderCompletionStatus& status) override;
 
  private:
-  UpdateURLLoaderRequest(URLLoaderFactoryGetter* loader_factory_getter,
-                         const GURL& url,
-                         int buffer_size,
-                         URLFetcher* fetcher);
-
   // Helper function to initiate an asynchronous read on the data pipe.
   void StartReading(MojoResult unused);
 
@@ -81,8 +114,6 @@
   // a pending read.
   void MaybeStartReading();
 
-  friend class AppCacheUpdateJob::UpdateRequestBase;
-
   URLFetcher* fetcher_;
   // Used to retrieve the network URLLoader interface to issue network
   // requests
diff --git a/content/browser/appcache/appcache_update_url_request.cc b/content/browser/appcache/appcache_update_url_request.cc
deleted file mode 100644
index 45d8b063..0000000
--- a/content/browser/appcache/appcache_update_url_request.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 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 "content/browser/appcache/appcache_update_url_request.h"
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_update_url_fetcher.h"
-#include "net/url_request/url_request_context.h"
-
-namespace content {
-
-AppCacheUpdateJob::UpdateURLRequest::~UpdateURLRequest() {
-  // To defend against URLRequest calling delegate methods during
-  // destruction, we test for a !request_ in those methods.
-  std::unique_ptr<net::URLRequest> temp = std::move(request_);
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::Start() {
-  request_->Start();
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::SetExtraRequestHeaders(
-    const net::HttpRequestHeaders& headers) {
-  request_->SetExtraRequestHeaders(headers);
-}
-
-GURL AppCacheUpdateJob::UpdateURLRequest::GetURL() const {
-  return request_->url();
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::SetLoadFlags(int flags) {
-  request_->SetLoadFlags(flags);
-}
-
-int AppCacheUpdateJob::UpdateURLRequest::GetLoadFlags() const {
-  return request_->load_flags();
-}
-
-std::string AppCacheUpdateJob::UpdateURLRequest::GetMimeType() const {
-  std::string mime_type;
-  request_->GetMimeType(&mime_type);
-  return mime_type;
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::SetSiteForCookies(
-    const GURL& site_for_cookies) {
-  request_->set_site_for_cookies(site_for_cookies);
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::SetInitiator(
-    const base::Optional<url::Origin>& initiator) {
-  request_->set_initiator(initiator);
-}
-
-net::HttpResponseHeaders*
-AppCacheUpdateJob::UpdateURLRequest::GetResponseHeaders() const {
-  return request_->response_headers();
-}
-
-int AppCacheUpdateJob::UpdateURLRequest::GetResponseCode() const {
-  return request_->GetResponseCode();
-}
-
-const net::HttpResponseInfo&
-AppCacheUpdateJob::UpdateURLRequest::GetResponseInfo() const {
-  return request_->response_info();
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::Read() {
-  int bytes_read = request_->Read(buffer_.get(), buffer_size_);
-  if (bytes_read != net::ERR_IO_PENDING) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJob::UpdateURLRequest::OnReadCompleted,
-                       weak_factory_.GetWeakPtr(), request_.get(), bytes_read));
-  }
-}
-
-int AppCacheUpdateJob::UpdateURLRequest::Cancel() {
-  return request_->Cancel();
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::OnReceivedRedirect(
-    net::URLRequest* request,
-    const net::RedirectInfo& redirect_info,
-    bool* defer_redirect) {
-  if (!request_)
-    return;
-  DCHECK_EQ(request_.get(), request);
-  fetcher_->OnReceivedRedirect(redirect_info);
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::OnResponseStarted(
-    net::URLRequest* request,
-    int net_error) {
-  if (!request_)
-    return;
-  DCHECK_EQ(request_.get(), request);
-  fetcher_->OnResponseStarted(net_error);
-}
-
-void AppCacheUpdateJob::UpdateURLRequest::OnReadCompleted(
-    net::URLRequest* request,
-    int bytes_read) {
-  if (!request_)
-    return;
-  DCHECK_EQ(request_.get(), request);
-  fetcher_->OnReadCompleted(buffer_.get(), bytes_read);
-}
-
-AppCacheUpdateJob::UpdateURLRequest::UpdateURLRequest(
-    net::URLRequestContext* request_context,
-    const GURL& url,
-    int buffer_size,
-    URLFetcher* fetcher)
-    : request_(request_context->CreateRequest(url,
-                                              net::DEFAULT_PRIORITY,
-                                              this,
-                                              GetTrafficAnnotation())),
-      fetcher_(fetcher),
-      buffer_(base::MakeRefCounted<net::IOBuffer>(buffer_size)),
-      buffer_size_(buffer_size),
-      weak_factory_(this) {}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_update_url_request.h b/content/browser/appcache/appcache_update_url_request.h
deleted file mode 100644
index c2c55a0..0000000
--- a/content/browser/appcache/appcache_update_url_request.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 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 CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
-#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/appcache/appcache_update_request_base.h"
-#include "net/base/io_buffer.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-// URLRequest subclass for the UpdateRequestBase class. Provides functionality
-// to update the AppCache using functionality provided by the URLRequest class.
-class AppCacheUpdateJob::UpdateURLRequest
-    : public AppCacheUpdateJob::UpdateRequestBase,
-      public net::URLRequest::Delegate {
- public:
-  ~UpdateURLRequest() override;
-
-  // UpdateRequestBase overrides.
-  void Start() override;
-  void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
-  GURL GetURL() const override;
-  void SetLoadFlags(int flags) override;
-  int GetLoadFlags() const override;
-  std::string GetMimeType() const override;
-  void SetSiteForCookies(const GURL& site_for_cookies) override;
-  void SetInitiator(const base::Optional<url::Origin>& initiator) override;
-  net::HttpResponseHeaders* GetResponseHeaders() const override;
-  int GetResponseCode() const override;
-  const net::HttpResponseInfo& GetResponseInfo() const override;
-  void Read() override;
-  int Cancel() override;
-
-  // URLRequest::Delegate overrides
-  void OnReceivedRedirect(net::URLRequest* request,
-                          const net::RedirectInfo& redirect_info,
-                          bool* defer_redirect) override;
-  void OnResponseStarted(net::URLRequest* request, int net_error) override;
-  void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
-
- private:
-  UpdateURLRequest(net::URLRequestContext* request_context,
-                   const GURL& url,
-                   int buffer_size,
-                   URLFetcher* fetcher);
-
-  friend class AppCacheUpdateJob::UpdateRequestBase;
-
-  std::unique_ptr<net::URLRequest> request_;
-  URLFetcher* fetcher_;
-  scoped_refptr<net::IOBuffer> buffer_;
-  int buffer_size_;
-
-  base::WeakPtrFactory<AppCacheUpdateJob::UpdateURLRequest> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(UpdateURLRequest);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_URL_REQUEST_H_
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc
index 99cf8d5..c6603a6 100644
--- a/content/browser/appcache/appcache_url_loader_job.cc
+++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -67,7 +67,8 @@
 
   // We signal our caller with an empy callback that it needs to perform
   // the network load.
-  DCHECK(loader_callback_ && !binding_.is_bound());
+  DCHECK(loader_callback_);
+  DCHECK(!binding_.is_bound());
   std::move(loader_callback_).Run({});
   DeleteSoon();
 }
diff --git a/content/browser/battery_monitor_browsertest.cc b/content/browser/battery_monitor_browsertest.cc
index eb3fa65..60d32b2 100644
--- a/content/browser/battery_monitor_browsertest.cc
+++ b/content/browser/battery_monitor_browsertest.cc
@@ -15,6 +15,7 @@
 #include "content/shell/browser/shell.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
+#include "services/device/public/mojom/battery_status.mojom.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/service_binding.h"
 
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 03898fd..2fbd8546 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -169,7 +169,6 @@
 #include "content/browser/android/launcher_thread.h"
 #include "content/browser/android/scoped_surface_request_manager.h"
 #include "content/browser/android/tracing_controller_android.h"
-#include "content/browser/media/android/browser_media_player_manager.h"
 #include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
 #include "media/base/android/media_drm_bridge_client.h"
 #include "ui/android/screen_android.h"
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc
index 51884bd..91f7df1 100644
--- a/content/browser/cache_storage/cache_storage_cache.cc
+++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -669,8 +669,7 @@
   base::CheckedNumeric<uint64_t> safe_side_data_size = 0;
   for (const auto& operation : operations) {
     if (operation->operation_type == blink::mojom::OperationType::kPut) {
-      safe_space_required +=
-          (operation->response->blob ? operation->response->blob->size : 0);
+      safe_space_required += CalculateRequiredSafeSpaceForPut(operation);
       safe_side_data_size += (operation->response->side_data_blob
                                   ? operation->response->side_data_blob->size
                                   : 0);
@@ -2131,4 +2130,56 @@
   return cache_size_ + cache_padding_;
 }
 
+base::CheckedNumeric<uint64_t>
+CacheStorageCache::CalculateRequiredSafeSpaceForPut(
+    const blink::mojom::BatchOperationPtr& operation) {
+  DCHECK_EQ(blink::mojom::OperationType::kPut, operation->operation_type);
+  base::CheckedNumeric<uint64_t> safe_space_required = 0;
+  safe_space_required +=
+      CalculateRequiredSafeSpaceForResponse(operation->response);
+  safe_space_required +=
+      CalculateRequiredSafeSpaceForRequest(operation->request);
+
+  return safe_space_required;
+}
+
+base::CheckedNumeric<uint64_t>
+CacheStorageCache::CalculateRequiredSafeSpaceForRequest(
+    const blink::mojom::FetchAPIRequestPtr& request) {
+  base::CheckedNumeric<uint64_t> safe_space_required = 0;
+  safe_space_required += request->method.size();
+
+  safe_space_required += request->url.spec().size();
+
+  for (const auto& header : request->headers) {
+    safe_space_required += header.first.size();
+    safe_space_required += header.second.size();
+  }
+
+  return safe_space_required;
+}
+
+base::CheckedNumeric<uint64_t>
+CacheStorageCache::CalculateRequiredSafeSpaceForResponse(
+    const blink::mojom::FetchAPIResponsePtr& response) {
+  base::CheckedNumeric<uint64_t> safe_space_required = 0;
+  safe_space_required += (response->blob ? response->blob->size : 0);
+  safe_space_required += response->status_text.size();
+
+  for (const auto& header : response->headers) {
+    safe_space_required += header.first.size();
+    safe_space_required += header.second.size();
+  }
+
+  for (const auto& header : response->cors_exposed_header_names) {
+    safe_space_required += header.size();
+  }
+
+  for (const auto& url : response->url_list) {
+    safe_space_required += url.spec().size();
+  }
+
+  return safe_space_required;
+}
+
 }  // namespace content
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h
index a788427..185c47c 100644
--- a/content/browser/cache_storage/cache_storage_cache.h
+++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -477,6 +477,14 @@
       int64_t cache_padding);
   void DeleteBackendCompletedIO();
 
+  // Calculate the required safe space to put the entry in the cache.
+  base::CheckedNumeric<uint64_t> CalculateRequiredSafeSpaceForPut(
+      const blink::mojom::BatchOperationPtr& operation);
+  base::CheckedNumeric<uint64_t> CalculateRequiredSafeSpaceForRequest(
+      const blink::mojom::FetchAPIRequestPtr& request);
+  base::CheckedNumeric<uint64_t> CalculateRequiredSafeSpaceForResponse(
+      const blink::mojom::FetchAPIResponsePtr& response);
+
   // Be sure to check |backend_state_| before use.
   std::unique_ptr<disk_cache::Backend> backend_;
 
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc
index 8cd2cc3..c7d0edc 100644
--- a/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <limits>
 #include <memory>
 #include <set>
 #include <utility>
@@ -357,6 +358,16 @@
 
   void Init() { InitBackend(); }
 
+  base::CheckedNumeric<uint64_t> GetRequiredSafeSpaceForRequest(
+      const blink::mojom::FetchAPIRequestPtr& request) {
+    return CalculateRequiredSafeSpaceForRequest(request);
+  }
+
+  base::CheckedNumeric<uint64_t> GetRequiredSafeSpaceForResponse(
+      const blink::mojom::FetchAPIResponsePtr& response) {
+    return CalculateRequiredSafeSpaceForResponse(response);
+  }
+
  private:
   CacheStorageCacheHandle CreateHandle() override {
     // Returns an empty handle. There is no need for CacheStorage and its
@@ -1635,9 +1646,13 @@
 }
 
 TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceeded) {
-  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
-                                expected_blob_data_.size() - 1);
   blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size - 1);
   const std::string expected_side_data = "SideData";
   std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
       BuildBlobHandle("blob-id:mysideblob", expected_side_data);
@@ -1650,9 +1665,13 @@
 }
 
 TEST_P(CacheStorageCacheTestP, PutWithSideData_QuotaExceededSkipSideData) {
-  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
-                                expected_blob_data_.size());
   blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
   const std::string expected_side_data = "SideData";
   std::unique_ptr<storage::BlobDataHandle> side_data_blob_handle =
       BuildBlobHandle("blob-id:mysideblob", expected_side_data);
@@ -1685,7 +1704,8 @@
   operation->operation_type = blink::mojom::OperationType::kPut;
   operation->request = BackgroundFetchSettledFetch::CloneRequest(body_request_);
   operation->response = std::move(response);
-  operation->response->blob->size = std::numeric_limits<uint64_t>::max();
+  operation->response->side_data_blob->size =
+      std::numeric_limits<uint64_t>::max();
 
   std::vector<blink::mojom::BatchOperationPtr> operations;
   operations.emplace_back(std::move(operation));
@@ -1849,6 +1869,162 @@
   EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
 }
 
+TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimitsWithEmptyResponse) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  // The first Put will completely fill the quota, leaving no space for the
+  // second operation, which will fail even with empty response, due to the size
+  // of the headers.
+  EXPECT_TRUE(Put(body_request_, std::move(response)));
+  EXPECT_FALSE(Put(no_body_request_, CreateNoBodyResponse()));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutSafeSpaceIsEnough) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  EXPECT_TRUE(Put(body_request_, std::move(response)));
+}
+
+TEST_P(CacheStorageCacheTestP, PutRequestUrlObeysQuotaLimits) {
+  const GURL url("http://example.com/body.html");
+  const GURL longerUrl("http://example.com/longer-body.html");
+  blink::mojom::FetchAPIRequestPtr request = CreateFetchAPIRequest(
+      url, "GET", kHeaders, blink::mojom::Referrer::New(), false);
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(request) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  request->url = longerUrl;
+  EXPECT_FALSE(Put(request, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutRequestMethodObeysQuotaLimits) {
+  blink::mojom::FetchAPIRequestPtr request = CreateFetchAPIRequest(
+      kBodyUrl, "GET", kHeaders, blink::mojom::Referrer::New(), false);
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(request) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  request->method = "LongerMethodThanGet";
+  EXPECT_FALSE(Put(request, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutRequestHeadersObeyQuotaLimits) {
+  blink::mojom::FetchAPIRequestPtr request = CreateFetchAPIRequest(
+      kBodyUrl, "GET", kHeaders, blink::mojom::Referrer::New(), false);
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(request) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  request->headers["New-Header"] = "foo";
+  EXPECT_FALSE(Put(request, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutResponseStatusObeysQuotaLimits) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  response->status_text = "LongerThanOK";
+  EXPECT_FALSE(Put(body_request_, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutResponseBlobObeysQuotaLimits) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  response->blob->size += 1;
+  EXPECT_FALSE(Put(body_request_, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutResponseHeadersObeyQuotaLimits) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  response->headers["New-Header"] = "foo";
+  EXPECT_FALSE(Put(body_request_, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutResponseCorsHeadersObeyQuotaLimits) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  response->cors_exposed_header_names.push_back("AnotherOne");
+  EXPECT_FALSE(Put(body_request_, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutResponseUrlListObeysQuotaLimits) {
+  blink::mojom::FetchAPIResponsePtr response = CreateBlobBodyResponse();
+  base::CheckedNumeric<uint64_t> safe_expected_entry_size =
+      cache_->GetRequiredSafeSpaceForRequest(body_request_) +
+      cache_->GetRequiredSafeSpaceForResponse(response);
+  uint64_t expected_entry_size = safe_expected_entry_size.ValueOrDie();
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                expected_entry_size);
+
+  response->url_list.push_back(GURL("http://example.com/another-url"));
+  EXPECT_FALSE(Put(body_request_, std::move(response)));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimitsWithEmptyResponseZeroQuota) {
+  mock_quota_manager_->SetQuota(kOrigin, blink::mojom::StorageType::kTemporary,
+                                0);
+  EXPECT_FALSE(Put(body_request_, CreateNoBodyResponse()));
+  EXPECT_EQ(CacheStorageError::kErrorQuotaExceeded, callback_error_);
+}
+
 TEST_P(CacheStorageCacheTestP, Size) {
   EXPECT_EQ(0, Size());
   EXPECT_TRUE(Put(no_body_request_, CreateNoBodyResponse()));
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 5c361d43..614b977 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
@@ -2205,11 +2206,16 @@
 // Check that downloading a single file works.
 IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, SingleDownload) {
   base::ThreadRestrictions::SetIOAllowed(true);
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  std::string download_path =
+      temp_dir.GetPath().AppendASCII("download").AsUTF8Unsafe();
+
   SetupEnsureNoPendingDownloads();
   NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
   Attach();
 
-  SetDownloadBehavior("allow", "download");
+  SetDownloadBehavior("allow", download_path);
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download = StartDownloadAndReturnItem(
@@ -2339,11 +2345,18 @@
 // corrupted files.
 IN_PROC_BROWSER_TEST_F(DevToolsDownloadContentTest, MAYBE_MultiDownload) {
   base::ThreadRestrictions::SetIOAllowed(true);
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  std::string download1_path =
+      temp_dir.GetPath().AppendASCII("download1").AsUTF8Unsafe();
+  std::string download2_path =
+      temp_dir.GetPath().AppendASCII("download2").AsUTF8Unsafe();
+
   SetupEnsureNoPendingDownloads();
   NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
   Attach();
 
-  SetDownloadBehavior("allow", "download1");
+  SetDownloadBehavior("allow", download1_path);
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download1 = StartDownloadAndReturnItem(
@@ -2352,7 +2365,7 @@
   ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download1->GetState());
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
-  SetDownloadBehavior("allow", "download2");
+  SetDownloadBehavior("allow", download2_path);
   // Start the second download and wait until it's done.
   GURL url(embedded_test_server()->GetURL("/download/download-test.lib"));
   download::DownloadItem* download2 = StartDownloadAndReturnItem(shell(), url);
@@ -2378,14 +2391,14 @@
   // |file1| should be full of '*'s, and |file2| should be the same as the
   // source file.
   base::FilePath file1(download1->GetTargetFilePath());
-  ASSERT_EQ(file1.DirName().MaybeAsASCII(), "download1");
+  ASSERT_EQ(file1.DirName().MaybeAsASCII(), download1_path);
   size_t file_size1 = content::SlowDownloadHttpResponse::kFirstDownloadSize +
                       content::SlowDownloadHttpResponse::kSecondDownloadSize;
   std::string expected_contents(file_size1, '*');
   ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
 
   base::FilePath file2(download2->GetTargetFilePath());
-  ASSERT_EQ(file2.DirName().MaybeAsASCII(), "download2");
+  ASSERT_EQ(file2.DirName().MaybeAsASCII(), download2_path);
   ASSERT_TRUE(base::ContentsEqual(
       file2, GetTestFilePath("download", "download-test.lib")));
 }
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc b/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
index 6398811..71b1cc8 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
@@ -16,13 +17,16 @@
 #include "content/browser/dom_storage/session_storage_context_mojo.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
 
 namespace content {
 
 class DOMStorageContextWrapperTest : public testing::Test {
  public:
-  DOMStorageContextWrapperTest() = default;
+  DOMStorageContextWrapperTest() {
+    feature_list_.InitAndEnableFeature(blink::features::kOnionSoupDOMStorage);
+  }
 
   void SetUp() override {
     storage_policy_ = new MockSpecialStoragePolicy();
@@ -46,6 +50,7 @@
   }
 
  protected:
+  base::test::ScopedFeatureList feature_list_;
   base::test::ScopedTaskEnvironment task_environment_;
   scoped_refptr<base::TestSimpleTaskRunner> fake_mojo_task_runner_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
diff --git a/content/browser/loader/prefetch_url_loader.h b/content/browser/loader/prefetch_url_loader.h
index 9dc94b9..3055466 100644
--- a/content/browser/loader/prefetch_url_loader.h
+++ b/content/browser/loader/prefetch_url_loader.h
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/data_pipe_drainer.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "url/gurl.h"
 
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc
deleted file mode 100644
index beb09b1..0000000
--- a/content/browser/media/android/browser_media_player_manager.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/android/browser_media_player_manager.h"
-
-#include <utility>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
-#include "base/memory/singleton.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/media/android/media_resource_getter_impl.h"
-#include "content/browser/media/android/media_web_contents_observer_android.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_switches.h"
-#include "media/base/android/media_player_bridge.h"
-#include "media/base/android/media_url_interceptor.h"
-#include "media/base/media_content_type.h"
-
-#if !defined(USE_AURA)
-#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#endif
-
-using media::MediaPlayerAndroid;
-using media::MediaPlayerBridge;
-using media::MediaPlayerManager;
-
-namespace content {
-
-// static
-void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
-  NOTREACHED();
-}
-
-// static
-void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
-    media::MediaUrlInterceptor* media_url_interceptor) {
-  // NOTREACHED() here causes some crashes in some test suites.
-  // This entire class will be removed very shortly in a follow up patch,
-  // so NO-OP is fine for now.
-}
-
-// static
-BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
-    RenderFrameHost* rfh) {
-  NOTREACHED();
-  return nullptr;
-}
-
-std::unique_ptr<MediaPlayerAndroid>
-BrowserMediaPlayerManager::CreateMediaPlayer(
-    const MediaPlayerHostMsg_Initialize_Params& media_player_params,
-    bool hide_url_log) {
-  NOTREACHED();
-  return nullptr;
-}
-
-BrowserMediaPlayerManager::BrowserMediaPlayerManager(
-    RenderFrameHost* render_frame_host)
-    : render_frame_host_(render_frame_host),
-      web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
-      weak_ptr_factory_(this) {
-}
-
-BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
-}
-
-void BrowserMediaPlayerManager::OnTimeUpdate(
-    int player_id,
-    base::TimeDelta current_timestamp,
-    base::TimeTicks current_time_ticks) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnMediaMetadataChanged(
-    int player_id, base::TimeDelta duration, int width, int height,
-    bool success) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
-  // Tell WebKit that the audio should be paused, then release all resources
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnBufferingUpdate(int player_id,
-                                                  int percentage) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSeekRequest(
-    int player_id,
-    const base::TimeDelta& time_to_seek) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSeekComplete(
-    int player_id,
-    const base::TimeDelta& current_time) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnError(int player_id, int error) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnVideoSizeChanged(
-    int player_id, int width, int height) {
-  NOTREACHED();
-}
-
-media::MediaResourceGetter*
-BrowserMediaPlayerManager::GetMediaResourceGetter() {
-  NOTREACHED();
-  return nullptr;
-}
-
-media::MediaUrlInterceptor*
-BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
-  NOTREACHED();
-  return nullptr;
-}
-
-MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
-  NOTREACHED();
-  return nullptr;
-}
-
-bool BrowserMediaPlayerManager::RequestPlay(int player_id,
-                                            base::TimeDelta duration,
-                                            bool has_audio) {
-  NOTREACHED();
-  return false;
-}
-
-void BrowserMediaPlayerManager::OnInitialize(
-    const MediaPlayerHostMsg_Initialize_Params& media_player_params) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnStart(int player_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSeek(
-    int player_id,
-    const base::TimeDelta& time) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnPause(
-    int player_id,
-    bool is_media_related_action) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnSuspendAndReleaseResources(int player_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
-    int /* player_id */) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::OnRequestRemotePlaybackStop(
-    int /* player_id */) {
-  NOTREACHED();
-}
-
-bool BrowserMediaPlayerManager::IsPlayingRemotely(int player_id) {
-  NOTREACHED();
-  return false;
-}
-
-void BrowserMediaPlayerManager::AddPlayer(
-    std::unique_ptr<MediaPlayerAndroid> player,
-    int delegate_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::DestroyPlayer(int player_id) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::ReleaseResources(int player_id) {
-  NOTREACHED();
-}
-
-std::unique_ptr<MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
-    int player_id,
-    std::unique_ptr<MediaPlayerAndroid> player) {
-  NOTREACHED();
-  return nullptr;
-}
-
-bool BrowserMediaPlayerManager::RequestDecoderResources(
-    int player_id, bool temporary) {
-  NOTREACHED();
-  return true;
-}
-
-void BrowserMediaPlayerManager::OnDecoderResourcesReleased(int player_id) {
-  NOTREACHED();
-}
-
-int BrowserMediaPlayerManager::RoutingID() {
-  NOTREACHED();
-  return 0;
-}
-
-bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
-  NOTREACHED();
-  return render_frame_host_->Send(msg);
-}
-
-void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
-    MediaPlayerAndroid* player) {
-  NOTREACHED();
-}
-
-void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) {
-  NOTREACHED();
-}
-
-}  // namespace content
diff --git a/content/browser/media/android/browser_media_player_manager.h b/content/browser/media/android/browser_media_player_manager.h
deleted file mode 100644
index f942adc..0000000
--- a/content/browser/media/android/browser_media_player_manager.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_message.h"
-#include "media/base/android/media_player_android.h"
-#include "media/base/android/media_player_manager.h"
-#include "media/base/android/media_url_interceptor.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gl/android/scoped_java_surface.h"
-#include "url/gurl.h"
-
-struct MediaPlayerHostMsg_Initialize_Params;
-
-namespace content {
-class RenderFrameHost;
-class WebContents;
-
-// This class manages all the MediaPlayerAndroid objects.
-// It receives control operations from the the render process, and forwards
-// them to corresponding MediaPlayerAndroid object. Callbacks from
-// MediaPlayerAndroid objects are converted to IPCs and then sent to the render
-// process.
-class CONTENT_EXPORT BrowserMediaPlayerManager
-    : public media::MediaPlayerManager {
- public:
-  // Permits embedders to provide an extended version of the class.
-  typedef BrowserMediaPlayerManager* (*Factory)(RenderFrameHost*);
-  static void RegisterFactory(Factory factory);
-
-  // Permits embedders to handle custom urls.
-  static void RegisterMediaUrlInterceptor(
-      media::MediaUrlInterceptor* media_url_interceptor);
-
-  // Returns a new instance using the registered factory.
-  // Returns nullptr if no factory was registered.
-  static BrowserMediaPlayerManager* Create(RenderFrameHost* rfh);
-
-  ~BrowserMediaPlayerManager() override;
-
-  // Called when browser player wants the renderer media element to seek.
-  // Any actual seek started by renderer will be handled by browser in OnSeek().
-  void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
-
-  WebContents* web_contents() const { return web_contents_; }
-
-  // media::MediaPlayerManager overrides.
-  void OnTimeUpdate(int player_id,
-                    base::TimeDelta current_timestamp,
-                    base::TimeTicks current_time_ticks) override;
-  void OnMediaMetadataChanged(int player_id,
-                              base::TimeDelta duration,
-                              int width,
-                              int height,
-                              bool success) override;
-  void OnPlaybackComplete(int player_id) override;
-  void OnMediaInterrupted(int player_id) override;
-  void OnBufferingUpdate(int player_id, int percentage) override;
-  void OnSeekComplete(int player_id,
-                      const base::TimeDelta& current_time) override;
-  void OnError(int player_id, int error) override;
-  void OnVideoSizeChanged(int player_id, int width, int height) override;
-
-  media::MediaResourceGetter* GetMediaResourceGetter() override;
-  media::MediaUrlInterceptor* GetMediaUrlInterceptor() override;
-  media::MediaPlayerAndroid* GetPlayer(int player_id) override;
-  bool RequestPlay(int player_id, base::TimeDelta duration,
-                   bool has_audio) override;
-
-  // Message handlers.
-  virtual void OnInitialize(
-      const MediaPlayerHostMsg_Initialize_Params& media_player_params);
-  virtual void OnStart(int player_id);
-  virtual void OnSeek(int player_id, const base::TimeDelta& time);
-  virtual void OnPause(int player_id, bool is_media_related_action);
-  virtual void OnSetVolume(int player_id, double volume);
-  virtual void OnSetPoster(int player_id, const GURL& poster);
-  virtual void OnSuspendAndReleaseResources(int player_id);
-  virtual void OnDestroyPlayer(int player_id);
-  virtual void OnRequestRemotePlayback(int player_id);
-  virtual void OnRequestRemotePlaybackControl(int player_id);
-  virtual void OnRequestRemotePlaybackStop(int player_id);
-  virtual bool IsPlayingRemotely(int player_id);
-  virtual void ReleaseFullscreenPlayer(media::MediaPlayerAndroid* player);
-
- protected:
-  // Clients must use Create() or subclass constructor.
-  explicit BrowserMediaPlayerManager(RenderFrameHost* render_frame_host);
-
-  // Adds a given player to the list.  Not private to allow embedders
-  // to extend the manager and still utilize the base player management.
-  void AddPlayer(std::unique_ptr<media::MediaPlayerAndroid> player,
-                 int delegate_id);
-
-  // Removes the player with the specified id.
-  void DestroyPlayer(int player_id);
-
-  // Release resources associated to a player.
-  virtual void ReleaseResources(int player_id);
-
-  // Replaces a player with the specified id with a given MediaPlayerAndroid
-  // object. This will also return the original MediaPlayerAndroid object that
-  // was replaced.
-  std::unique_ptr<media::MediaPlayerAndroid> SwapPlayer(
-      int player_id,
-      std::unique_ptr<media::MediaPlayerAndroid> player);
-
-  // Called to request decoder resources. Returns true if the request is
-  // permitted, or false otherwise. The manager object maintains a list
-  // of active MediaPlayerAndroid objects and releases the inactive resources
-  // when needed. If |temporary| is true, the request is short lived
-  // and it will not be cleaned up when handling other requests.
-  // On the contrary, requests with false |temporary| value are subject to
-  // clean up if their players are idle.
-  virtual bool RequestDecoderResources(int player_id, bool temporary);
-
-  // MediaPlayerAndroid must call this to inform the manager that it has
-  // released the decoder resources. This can be triggered by the
-  // ReleasePlayer() call below, or when meta data is extracted, or when player
-  // is stuck in an error.
-  virtual void OnDecoderResourcesReleased(int player_id);
-
-  int RoutingID();
-
-  // Helper function to send messages to RenderFrameObserver.
-  bool Send(IPC::Message* msg);
-
- private:
-  // Constructs a MediaPlayerAndroid object.
-  std::unique_ptr<media::MediaPlayerAndroid> CreateMediaPlayer(
-      const MediaPlayerHostMsg_Initialize_Params& media_player_params,
-      bool hide_url_log);
-
-  // Instructs |player| to release its java player. This will not remove the
-  // player from |players_|.
-  void ReleasePlayer(media::MediaPlayerAndroid* player);
-
-  RenderFrameHost* const render_frame_host_;
-
-  // An array of managed players.
-  std::vector<std::unique_ptr<media::MediaPlayerAndroid>> players_;
-
-  typedef std::map<int, bool> ActivePlayerMap;
-  // Players that have requested decoding resources. Even though resource is
-  // requested, a player may be in a paused or error state and the manager
-  // will release its resources later.
-  ActivePlayerMap active_players_;
-
-  WebContents* const web_contents_;
-
-  // Object for retrieving resources media players.
-  std::unique_ptr<media::MediaResourceGetter> media_resource_getter_;
-
-  // Map of player IDs to delegate IDs for use with
-  // MediaWebContentsObserverAndroid.
-  std::map<int, int> player_id_to_delegate_id_map_;
-
-  // NOTE: Weak pointers must be invalidated before all other member variables.
-  base::WeakPtrFactory<BrowserMediaPlayerManager> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserMediaPlayerManager);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
diff --git a/content/browser/media/audio_output_stream_broker.cc b/content/browser/media/audio_output_stream_broker.cc
index 256eb2f6..24a8438a 100644
--- a/content/browser/media/audio_output_stream_broker.cc
+++ b/content/browser/media/audio_output_stream_broker.cc
@@ -14,6 +14,7 @@
 #include "content/public/browser/media_observer.h"
 #include "content/public/common/content_client.h"
 #include "media/audio/audio_logging.h"
+#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
 
 namespace content {
 
diff --git a/content/browser/media/audio_output_stream_broker_unittest.cc b/content/browser/media/audio_output_stream_broker_unittest.cc
index 0d5ea4b4..59e5b016 100644
--- a/content/browser/media/audio_output_stream_broker_unittest.cc
+++ b/content/browser/media/audio_output_stream_broker_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/unguessable_token.h"
 #include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
 #include "media/mojo/interfaces/audio_output_stream.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
diff --git a/content/browser/media/capture/lame_window_capturer_chromeos.cc b/content/browser/media/capture/lame_window_capturer_chromeos.cc
index ab594361..d3daea21 100644
--- a/content/browser/media/capture/lame_window_capturer_chromeos.cc
+++ b/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -13,6 +13,7 @@
 #include "components/viz/common/frame_sinks/copy_output_result.h"
 #include "media/base/limits.h"
 #include "media/base/video_util.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "mojo/public/cpp/base/shared_memory_utils.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/content/browser/media/hardware_key_media_controller.cc b/content/browser/media/hardware_key_media_controller.cc
index cb9b92a9..0d47843 100644
--- a/content/browser/media/hardware_key_media_controller.cc
+++ b/content/browser/media/hardware_key_media_controller.cc
@@ -8,8 +8,10 @@
 #include <utility>
 #include <vector>
 
+#include "base/metrics/histogram_macros.h"
 #include "content/public/browser/media_keys_listener_manager.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/accelerators/accelerator.h"
 
@@ -112,18 +114,23 @@
   switch (action) {
     case MediaSessionAction::kPreviousTrack:
       media_controller_ptr_->PreviousTrack();
+      RecordAction(MediaHardwareKeyAction::kActionPreviousTrack);
       return;
     case MediaSessionAction::kPlay:
       media_controller_ptr_->Resume();
+      RecordAction(MediaHardwareKeyAction::kActionPlay);
       return;
     case MediaSessionAction::kPause:
       media_controller_ptr_->Suspend();
+      RecordAction(MediaHardwareKeyAction::kActionPause);
       return;
     case MediaSessionAction::kNextTrack:
       media_controller_ptr_->NextTrack();
+      RecordAction(MediaHardwareKeyAction::kActionNextTrack);
       return;
     case MediaSessionAction::kStop:
       media_controller_ptr_->Stop();
+      RecordAction(MediaHardwareKeyAction::kActionStop);
       return;
     case MediaSessionAction::kSeekBackward:
     case MediaSessionAction::kSeekForward:
@@ -133,6 +140,10 @@
   }
 }
 
+void HardwareKeyMediaController::RecordAction(MediaHardwareKeyAction action) {
+  UMA_HISTOGRAM_ENUMERATION("Media.HardwareKeyPressed", action);
+}
+
 MediaSessionAction HardwareKeyMediaController::KeyCodeToMediaSessionAction(
     ui::KeyboardCode key_code) const {
   switch (key_code) {
diff --git a/content/browser/media/hardware_key_media_controller.h b/content/browser/media/hardware_key_media_controller.h
index d8150446..94dbb0fe 100644
--- a/content/browser/media/hardware_key_media_controller.h
+++ b/content/browser/media/hardware_key_media_controller.h
@@ -49,6 +49,17 @@
   }
 
  private:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class MediaHardwareKeyAction {
+    kActionPlay = 0,
+    kActionPause,
+    kActionStop,
+    kActionNextTrack,
+    kActionPreviousTrack,
+    kMaxValue = kActionPreviousTrack
+  };
+
   // Used for converting between MediaSessionAction and KeyboardCode.
   media_session::mojom::MediaSessionAction KeyCodeToMediaSessionAction(
       ui::KeyboardCode key_code) const;
@@ -60,6 +71,7 @@
 
   bool SupportsAction(media_session::mojom::MediaSessionAction action) const;
   void PerformAction(media_session::mojom::MediaSessionAction action);
+  void RecordAction(MediaHardwareKeyAction action);
 
   // Used to control the active session.
   media_session::mojom::MediaControllerPtr media_controller_ptr_;
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc
index 1fbe264..b9452f6 100644
--- a/content/browser/media/media_interface_proxy.cc
+++ b/content/browser/media/media_interface_proxy.cc
@@ -18,6 +18,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/service_manager_connection.h"
 #include "media/mojo/buildflags.h"
+#include "media/mojo/interfaces/cdm_proxy.mojom.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index 491b21e7..cdd22404 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -20,7 +20,6 @@
 #include "content/browser/media/session/media_session_service_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/media_session.h"
-#include "content/public/browser/media_session_observer.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "media/base/media_content_type.h"
@@ -33,6 +32,7 @@
 
 namespace content {
 
+using blink::mojom::MediaSessionPlaybackState;
 using MediaSessionUserAction = MediaSessionUmaHelper::MediaSessionUserAction;
 using media_session::mojom::MediaSessionInfo;
 using media_session::mojom::MediaPlaybackState;
@@ -147,10 +147,6 @@
   DCHECK(pepper_players_.empty());
   DCHECK(one_shot_players_.empty());
   DCHECK(audio_focus_state_ == State::INACTIVE);
-  for (auto& observer : observers_) {
-    observer.MediaSessionDestroyed();
-    observer.StopObserving();
-  }
 }
 
 void MediaSessionImpl::WebContentsDestroyed() {
@@ -187,29 +183,10 @@
   NotifyMediaSessionMetadataChange();
 }
 
-void MediaSessionImpl::AddObserver(MediaSessionObserver* observer) {
-  observers_.AddObserver(observer);
-  NotifyAddedObserver(observer);
-}
-
-void MediaSessionImpl::RemoveObserver(MediaSessionObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void MediaSessionImpl::NotifyAddedObserver(MediaSessionObserver* observer) {
-  observer->MediaSessionMetadataChanged(
-      routed_service_ ? routed_service_->metadata() : base::nullopt);
-  observer->MediaSessionActionsChanged(actions_);
-  observer->MediaSessionStateChanged(IsControllable(), IsActuallyPaused());
-}
-
 void MediaSessionImpl::NotifyMediaSessionMetadataChange() {
   const media_session::MediaMetadata& metadata = GetMediaMetadata();
 
-  for (auto& observer : observers_)
-    observer.MediaSessionMetadataChanged(metadata);
-
-  mojo_observers_.ForAllPtrs(
+  observers_.ForAllPtrs(
       [&metadata](media_session::mojom::MediaSessionObserver* observer) {
         observer->MediaSessionMetadataChanged(metadata);
       });
@@ -251,7 +228,6 @@
     }
   }
 
-  bool old_controllable = IsControllable();
   State old_audio_focus_state = audio_focus_state_;
   RequestSystemAudioFocus(required_audio_focus_type);
 
@@ -271,19 +247,14 @@
 
   UpdateRoutedService();
 
-  if (old_audio_focus_state != audio_focus_state_ ||
-      old_controllable != IsControllable()) {
-    NotifyLegacyObserversStateChange();
-    RebuildAndNotifyActionsChanged();
-  }
+  RebuildAndNotifyMediaSessionInfoChanged();
+  RebuildAndNotifyActionsChanged();
 
   return true;
 }
 
 void MediaSessionImpl::RemovePlayer(MediaSessionPlayerObserver* observer,
                                     int player_id) {
-  bool was_controllable = IsControllable();
-
   PlayerIdentifier identifier(observer, player_id);
 
   auto iter = normal_players_.find(identifier);
@@ -301,18 +272,11 @@
   AbandonSystemAudioFocusIfNeeded();
   UpdateRoutedService();
 
-  // The session may become controllable after removing a one-shot player.
-  // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
-  // about the state change.
-  if (!was_controllable && IsControllable()) {
-    NotifyLegacyObserversStateChange();
-    RebuildAndNotifyActionsChanged();
-  }
+  RebuildAndNotifyMediaSessionInfoChanged();
+  RebuildAndNotifyActionsChanged();
 }
 
 void MediaSessionImpl::RemovePlayers(MediaSessionPlayerObserver* observer) {
-  bool was_controllable = IsControllable();
-
   for (auto it = normal_players_.begin(); it != normal_players_.end();) {
     if (it->first.observer == observer)
       normal_players_.erase(it++);
@@ -337,13 +301,8 @@
   AbandonSystemAudioFocusIfNeeded();
   UpdateRoutedService();
 
-  // The session may become controllable after removing a one-shot player.
-  // However AbandonSystemAudioFocusIfNeeded will short-return and won't notify
-  // about the state change.
-  if (!was_controllable && IsControllable()) {
-    NotifyLegacyObserversStateChange();
-    RebuildAndNotifyActionsChanged();
-  }
+  RebuildAndNotifyMediaSessionInfoChanged();
+  RebuildAndNotifyActionsChanged();
 }
 
 void MediaSessionImpl::RecordSessionDuck() {
@@ -508,15 +467,6 @@
   return desired_audio_focus_type_ == AudioFocusType::kGain;
 }
 
-bool MediaSessionImpl::IsActuallyPaused() const {
-  if (routed_service_ && routed_service_->playback_state() ==
-                             blink::mojom::MediaSessionPlaybackState::PLAYING) {
-    return false;
-  }
-
-  return !IsActive();
-}
-
 void MediaSessionImpl::SetDuckingVolumeMultiplier(double multiplier) {
   ducking_volume_multiplier_ = base::ClampToRange(multiplier, 0.0, 1.0);
 }
@@ -531,7 +481,7 @@
     return;
   is_ducking_ = true;
   UpdateVolumeMultiplier();
-  OnMediaSessionInfoChanged();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 void MediaSessionImpl::StopDucking() {
@@ -539,7 +489,7 @@
     return;
   is_ducking_ = false;
   UpdateVolumeMultiplier();
-  OnMediaSessionInfoChanged();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 void MediaSessionImpl::UpdateVolumeMultiplier() {
@@ -568,12 +518,6 @@
   return !pepper_players_.empty();
 }
 
-std::unique_ptr<base::CallbackList<void(MediaSessionImpl::State)>::Subscription>
-MediaSessionImpl::RegisterMediaSessionStateChangedCallbackForTest(
-    const StateChangedCallback& cb) {
-  return media_session_state_listeners_.Add(cb);
-}
-
 void MediaSessionImpl::SetDelegateForTests(
     std::unique_ptr<AudioFocusDelegate> delegate) {
   delegate_ = std::move(delegate);
@@ -649,7 +593,7 @@
     it.observer->OnSetVolumeMultiplier(it.player_id,
                                        ducking_volume_multiplier_);
 
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 void MediaSessionImpl::OnResumeInternal(SuspendType suspend_type) {
@@ -664,7 +608,7 @@
   for (const auto& it : pepper_players_)
     it.observer->OnSetVolumeMultiplier(it.player_id, GetVolumeMultiplier());
 
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
@@ -673,8 +617,7 @@
       desired_audio_focus_type_(AudioFocusType::kGainTransientMayDuck),
       is_ducking_(false),
       ducking_volume_multiplier_(kDefaultDuckingVolumeMultiplier),
-      routed_service_(nullptr),
-      info_changed_timer_(new base::OneShotTimer()) {
+      routed_service_(nullptr) {
 #if defined(OS_ANDROID)
   session_android_.reset(new MediaSessionAndroid(this));
 #endif  // defined(OS_ANDROID)
@@ -751,8 +694,16 @@
   // If we have Pepper players then we should force ducking.
   info->force_duck = HasPepper();
 
-  info->playback_state = IsActuallyPaused() ? MediaPlaybackState::kPaused
-                                            : MediaPlaybackState::kPlaying;
+  // The playback state should use |IsActive| to determine whether we are
+  // playing or not. However, if there is a |routed_service_| which is playing
+  // then we should force the playback state to be playing.
+  info->playback_state =
+      IsActive() ? MediaPlaybackState::kPlaying : MediaPlaybackState::kPaused;
+  if (routed_service_ &&
+      routed_service_->playback_state() == MediaSessionPlaybackState::PLAYING) {
+    info->playback_state = MediaPlaybackState::kPlaying;
+  }
+
   info->is_controllable = IsControllable();
 
   return info;
@@ -772,7 +723,7 @@
       actions_.begin(), actions_.end());
   observer->MediaSessionActionsChanged(actions);
 
-  mojo_observers_.AddPtr(std::move(observer));
+  observers_.AddPtr(std::move(observer));
 }
 
 void MediaSessionImpl::FinishSystemAudioFocusRequest(
@@ -831,20 +782,10 @@
   is_ducking_ = false;
 
   SetAudioFocusState(State::INACTIVE);
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
   RebuildAndNotifyActionsChanged();
 }
 
-void MediaSessionImpl::NotifyLegacyObserversStateChange() {
-  media_session_state_listeners_.Notify(audio_focus_state_);
-
-  bool is_actually_paused = IsActuallyPaused();
-  for (auto& observer : observers_)
-    observer.MediaSessionStateChanged(IsControllable(), is_actually_paused);
-
-  OnMediaSessionInfoChanged();
-}
-
 void MediaSessionImpl::SetAudioFocusState(State audio_focus_state) {
   if (audio_focus_state == audio_focus_state_)
     return;
@@ -862,31 +803,28 @@
       break;
   }
 
-  OnMediaSessionInfoChanged();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 void MediaSessionImpl::FlushForTesting() {
-  mojo_observers_.FlushForTesting();
+  observers_.FlushForTesting();
 }
 
-void MediaSessionImpl::OnMediaSessionInfoChanged() {
-  info_changed_timer_->Start(
-      FROM_HERE, base::TimeDelta::FromSeconds(0),
-      base::BindOnce(
-          &MediaSessionImpl::NotifyMojoObserversMediaSessionInfoChanged,
-          base::Unretained(this)));
-}
-
-void MediaSessionImpl::NotifyMojoObserversMediaSessionInfoChanged() {
+void MediaSessionImpl::RebuildAndNotifyMediaSessionInfoChanged() {
   media_session::mojom::MediaSessionInfoPtr current_info =
       GetMediaSessionInfoSync();
 
-  mojo_observers_.ForAllPtrs(
+  if (current_info == session_info_)
+    return;
+
+  observers_.ForAllPtrs(
       [&current_info](media_session::mojom::MediaSessionObserver* observer) {
         observer->MediaSessionInfoChanged(current_info.Clone());
       });
 
   delegate_->MediaSessionInfoChanged(current_info.Clone());
+
+  session_info_ = std::move(current_info);
 }
 
 bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
@@ -900,7 +838,7 @@
   observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
 
   UpdateRoutedService();
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
 
   return result != AudioFocusDelegate::AudioFocusResult::kFailed;
 }
@@ -916,7 +854,7 @@
   one_shot_players_.insert(PlayerIdentifier(observer, player_id));
 
   UpdateRoutedService();
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
 
   return true;
 }
@@ -956,7 +894,7 @@
   if (service != routed_service_)
     return;
 
-  NotifyLegacyObserversStateChange();
+  RebuildAndNotifyMediaSessionInfoChanged();
   RebuildAndNotifyActionsChanged();
 }
 
@@ -1033,6 +971,7 @@
 
   NotifyMediaSessionMetadataChange();
   RebuildAndNotifyActionsChanged();
+  RebuildAndNotifyMediaSessionInfoChanged();
 }
 
 MediaSessionServiceImpl* MediaSessionImpl::ComputeServiceForRouting() {
@@ -1100,12 +1039,9 @@
 
   actions_ = actions;
 
-  for (auto& observer : observers_)
-    observer.MediaSessionActionsChanged(actions);
-
   std::vector<media_session::mojom::MediaSessionAction> actions_vec(
       actions.begin(), actions.end());
-  mojo_observers_.ForAllPtrs(
+  observers_.ForAllPtrs(
       [&actions_vec](media_session::mojom::MediaSessionObserver* observer) {
         observer->MediaSessionActionsChanged(actions_vec);
       });
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h
index ea66a904..4eeea228 100644
--- a/content/browser/media/session/media_session_impl.h
+++ b/content/browser/media/session/media_session_impl.h
@@ -12,17 +12,14 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include "base/callback_list.h"
 #include "base/containers/id_map.h"
 #include "base/macros.h"
-#include "base/observer_list.h"
 #include "base/optional.h"
 #include "base/timer/timer.h"
 #include "content/browser/media/session/audio_focus_delegate.h"
 #include "content/browser/media/session/media_session_uma_helper.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/media_session.h"
-#include "content/public/browser/media_session_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -50,7 +47,6 @@
 class MediaSessionImplServiceRoutingTest;
 class MediaSessionImplStateObserver;
 class MediaSessionImplVisibilityBrowserTest;
-class MediaSessionObserver;
 class MediaSessionPlayerObserver;
 class MediaSessionServiceImpl;
 class MediaSessionServiceImplBrowserTest;
@@ -121,9 +117,6 @@
   CONTENT_EXPORT void OnPlayerPaused(MediaSessionPlayerObserver* observer,
                                      int player_id);
 
-  void AddObserver(MediaSessionObserver* observer) override;
-  void RemoveObserver(MediaSessionObserver* observer) override;
-
   // Returns if the session is currently active.
   CONTENT_EXPORT bool IsActive() const;
 
@@ -168,15 +161,12 @@
       mojo::InterfaceRequest<media_session::mojom::MediaSession> request);
 
   // Returns information about the MediaSession.
-  media_session::mojom::MediaSessionInfoPtr GetMediaSessionInfoSync();
+  CONTENT_EXPORT media_session::mojom::MediaSessionInfoPtr
+  GetMediaSessionInfoSync();
 
   // Returns if the session can be controlled by the user.
   CONTENT_EXPORT bool IsControllable() const;
 
-  // Compute if the actual playback state is paused by combining the
-  // MediaSessionService declared state and guessed state (audio_focus_state_).
-  CONTENT_EXPORT bool IsActuallyPaused() const;
-
   // MediaSession overrides ---------------------------------------------------
 
   // Resume the media session.
@@ -299,13 +289,6 @@
   // delegate to abandon the audio focus.
   CONTENT_EXPORT void AbandonSystemAudioFocusIfNeeded();
 
-  // Notify all information that an observer needs to know when it's added.
-  void NotifyAddedObserver(MediaSessionObserver* observer);
-
-  // Notifies legacy (non-mojo) observers about the state change of the media
-  // session.
-  void NotifyLegacyObserversStateChange();
-
   // Internal method that should be used instead of setting audio_focus_state_.
   // It sets audio_focus_state_ and notifies observers about the state change.
   void SetAudioFocusState(State audio_focus_state);
@@ -313,9 +296,8 @@
   // Flushes any mojo bindings for testing.
   CONTENT_EXPORT void FlushForTesting();
 
-  // Notifies mojo observers that the MediaSessionInfo has changed.
-  void OnMediaSessionInfoChanged();
-  void NotifyMojoObserversMediaSessionInfoChanged();
+  // Notifies |observers_| and |delegate_| that |MediaSessionInfo| has changed.
+  void RebuildAndNotifyMediaSessionInfoChanged();
 
   // Update the volume multiplier when ducking state changes.
   void UpdateVolumeMultiplier();
@@ -324,11 +306,6 @@
   // ducking.
   double GetVolumeMultiplier() const;
 
-  // Registers a MediaSessionImpl state change callback.
-  CONTENT_EXPORT std::unique_ptr<base::CallbackList<void(State)>::Subscription>
-  RegisterMediaSessionStateChangedCallbackForTest(
-      const StateChangedCallback& cb);
-
   CONTENT_EXPORT bool AddPepperPlayer(MediaSessionPlayerObserver* observer,
                                       int player_id);
 
@@ -376,6 +353,9 @@
   // we request system audio focus.
   media_session::mojom::AudioFocusType desired_audio_focus_type_;
 
+  // The last updated |MediaSessionInfo| that was sent to |observers_|.
+  media_session::mojom::MediaSessionInfoPtr session_info_;
+
   MediaSessionUmaHelper uma_helper_;
 
   // The ducking state of this media session. The initial value is |false|, and
@@ -387,10 +367,6 @@
 
   double ducking_volume_multiplier_;
 
-  base::CallbackList<void(State)> media_session_state_listeners_;
-
-  base::ObserverList<MediaSessionObserver>::Unchecked observers_;
-
 #if defined(OS_ANDROID)
   std::unique_ptr<MediaSessionAndroid> session_android_;
 #endif  // defined(OS_ANDROID)
@@ -408,11 +384,7 @@
   // Bindings for Mojo pointers to |this| held by media route providers.
   mojo::BindingSet<media_session::mojom::MediaSession> bindings_;
 
-  mojo::InterfacePtrSet<media_session::mojom::MediaSessionObserver>
-      mojo_observers_;
-
-  // Timer used for debouncing MediaSessionInfoChanged events.
-  std::unique_ptr<base::OneShotTimer> info_changed_timer_;
+  mojo::InterfacePtrSet<media_session::mojom::MediaSessionObserver> observers_;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 
diff --git a/content/browser/media/session/media_session_impl_browsertest.cc b/content/browser/media/session/media_session_impl_browsertest.cc
index 83085ccc..120fbeba 100644
--- a/content/browser/media/session/media_session_impl_browsertest.cc
+++ b/content/browser/media/session/media_session_impl_browsertest.cc
@@ -33,7 +33,6 @@
 using content::WebContents;
 using content::MediaSession;
 using content::MediaSessionImpl;
-using content::MediaSessionObserver;
 using content::AudioFocusDelegate;
 using content::MediaSessionPlayerObserver;
 using content::MediaSessionUmaHelper;
diff --git a/content/browser/media/session/media_session_impl_unittest.cc b/content/browser/media/session/media_session_impl_unittest.cc
index 1ced75f4..8fe6cdf 100644
--- a/content/browser/media/session/media_session_impl_unittest.cc
+++ b/content/browser/media/session/media_session_impl_unittest.cc
@@ -126,12 +126,12 @@
     return media_session::test::GetMediaSessionInfoSync(session)->state;
   }
 
-  void ClearMojoObservers(MediaSessionImpl* session) {
-    session->mojo_observers_.CloseAll();
+  void ClearObservers(MediaSessionImpl* session) {
+    session->observers_.CloseAll();
   }
 
-  bool HasMojoObservers(MediaSessionImpl* session) {
-    return !session->mojo_observers_.empty();
+  bool HasObservers(MediaSessionImpl* session) {
+    return !session->observers_.empty();
   }
 
   void FlushForTesting(MediaSessionImpl* session) {
@@ -305,17 +305,17 @@
   EXPECT_FALSE(GetForceDuck(GetMediaSession()));
 }
 
-TEST_F(MediaSessionImplTest, RegisterMojoObserver) {
+TEST_F(MediaSessionImplTest, RegisterObserver) {
   // There is no way to get the number of mojo observers so we should just
   // remove them all and check if the mojo observers interface ptr set is
   // empty or not.
-  ClearMojoObservers(GetMediaSession());
-  EXPECT_FALSE(HasMojoObservers(GetMediaSession()));
+  ClearObservers(GetMediaSession());
+  EXPECT_FALSE(HasObservers(GetMediaSession()));
 
   MockMediaSessionMojoObserver observer(*GetMediaSession());
   FlushForTesting(GetMediaSession());
 
-  EXPECT_TRUE(HasMojoObservers(GetMediaSession()));
+  EXPECT_TRUE(HasObservers(GetMediaSession()));
 }
 
 TEST_F(MediaSessionImplTest, SessionInfo_PlaybackState) {
diff --git a/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index e2527849..60d28ecb 100644
--- a/content/browser/media/session/media_session_impl_visibility_browsertest.cc
+++ b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -22,9 +22,13 @@
 #include "content/shell/browser/shell.h"
 #include "media/base/media_switches.h"
 #include "services/media_session/public/cpp/features.h"
+#include "services/media_session/public/cpp/test/mock_media_session.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
+
+using media_session::mojom::MediaSessionInfo;
+
 namespace {
 static const char kStartPlayerScript[] =
     "document.getElementById('long-video').play()";
@@ -41,17 +45,11 @@
   DISABLED,
 };
 
-enum class SessionState {
-  ACTIVE,
-  SUSPENDED,
-  INACTIVE,
-};
-
 struct VisibilityTestData {
   MediaSuspend media_suspend;
   BackgroundResuming background_resuming;
-  SessionState session_state_before_hide;
-  SessionState session_state_after_hide;
+  MediaSessionInfo::SessionState session_state_before_hide;
+  MediaSessionInfo::SessionState session_state_after_hide;
 };
 }
 
@@ -80,24 +78,6 @@
     ContentBrowserTest::SetUpOnMainThread();
     web_contents_ = shell()->web_contents();
     media_session_ = MediaSessionImpl::Get(web_contents_);
-
-    media_session_state_loop_runners_[MediaSessionImpl::State::ACTIVE] =
-        new MessageLoopRunner();
-    media_session_state_loop_runners_[MediaSessionImpl::State::SUSPENDED] =
-        new MessageLoopRunner();
-    media_session_state_loop_runners_[MediaSessionImpl::State::INACTIVE] =
-        new MessageLoopRunner();
-    media_session_state_callback_subscription_ =
-        media_session_->RegisterMediaSessionStateChangedCallbackForTest(
-            base::Bind(&MediaSessionImplVisibilityBrowserTest::
-                           OnMediaSessionStateChanged,
-                       base::Unretained(this)));
-  }
-
-  void TearDownOnMainThread() override {
-    // Unsubscribe the callback subscription before tearing down, so that the
-    // CallbackList in MediaSession will be empty when it is destroyed.
-    media_session_state_callback_subscription_.reset();
   }
 
   void EnableDisableResumingBackgroundVideos(bool enable) {
@@ -126,52 +106,40 @@
 
   void StartPlayer() {
     LoadTestPage();
-
-    LOG(INFO) << "Starting player";
-    ClearMediaSessionStateLoopRunners();
     RunScript(kStartPlayerScript);
-    LOG(INFO) << "Waiting for session to be active";
-    WaitForMediaSessionState(MediaSessionImpl::State::ACTIVE);
+    WaitForMediaSessionState(MediaSessionInfo::SessionState::kActive);
   }
 
   // Maybe pause the player depending on whether the session state before hide
   // is SUSPENDED.
   void MaybePausePlayer() {
     ASSERT_TRUE(GetVisibilityTestData().session_state_before_hide !=
-                SessionState::INACTIVE);
+                MediaSessionInfo::SessionState::kInactive);
     if (GetVisibilityTestData().session_state_before_hide ==
-        SessionState::ACTIVE)
+        MediaSessionInfo::SessionState::kActive)
       return;
 
-    LOG(INFO) << "Pausing player";
-    ClearMediaSessionStateLoopRunners();
     RunScript(kPausePlayerScript);
-    LOG(INFO) << "Waiting for session to be suspended";
-    WaitForMediaSessionState(MediaSessionImpl::State::SUSPENDED);
+    WaitForMediaSessionState(MediaSessionInfo::SessionState::kSuspended);
   }
 
   void HideTab() {
-    LOG(INFO) << "Hiding the tab";
-    ClearMediaSessionStateLoopRunners();
     web_contents_->WasHidden();
   }
 
   void CheckSessionStateAfterHide() {
-    MediaSessionImpl::State state_before_hide =
-        ToMediaSessionState(GetVisibilityTestData().session_state_before_hide);
-    MediaSessionImpl::State state_after_hide =
-        ToMediaSessionState(GetVisibilityTestData().session_state_after_hide);
+    MediaSessionInfo::SessionState state_before_hide =
+        GetVisibilityTestData().session_state_before_hide;
+    MediaSessionInfo::SessionState state_after_hide =
+        GetVisibilityTestData().session_state_after_hide;
 
     if (state_before_hide == state_after_hide) {
-      LOG(INFO) << "Waiting for 1 second and check session state is unchanged";
       Wait(base::TimeDelta::FromSeconds(1));
-      ASSERT_EQ(state_after_hide, media_session_->audio_focus_state_);
+      ASSERT_EQ(state_after_hide,
+                media_session_->GetMediaSessionInfoSync()->state);
     } else {
-      LOG(INFO) << "Waiting for Session to change";
       WaitForMediaSessionState(state_after_hide);
     }
-
-    LOG(INFO) << "Test succeeded";
   }
 
  private:
@@ -185,16 +153,6 @@
     ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), script));
   }
 
-  void ClearMediaSessionStateLoopRunners() {
-    for (auto& state_loop_runner : media_session_state_loop_runners_)
-      state_loop_runner.second = new MessageLoopRunner();
-  }
-
-  void OnMediaSessionStateChanged(MediaSessionImpl::State state) {
-    ASSERT_TRUE(media_session_state_loop_runners_.count(state));
-    media_session_state_loop_runners_[state]->Quit();
-  }
-
   // TODO(zqzhang): This method is shared with
   // MediaRouterIntegrationTests. Move it into a general place.
   void Wait(base::TimeDelta timeout) {
@@ -204,26 +162,9 @@
     run_loop.Run();
   }
 
-  void WaitForMediaSessionState(MediaSessionImpl::State state) {
-    ASSERT_TRUE(media_session_state_loop_runners_.count(state));
-    media_session_state_loop_runners_[state]->Run();
-  }
-
-  MediaSessionImpl::State ToMediaSessionState(SessionState state) {
-    switch (state) {
-      case SessionState::ACTIVE:
-        return MediaSessionImpl::State::ACTIVE;
-        break;
-      case SessionState::SUSPENDED:
-        return MediaSessionImpl::State::SUSPENDED;
-        break;
-      case SessionState::INACTIVE:
-        return MediaSessionImpl::State::INACTIVE;
-        break;
-      default:
-        ADD_FAILURE() << "invalid SessionState to convert";
-        return MediaSessionImpl::State::INACTIVE;
-    }
+  void WaitForMediaSessionState(MediaSessionInfo::SessionState state) {
+    media_session::test::MockMediaSessionMojoObserver observer(*media_session_);
+    observer.WaitForState(state);
   }
 
   base::test::ScopedFeatureList ms_feature_list_;
@@ -231,17 +172,6 @@
 
   WebContents* web_contents_;
   MediaSessionImpl* media_session_;
-  // MessageLoopRunners for waiting MediaSession state to change. Note that the
-  // MessageLoopRunners can accept Quit() before calling Run(), thus the state
-  // change can still be captured before waiting. For example, the MediaSession
-  // might go active immediately after calling HTMLMediaElement.play(). A test
-  // can listen to the state change before calling play(), and then wait for the
-  // state change after play().
-  std::map<MediaSessionImpl::State, scoped_refptr<MessageLoopRunner>>
-      media_session_state_loop_runners_;
-  std::unique_ptr<
-      base::CallbackList<void(MediaSessionImpl::State)>::Subscription>
-      media_session_state_callback_subscription_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaSessionImplVisibilityBrowserTest);
 };
@@ -250,21 +180,29 @@
 
 VisibilityTestData kTestParams[] = {
     {MediaSuspend::ENABLED, BackgroundResuming::DISABLED,
-     SessionState::SUSPENDED, SessionState::INACTIVE},
-    {MediaSuspend::ENABLED, BackgroundResuming::DISABLED, SessionState::ACTIVE,
-     SessionState::INACTIVE},
-    {MediaSuspend::ENABLED, BackgroundResuming::ENABLED, SessionState::ACTIVE,
-     SessionState::SUSPENDED},
+     MediaSessionInfo::SessionState::kSuspended,
+     MediaSessionInfo::SessionState::kInactive},
+    {MediaSuspend::ENABLED, BackgroundResuming::DISABLED,
+     MediaSessionInfo::SessionState::kActive,
+     MediaSessionInfo::SessionState::kInactive},
     {MediaSuspend::ENABLED, BackgroundResuming::ENABLED,
-     SessionState::SUSPENDED, SessionState::SUSPENDED},
+     MediaSessionInfo::SessionState::kActive,
+     MediaSessionInfo::SessionState::kSuspended},
+    {MediaSuspend::ENABLED, BackgroundResuming::ENABLED,
+     MediaSessionInfo::SessionState::kSuspended,
+     MediaSessionInfo::SessionState::kSuspended},
     {MediaSuspend::DISABLED, BackgroundResuming::DISABLED,
-     SessionState::SUSPENDED, SessionState::SUSPENDED},
-    {MediaSuspend::DISABLED, BackgroundResuming::DISABLED, SessionState::ACTIVE,
-     SessionState::ACTIVE},
-    {MediaSuspend::DISABLED, BackgroundResuming::ENABLED, SessionState::ACTIVE,
-     SessionState::ACTIVE},
+     MediaSessionInfo::SessionState::kSuspended,
+     MediaSessionInfo::SessionState::kSuspended},
+    {MediaSuspend::DISABLED, BackgroundResuming::DISABLED,
+     MediaSessionInfo::SessionState::kActive,
+     MediaSessionInfo::SessionState::kActive},
     {MediaSuspend::DISABLED, BackgroundResuming::ENABLED,
-     SessionState::SUSPENDED, SessionState::SUSPENDED},
+     MediaSessionInfo::SessionState::kActive,
+     MediaSessionInfo::SessionState::kActive},
+    {MediaSuspend::DISABLED, BackgroundResuming::ENABLED,
+     MediaSessionInfo::SessionState::kSuspended,
+     MediaSessionInfo::SessionState::kSuspended},
 };
 
 }  // anonymous namespace
diff --git a/content/browser/media/session/media_session_service_impl_browsertest.cc b/content/browser/media/session/media_session_service_impl_browsertest.cc
index 66dc7f4..1e7f3813 100644
--- a/content/browser/media/session/media_session_service_impl_browsertest.cc
+++ b/content/browser/media/session/media_session_service_impl_browsertest.cc
@@ -5,7 +5,6 @@
 #include "content/browser/media/session/media_session_service_impl.h"
 
 #include "base/command_line.h"
-#include "base/run_loop.h"
 #include "content/browser/media/session/media_session_impl.h"
 #include "content/browser/media/session/media_session_player_observer.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -14,34 +13,13 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "media/base/media_content_type.h"
+#include "services/media_session/public/cpp/test/mock_media_session.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
 
 namespace {
 
-class MockMediaSessionObserver : public MediaSessionObserver {
- public:
-  explicit MockMediaSessionObserver(
-      MediaSession* session,
-      const base::Closure& closure_on_actions_change)
-      : MediaSessionObserver(session),
-        closure_on_actions_change_(closure_on_actions_change) {}
-
-  void MediaSessionActionsChanged(
-      const std::set<media_session::mojom::MediaSessionAction>& actions)
-      override {
-    // Wait for the page action to be present.
-    if (base::ContainsKey(
-            actions, media_session::mojom::MediaSessionAction::kSeekForward)) {
-      closure_on_actions_change_.Run();
-    }
-  }
-
- private:
-  base::Closure closure_on_actions_change_;
-};
-
 class MockWebContentsObserver : public WebContentsObserver {
  public:
   explicit MockWebContentsObserver(WebContents* contents,
@@ -129,11 +107,12 @@
   }
 
   bool ExecuteScriptToSetUpMediaSessionSync() {
-    // Using the actions change as the signal of completion.
-    base::RunLoop run_loop;
-    MockMediaSessionObserver observer(GetSession(), run_loop.QuitClosure());
     bool result = ExecuteScript(shell(), kSetUpMediaSessionScript);
-    run_loop.Run();
+    media_session::test::MockMediaSessionMojoObserver observer(*GetSession());
+    observer.WaitForActions();
+    EXPECT_TRUE(base::ContainsKey(
+        observer.actions_set(),
+        media_session::mojom::MediaSessionAction::kSeekForward));
     return result;
   }
 
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
index ce810d3..e9b93520 100644
--- a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
+++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -70,8 +70,14 @@
 
   std::string event_name = WebInputEvent::GetName(type);
 
-  if (latency.source_event_type() == ui::SourceEventType::KEY_PRESS)
+  if (latency.source_event_type() == ui::SourceEventType::KEY_PRESS) {
     event_name = "KeyPress";
+  } else if (event_name != "TouchEnd" && event_name != "TouchMove" &&
+             event_name != "TouchStart") {
+    // Only log events we care about (that are documented in histograms.xml),
+    // to avoid using memory and bandwidth for metrics that are not important.
+    return;
+  }
 
   std::string default_action_status =
       action_prevented ? "DefaultPrevented" : "DefaultAllowed";
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index c29ca87..5da41d3 100644
--- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
+++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -1185,72 +1185,6 @@
               ElementsAre());
 }
 
-// Some touch input histograms aren't reported for multi-finger touch. Other
-// input modalities shouldn't be impacted by there being an active multi-finger
-// touch gesture.
-TEST_F(RenderWidgetHostLatencyTrackerTest, WheelDuringMultiFingerTouch) {
-  SyntheticWebTouchEvent touch_event;
-  InputEventAckState ack_state = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-
-  {
-    // First touch start.
-    ui::LatencyInfo latency;
-    latency.set_source_event_type(ui::SourceEventType::TOUCH);
-    touch_event.PressPoint(1, 1);
-    tracker()->OnInputEvent(touch_event, &latency);
-    tracker()->OnInputEventAck(touch_event, &latency, ack_state);
-  }
-
-  {
-    // Second touch start.
-    ui::LatencyInfo latency;
-    latency.set_source_event_type(ui::SourceEventType::TOUCH);
-    touch_event.PressPoint(1, 1);
-    tracker()->OnInputEvent(touch_event, &latency);
-    tracker()->OnInputEventAck(touch_event, &latency, ack_state);
-  }
-
-  {
-    // Wheel event.
-    ui::LatencyInfo latency;
-    latency.set_source_event_type(ui::SourceEventType::WHEEL);
-    // These numbers are sensitive to where the histogram buckets are.
-    int timestamps_ms[] = {11, 25, 35};
-    auto wheel_event = SyntheticWebMouseWheelEventBuilder::Build(
-        blink::WebMouseWheelEvent::kPhaseChanged);
-    tracker()->OnInputEvent(touch_event, &latency);
-
-    ui::LatencyInfo fake_latency;
-    fake_latency.set_trace_id(kTraceEventId);
-    fake_latency.set_source_event_type(ui::SourceEventType::TOUCH);
-    fake_latency.AddLatencyNumberWithTimestamp(
-        ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
-        base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[0]),
-        1);
-
-    fake_latency.AddLatencyNumberWithTimestamp(
-        ui::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
-        base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[1]),
-        1);
-
-    fake_latency.AddLatencyNumberWithTimestamp(
-        ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
-        base::TimeTicks() + base::TimeDelta::FromMilliseconds(timestamps_ms[2]),
-        1);
-
-    // Call ComputeInputLatencyHistograms directly to avoid OnInputEventAck
-    // overwriting components.
-    tracker()->ComputeInputLatencyHistograms(wheel_event.GetType(),
-                                             fake_latency, ack_state);
-
-    tracker()->OnInputEventAck(wheel_event, &latency, ack_state);
-  }
-
-  EXPECT_THAT(histogram_tester().GetAllSamples(
-                  "Event.Latency.QueueingTime.MouseWheelDefaultAllowed"),
-              ElementsAre(Bucket(14, 1)));
-}
-
 TEST_F(RenderWidgetHostLatencyTrackerTest, TouchpadPinchEvents) {
   ui::LatencyInfo latency;
   latency.set_trace_id(kTraceEventId);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 2f2d84a..fcab5b30 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3132,7 +3132,6 @@
     service_manager::switches::kDisableWin32kLockDown,
     switches::kEnableWin7WebRtcHWH264Decoding,
     switches::kTrySupportedChannelLayouts,
-    switches::kTraceExportEventsToETW,
 #endif
 #if defined(USE_OZONE)
     switches::kOzonePlatform,
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index dc8ffbb..777bee8 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -26,7 +26,6 @@
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
 #include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
 #include "content/browser/frame_host/interstitial_page_impl.h"
-#include "content/browser/media/android/browser_media_player_manager.h"
 #include "content/browser/media/android/media_web_contents_observer_android.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
diff --git a/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
index 64c20b60..e7228848 100644
--- a/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
@@ -22,12 +22,17 @@
 #include "media/base/media_switches.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_metadata.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "media/capture/video/shared_memory_handle_provider.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/video_capture/public/mojom/constants.mojom.h"
+#include "services/video_capture/public/mojom/device_factory.mojom.h"
 #include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
+#include "services/video_capture/public/mojom/producer.mojom.h"
+#include "services/video_capture/public/mojom/scoped_access_permission.mojom.h"
+#include "services/video_capture/public/mojom/virtual_device.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/khronos/GLES2/gl2ext.h"
 #include "ui/compositor/compositor.h"
diff --git a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
index c4e1a9eb..cc18540 100644
--- a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
@@ -17,7 +17,9 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/video_capture/public/mojom/constants.mojom.h"
+#include "services/video_capture/public/mojom/device_factory.mojom.h"
 #include "services/video_capture/public/mojom/device_factory_provider.mojom.h"
+#include "services/video_capture/public/mojom/virtual_device.mojom.h"
 
 namespace content {
 
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc
index 00fc8db..33c64bdc 100644
--- a/content/browser/webui/shared_resources_data_source.cc
+++ b/content/browser/webui/shared_resources_data_source.cc
@@ -5,6 +5,7 @@
 #include "content/browser/webui/shared_resources_data_source.h"
 
 #include <stddef.h>
+#include <string>
 
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
@@ -16,6 +17,7 @@
 #include "build/build_config.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/url_constants.h"
@@ -45,6 +47,19 @@
 };
 using ResourcesMap = std::unordered_map<std::string, IdrGzipped>;
 
+#if defined(OS_CHROMEOS)
+const char kPolymerHtml[] = "polymer/v1_0/polymer/polymer.html";
+const char kPolymerJs[] = "polymer/v1_0/polymer/polymer-extracted.js";
+const char kPolymer2Html[] = "polymer/v1_0/polymer2/polymer.html";
+const char kPolymer2Js[] = "polymer/v1_0/polymer2/polymer-extracted.js";
+
+// Utility for determining if both Polymer 1 and Polymer 2 are needed.
+bool UsingMultiplePolymerVersions() {
+  return base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
+         base::FeatureList::IsEnabled(features::kWebUIPolymer2Exceptions);
+}
+#endif  // defined(OS_CHROMEOS)
+
 const std::map<std::string, std::string> CreatePathPrefixAliasesMap() {
   // TODO(rkc): Once we have a separate source for apps, remove '*/apps/'
   // aliases.
@@ -59,6 +74,11 @@
       {"../../webui/resources/cr_elements/", "cr_elements/"},
   };
 
+#if defined(OS_CHROMEOS)
+  if (UsingMultiplePolymerVersions())
+    return aliases;
+#endif  // defined(OS_CHROMEOS)
+
 #if !defined(OS_ANDROID)
   if (base::FeatureList::IsEnabled(features::kWebUIPolymer2)) {
     aliases["../../../third_party/polymer/v1_0/components-chromium/polymer2/"] =
@@ -95,6 +115,11 @@
 
 #if !defined(OS_ANDROID)
 bool ShouldIgnore(std::string resource) {
+#if defined(OS_CHROMEOS)
+  if (UsingMultiplePolymerVersions())
+    return false;
+#endif  // defined(OS_CHROMEOS)
+
   if (base::FeatureList::IsEnabled(features::kWebUIPolymer2) &&
       base::StartsWith(
           resource,
@@ -209,8 +234,19 @@
     const std::string& path,
     const ResourceRequestInfo::WebContentsGetter& wc_getter,
     const URLDataSource::GotDataCallback& callback) {
-  int idr = GetIdrForPath(path);
-  DCHECK_NE(-1, idr) << " path: " << path;
+  std::string updated_path = path;
+#if defined(OS_CHROMEOS)
+  // If this is a Polymer request and multiple Polymer versions are enabled,
+  // return the Polymer 2 path unless the request is from the
+  // |disabled_polymer2_host_|.
+  if ((path == kPolymerHtml || path == kPolymerJs) &&
+      UsingMultiplePolymerVersions() && !IsPolymer2DisabledForPage(wc_getter)) {
+    updated_path = path == kPolymerHtml ? kPolymer2Html : kPolymer2Js;
+  }
+#endif  // defined(OS_CHROMEOS)
+
+  int idr = GetIdrForPath(updated_path);
+  DCHECK_NE(-1, idr) << " path: " << updated_path;
   scoped_refptr<base::RefCountedMemory> bytes;
 
   if (idr == IDR_WEBUI_CSS_TEXT_DEFAULTS) {
@@ -280,6 +316,15 @@
 scoped_refptr<base::SingleThreadTaskRunner>
 SharedResourcesDataSource::TaskRunnerForRequestPath(
     const std::string& path) const {
+  // Since WebContentsGetter can only be run on the UI thread, always return
+  // a task runner if we need to choose between Polymer resources based on the
+  // WebContents that is requesting the resource.
+  // TODO (rbpotter): Remove this once the OOBE Polymer 2 migration is complete.
+#if defined(OS_CHROMEOS)
+  if (UsingMultiplePolymerVersions())
+    return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
+#endif  // defined(OS_CHROMEOS)
+
   int idr = GetIdrForPath(path);
   if (idr == IDR_WEBUI_CSS_TEXT_DEFAULTS ||
       idr == IDR_WEBUI_CSS_TEXT_DEFAULTS_MD) {
@@ -313,4 +358,26 @@
   return it != GetResourcesMap().end() ? it->second.gzipped : false;
 }
 
+#if defined(OS_CHROMEOS)
+void SharedResourcesDataSource::DisablePolymer2ForHost(
+    const std::string& host) {
+  DCHECK(disabled_polymer2_host_.empty() || host == disabled_polymer2_host_);
+  disabled_polymer2_host_ = host;
+}
+
+// Returns true if the WebContents making the request has disabled Polymer 2.
+bool SharedResourcesDataSource::IsPolymer2DisabledForPage(
+    const ResourceRequestInfo::WebContentsGetter& wc_getter) {
+  // Return false in these cases, which sometimes occur in tests.
+  if (!wc_getter)
+    return false;
+
+  content::WebContents* web_contents = wc_getter.Run();
+  if (!web_contents)
+    return false;
+
+  return web_contents->GetLastCommittedURL().host_piece() ==
+         disabled_polymer2_host_;
+}
+#endif  // defined(OS_CHROMEOS)
 }  // namespace content
diff --git a/content/browser/webui/shared_resources_data_source.h b/content/browser/webui/shared_resources_data_source.h
index 27a8e3d..4e114cf 100644
--- a/content/browser/webui/shared_resources_data_source.h
+++ b/content/browser/webui/shared_resources_data_source.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_BROWSER_WEBUI_SHARED_RESOURCES_DATA_SOURCE_H_
 #define CONTENT_BROWSER_WEBUI_SHARED_RESOURCES_DATA_SOURCE_H_
 
+#include <string>
+
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
@@ -31,8 +33,18 @@
   std::string GetAccessControlAllowOriginForOrigin(
       const std::string& origin) const override;
   bool IsGzipped(const std::string& path) const override;
+#if defined(OS_CHROMEOS)
+  void DisablePolymer2ForHost(const std::string& host) override;
+#endif  // defined (OS_CHROMEOS)
 
  private:
+#if defined(OS_CHROMEOS)
+  std::string disabled_polymer2_host_;
+
+  bool IsPolymer2DisabledForPage(
+      const ResourceRequestInfo::WebContentsGetter& wc_getter);
+#endif  // defined (OS_CHROMEOS)
+
   ~SharedResourcesDataSource() override;
 
   DISALLOW_COPY_AND_ASSIGN(SharedResourcesDataSource);
diff --git a/content/browser/worker_host/mock_shared_worker.cc b/content/browser/worker_host/mock_shared_worker.cc
index b9ddcc6..8679ca43 100644
--- a/content/browser/worker_host/mock_shared_worker.cc
+++ b/content/browser/worker_host/mock_shared_worker.cc
@@ -7,6 +7,7 @@
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
diff --git a/content/browser/worker_host/mock_shared_worker.h b/content/browser/worker_host/mock_shared_worker.h
index 848486cb..b5fc971 100644
--- a/content/browser/worker_host/mock_shared_worker.h
+++ b/content/browser/worker_host/mock_shared_worker.h
@@ -16,8 +16,11 @@
 #include "content/browser/worker_host/shared_worker_host.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/worker/shared_worker_factory.mojom.h"
+#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h"
 
 class GURL;
 
diff --git a/content/browser/worker_host/shared_worker_connector_impl.cc b/content/browser/worker_host/shared_worker_connector_impl.cc
index 9ec48360..4b410f13 100644
--- a/content/browser/worker_host/shared_worker_connector_impl.cc
+++ b/content/browser/worker_host/shared_worker_connector_impl.cc
@@ -12,6 +12,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
 
 namespace content {
 
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 9a59717..e63a9779f 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
 #include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom.h"
 #include "third_party/blink/public/platform/web_feature.mojom.h"
 
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 80cfee5..8a06b22 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -41,6 +41,7 @@
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
 #include "url/origin.h"
 
 namespace content {
diff --git a/content/browser/worker_host/shared_worker_service_impl_unittest.cc b/content/browser/worker_host/shared_worker_service_impl_unittest.cc
index 20c8611..ddddded 100644
--- a/content/browser/worker_host/shared_worker_service_impl_unittest.cc
+++ b/content/browser/worker_host/shared_worker_service_impl_unittest.cc
@@ -27,6 +27,7 @@
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h"
 
 using blink::MessagePortChannel;
 
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index f5e7a0df..a9ce636 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -213,14 +213,11 @@
   if (gpu_preferences.gpu_startup_dialog)
     WaitForDebugger("Gpu");
 
-#if defined(OS_WIN)
-  if (gpu_preferences.enable_trace_export_events_to_etw)
-    base::trace_event::TraceEventETWExport::EnableETWExport();
-#endif
-
   base::Time start_time = base::Time::Now();
 
 #if defined(OS_WIN)
+  base::trace_event::TraceEventETWExport::EnableETWExport();
+
   // Prevent Windows from displaying a modal dialog on failures like not being
   // able to load a DLL.
   SetErrorMode(
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index afccfd22..753477a9 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -680,7 +680,6 @@
                         ? mContext.getString(R.string.actionbar_textselection_title)
                         : null);
         mode.setSubtitle(null);
-        createActionMenu(mode, menu);
     }
 
     @Override
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 517045a..e0d85c4 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -24,8 +24,6 @@
   visibility = [ "//content/*" ]
   sources = [
     "android/android_overlay_provider.h",
-    "android/browser_media_player_manager_register.cc",
-    "android/browser_media_player_manager_register.h",
     "android/child_process_importance.h",
     "android/compositor.h",
     "android/compositor_client.h",
@@ -33,6 +31,8 @@
     "android/devtools_auth.h",
     "android/gpu_video_accelerator_factories_provider.h",
     "android/java_interfaces.h",
+    "android/media_url_interceptor_register.cc",
+    "android/media_url_interceptor_register.h",
     "android/motion_event_action.h",
     "android/synchronous_compositor.cc",
     "android/synchronous_compositor.h",
@@ -173,8 +173,6 @@
     "media_keys_listener_manager.h",
     "media_request_state.h",
     "media_session.h",
-    "media_session_observer.cc",
-    "media_session_observer.h",
     "media_stream_request.cc",
     "media_stream_request.h",
     "message_port_provider.h",
diff --git a/content/public/browser/android/browser_media_player_manager_register.cc b/content/public/browser/android/browser_media_player_manager_register.cc
deleted file mode 100644
index 6145716..0000000
--- a/content/public/browser/android/browser_media_player_manager_register.cc
+++ /dev/null
@@ -1,22 +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 "content/public/browser/android/browser_media_player_manager_register.h"
-
-#include "content/browser/media/android/browser_media_player_manager.h"
-#include "content/browser/media/android/media_player_renderer.h"
-
-namespace content {
-
-void RegisterMediaUrlInterceptor(
-    media::MediaUrlInterceptor* media_url_interceptor) {
-  // TODO(tguilbert): Update this filename when deleting WMPA and the
-  // BrowserMediaPlayerManager. See crbug.com/570711.
-  content::BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
-      media_url_interceptor);
-  content::MediaPlayerRenderer::RegisterMediaUrlInterceptor(
-      media_url_interceptor);
-}
-
-}  // namespace content
diff --git a/content/public/browser/android/media_url_interceptor_register.cc b/content/public/browser/android/media_url_interceptor_register.cc
new file mode 100644
index 0000000..feedada
--- /dev/null
+++ b/content/public/browser/android/media_url_interceptor_register.cc
@@ -0,0 +1,17 @@
+// 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 "content/public/browser/android/media_url_interceptor_register.h"
+
+#include "content/browser/media/android/media_player_renderer.h"
+
+namespace content {
+
+void RegisterMediaUrlInterceptor(
+    media::MediaUrlInterceptor* media_url_interceptor) {
+  content::MediaPlayerRenderer::RegisterMediaUrlInterceptor(
+      media_url_interceptor);
+}
+
+}  // namespace content
diff --git a/content/public/browser/android/browser_media_player_manager_register.h b/content/public/browser/android/media_url_interceptor_register.h
similarity index 65%
rename from content/public/browser/android/browser_media_player_manager_register.h
rename to content/public/browser/android/media_url_interceptor_register.h
index 49ae041a..6b70f69 100644
--- a/content/public/browser/android/browser_media_player_manager_register.h
+++ b/content/public/browser/android/media_url_interceptor_register.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_REGISTER_H_
-#define CONTENT_PUBLIC_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_REGISTER_H_
+#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_MEDIA_URL_INTERCEPTOR_REGISTER_H_
+#define CONTENT_PUBLIC_BROWSER_ANDROID_MEDIA_URL_INTERCEPTOR_REGISTER_H_
 
 #include "content/common/content_export.h"
 
@@ -19,4 +19,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_PUBLIC_BROWSER_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_REGISTER_H_
+#endif  // CONTENT_PUBLIC_BROWSER_ANDROID_MEDIA_URL_INTERCEPTOR_REGISTER_H_
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc
index 2e21f99..d16a9348 100644
--- a/content/public/browser/gpu_utils.cc
+++ b/content/public/browser/gpu_utils.cc
@@ -99,10 +99,6 @@
       command_line->HasSwitch(switches::kDisableSoftwareRasterizer);
   gpu_preferences.log_gpu_control_list_decisions =
       command_line->HasSwitch(switches::kLogGpuControlListDecisions);
-#if defined(OS_WIN)
-  gpu_preferences.enable_trace_export_events_to_etw =
-      command_line->HasSwitch(switches::kTraceExportEventsToETW);
-#endif
   GetUintFromSwitch(command_line, switches::kMaxActiveWebGLContexts,
                     &gpu_preferences.max_active_webgl_contexts);
   gpu_preferences.gpu_startup_dialog =
@@ -122,6 +118,10 @@
       command_line->HasSwitch(switches::kEnableOopRasterizationDDL);
   gpu_preferences.enable_passthrough_raster_decoder =
       command_line->HasSwitch(switches::kEnablePassthroughRasterDecoder);
+#if defined(OS_WIN)
+  if (gpu_preferences.enable_oop_rasterization)
+    gpu_preferences.enable_passthrough_raster_decoder = true;
+#endif
 
   gpu_preferences.enable_vulkan =
       command_line->HasSwitch(switches::kEnableVulkan);
diff --git a/content/public/browser/media_session.h b/content/public/browser/media_session.h
index 969bd126..725ef06 100644
--- a/content/public/browser/media_session.h
+++ b/content/public/browser/media_session.h
@@ -13,7 +13,6 @@
 
 namespace content {
 
-class MediaSessionObserver;
 class WebContents;
 
 // MediaSession manages the media session and audio focus for a given
@@ -92,12 +91,6 @@
 
  protected:
   MediaSession() = default;
-
- private:
-  friend class MediaSessionObserver;
-
-  virtual void AddObserver(MediaSessionObserver* observer) = 0;
-  virtual void RemoveObserver(MediaSessionObserver* observer) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/media_session_observer.cc b/content/public/browser/media_session_observer.cc
deleted file mode 100644
index dfd4e11..0000000
--- a/content/public/browser/media_session_observer.cc
+++ /dev/null
@@ -1,31 +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 "content/public/browser/media_session_observer.h"
-
-#include "content/browser/media/session/media_session_impl.h"
-
-namespace content {
-
-MediaSessionObserver::MediaSessionObserver(MediaSession* media_session)
-    : media_session_(media_session) {
-  if (media_session_)
-    media_session_->AddObserver(this);
-}
-
-MediaSessionObserver::~MediaSessionObserver() {
-  StopObserving();
-}
-
-MediaSession* MediaSessionObserver::media_session() const {
-  return media_session_;
-}
-
-void MediaSessionObserver::StopObserving() {
-  if (media_session_)
-    media_session_->RemoveObserver(this);
-  media_session_ = nullptr;
-}
-
-}  // namespace content
diff --git a/content/public/browser/media_session_observer.h b/content/public/browser/media_session_observer.h
deleted file mode 100644
index 233f1d4..0000000
--- a/content/public/browser/media_session_observer.h
+++ /dev/null
@@ -1,72 +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 CONTENT_PUBLIC_BROWSER_MEDIA_SESSION_OBSERVER_H_
-#define CONTENT_PUBLIC_BROWSER_MEDIA_SESSION_OBSERVER_H_
-
-#include <set>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "content/common/content_export.h"
-
-namespace media_session {
-namespace mojom {
-enum class MediaSessionAction;
-}  // namespace mojom
-}  // namespace media_session
-
-namespace media_session {
-struct MediaMetadata;
-}  // namespace media_session
-
-namespace content {
-
-class MediaSession;
-
-// The observer for observing MediaSession events.
-class CONTENT_EXPORT MediaSessionObserver {
- public:
-  // Gets the observed MediaSession. Will return null when the session is
-  // destroyed.
-  MediaSession* media_session() const;
-
-  // Called when the observed MediaSession is being destroyed. Give subclass a
-  // chance to clean up. media_session() will return nullptr after this method
-  // is called.
-  virtual void MediaSessionDestroyed() {}
-
-  // Called when the observed MediaSession has changed its state.
-  virtual void MediaSessionStateChanged(bool is_controllable,
-                                        bool is_suspended) {}
-
-  // Called when the observed MediaSession has changed metadata.
-  virtual void MediaSessionMetadataChanged(
-      const base::Optional<media_session::MediaMetadata>& metadata) {}
-
-  // Called when the media session action list has changed.
-  virtual void MediaSessionActionsChanged(
-      const std::set<media_session::mojom::MediaSessionAction>& action) {}
-
- protected:
-  // Create a MediaSessionObserver and start observing a session.
-  explicit MediaSessionObserver(MediaSession* media_session);
-  // Destruct a MediaSessionObserver and remove it from the session if it's
-  // still observing.
-  virtual ~MediaSessionObserver();
-
- private:
-  friend class MediaSessionImpl;
-
-  void StopObserving();
-
-  // Weak pointer to MediaSession
-  MediaSession* media_session_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaSessionObserver);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_BROWSER_MEDIA_SESSION_OBSERVER_H_
diff --git a/content/public/browser/url_data_source.cc b/content/public/browser/url_data_source.cc
index 4056311c..31edfa0 100644
--- a/content/public/browser/url_data_source.cc
+++ b/content/public/browser/url_data_source.cc
@@ -8,7 +8,11 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/task/post_task.h"
+#include "content/browser/resource_context_impl.h"
 #include "content/browser/webui/url_data_manager.h"
+#include "content/browser/webui/url_data_manager_backend.h"
+#include "content/browser/webui/url_data_source_impl.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/url_constants.h"
@@ -16,12 +20,38 @@
 
 namespace content {
 
+namespace {
+
+URLDataSource* GetSourceForURLHelper(ResourceContext* resource_context,
+                                     const GURL& url) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  URLDataSourceImpl* source =
+      GetURLDataManagerForResourceContext(resource_context)
+          ->GetDataSourceFromURL(url);
+  return source->source();
+}
+
+}  // namespace
+
 // static
 void URLDataSource::Add(BrowserContext* browser_context,
                         std::unique_ptr<URLDataSource> source) {
   URLDataManager::AddDataSource(browser_context, std::move(source));
 }
 
+// static
+void URLDataSource::GetSourceForURL(
+    BrowserContext* browser_context,
+    const GURL& url,
+    base::OnceCallback<void(URLDataSource*)> callback) {
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {content::BrowserThread::IO},
+      base::BindOnce(&GetSourceForURLHelper,
+                     browser_context->GetResourceContext(), url),
+      std::move(callback));
+}
+
 scoped_refptr<base::SingleThreadTaskRunner>
 URLDataSource::TaskRunnerForRequestPath(const std::string& path) const {
   return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI});
@@ -84,4 +114,6 @@
   return false;
 }
 
+void URLDataSource::DisablePolymer2ForHost(const std::string& host) {}
+
 }  // namespace content
diff --git a/content/public/browser/url_data_source.h b/content/public/browser/url_data_source.h
index b7d96e7..22ed30b 100644
--- a/content/public/browser/url_data_source.h
+++ b/content/public/browser/url_data_source.h
@@ -35,6 +35,14 @@
   static void Add(BrowserContext* browser_context,
                   std::unique_ptr<URLDataSource> source);
 
+  // Gets a reference to the URL data source for |url| and runs |callback| with
+  // it as an argument.
+  // TODO (rbpotter): Remove this function when the OOBE page Polymer 2
+  // migration is complete.
+  static void GetSourceForURL(BrowserContext* browser_context,
+                              const GURL& url,
+                              base::OnceCallback<void(URLDataSource*)>);
+
   virtual ~URLDataSource() {}
 
   // The name of this source.
@@ -153,6 +161,13 @@
 
   // Whether |path| is gzipped (and should be transmitted gzipped).
   virtual bool IsGzipped(const std::string& path) const;
+
+  // Called on the UI thread. For the shared resource, disables using Polymer 2
+  // for requests from |host|, even if WebUIPolymer2 is enabled. Assumes this
+  // method is only called from one host.
+  // TODO (rbpotter): Remove this function when the OOBE page Polymer 2
+  // migration is complete.
+  virtual void DisablePolymer2ForHost(const std::string& host);
 };
 
 }  // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 356e045..452842b58 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -684,6 +684,17 @@
 };
 #endif  // !defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+// If this flag is enabled, Web UI pages can call DisablePolymer2() on the
+// shared resource during setup in order to use Polymer 1, regardless of the
+// state of the WebUIPolymer2 flag. Note: Currently, this only supports one Web
+// UI page disabling Polymer 2.
+// TODO(dpapad): Remove this once Polymer 2 migration is done,
+// https://crbug.com/738611.
+const base::Feature kWebUIPolymer2Exceptions{"WebUIPolymer2Exceptions",
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
+#endif  // defined(OS_CHROMEOS)
+
 #if defined(OS_MACOSX)
 // Enables caching of media devices for the purpose of enumerating them.
 const base::Feature kDeviceMonitorMac{"DeviceMonitorMac",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 6ea67f3..2cfd88a9 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -159,6 +159,10 @@
 CONTENT_EXPORT extern const base::Feature kWebUIPolymer2;
 #endif  // !defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+CONTENT_EXPORT extern const base::Feature kWebUIPolymer2Exceptions;
+#endif
+
 #if defined(OS_MACOSX)
 CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
 CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 535f50b..35c1203 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -1025,10 +1025,6 @@
 // processes.
 const char kPpapiSubpixelRenderingSetting[] =
     "ppapi-subpixel-rendering-setting";
-
-// Enables the exporting of the tracing events to ETW. This is only supported on
-// Windows Vista and later.
-const char kTraceExportEventsToETW[] = "trace-export-events-to-etw";
 #endif
 
 #if defined(ENABLE_IPC_FUZZER)
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index f420773..bb9e0db 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -291,7 +291,6 @@
 CONTENT_EXPORT extern const char kMemoryPressureThresholdsMb[];
 CONTENT_EXPORT extern const char kPpapiAntialiasedTextEnabled[];
 CONTENT_EXPORT extern const char kPpapiSubpixelRenderingSetting[];
-CONTENT_EXPORT extern const char kTraceExportEventsToETW[];
 #endif
 
 #if defined(ENABLE_IPC_FUZZER)
diff --git a/content/public/test/url_loader_interceptor.h b/content/public/test/url_loader_interceptor.h
index 9ffdec9..cbf4252 100644
--- a/content/public/test/url_loader_interceptor.h
+++ b/content/public/test/url_loader_interceptor.h
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace content {
diff --git a/content/renderer/dom_storage/local_storage_cached_areas.cc b/content/renderer/dom_storage/local_storage_cached_areas.cc
index 5cd2f24..32dc5d9 100644
--- a/content/renderer/dom_storage/local_storage_cached_areas.cc
+++ b/content/renderer/dom_storage/local_storage_cached_areas.cc
@@ -134,7 +134,6 @@
     LOCAL_HISTOGRAM_ENUMERATION("SessionStorage.RendererAreaCacheHit", metric);
 
   if (!result) {
-    ClearAreasIfNeeded();
     if (!dom_namespace) {
       dom_namespace = &cached_namespaces_[namespace_id];
     }
@@ -155,6 +154,7 @@
           this, scheduler);
     }
     dom_namespace->cached_areas.emplace(origin, result);
+    ClearAreasIfNeeded();
   }
   return result;
 }
diff --git a/content/renderer/dom_storage/mock_leveldb_wrapper.cc b/content/renderer/dom_storage/mock_leveldb_wrapper.cc
index faaec1c..4f7dead 100644
--- a/content/renderer/dom_storage/mock_leveldb_wrapper.cc
+++ b/content/renderer/dom_storage/mock_leveldb_wrapper.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
 
 namespace content {
 
diff --git a/content/renderer/dom_storage/mock_leveldb_wrapper.h b/content/renderer/dom_storage/mock_leveldb_wrapper.h
index d459ddba..2a2d4103 100644
--- a/content/renderer/dom_storage/mock_leveldb_wrapper.h
+++ b/content/renderer/dom_storage/mock_leveldb_wrapper.h
@@ -8,6 +8,7 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h"
 #include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
 #include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h"
 
diff --git a/content/renderer/gpu_benchmarking_extension.cc b/content/renderer/gpu_benchmarking_extension.cc
index 0fedd34b..924ca71 100644
--- a/content/renderer/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu_benchmarking_extension.cc
@@ -45,6 +45,7 @@
 #include "gpu/config/gpu_driver_bug_workaround_type.h"
 #include "gpu/ipc/common/gpu_messages.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
 #include "third_party/blink/public/platform/web_mouse_event.h"
 #include "third_party/blink/public/web/blink.h"
 #include "third_party/blink/public/web/web_image_cache.h"
@@ -264,7 +265,7 @@
   }
 }
 
-void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
+void RunCallbackHelper(CallbackAndContext* callback_and_context) {
   v8::Isolate* isolate = callback_and_context->isolate();
   v8::HandleScope scope(isolate);
   v8::Local<v8::Context> context = callback_and_context->GetContext();
@@ -277,6 +278,10 @@
   }
 }
 
+void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
+  RunCallbackHelper(callback_and_context);
+}
+
 bool BeginSmoothScroll(GpuBenchmarkingContext* context,
                        gin::Arguments* args,
                        mojom::InputInjectorPtr& injector,
@@ -473,6 +478,12 @@
   }
 }
 
+void OnSwapCompletedHelper(CallbackAndContext* callback_and_context,
+                           blink::WebLayerTreeView::SwapResult,
+                           base::TimeTicks) {
+  RunCallbackHelper(callback_and_context);
+}
+
 // This function is only used for correctness testing of this experimental
 // feature; no need for it in release builds.
 // Also note:  You must execute Chrome with `--no-sandbox` and
@@ -575,7 +586,9 @@
                  &GpuBenchmarking::GetGpuDriverBugWorkarounds)
       .SetMethod("startProfiling", &GpuBenchmarking::StartProfiling)
       .SetMethod("stopProfiling", &GpuBenchmarking::StopProfiling)
-      .SetMethod("freeze", &GpuBenchmarking::Freeze);
+      .SetMethod("freeze", &GpuBenchmarking::Freeze)
+      .SetMethod("addSwapCompletionEventListener",
+                 &GpuBenchmarking::AddSwapCompletionEventListener);
 }
 
 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
@@ -1194,4 +1207,25 @@
   context.web_view()->SetPageFrozen(true);
 }
 
+bool GpuBenchmarking::AddSwapCompletionEventListener(gin::Arguments* args) {
+  v8::Local<v8::Function> callback;
+  if (!GetArg(args, &callback))
+    return false;
+  if (!render_frame_)
+    return false;
+  LayerTreeView* layer_tree_view =
+      render_frame_->GetLocalRootRenderWidget()->layer_tree_view();
+  if (!layer_tree_view)
+    return false;
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return false;
+
+  auto callback_and_context = base::MakeRefCounted<CallbackAndContext>(
+      args->isolate(), callback, context.web_frame()->MainWorldScriptContext());
+  layer_tree_view->NotifySwapTime(base::BindOnce(
+      &OnSwapCompletedHelper, base::RetainedRef(callback_and_context)));
+  return true;
+}
+
 }  // namespace content
diff --git a/content/renderer/gpu_benchmarking_extension.h b/content/renderer/gpu_benchmarking_extension.h
index 1384789..e113293e 100644
--- a/content/renderer/gpu_benchmarking_extension.h
+++ b/content/renderer/gpu_benchmarking_extension.h
@@ -94,6 +94,10 @@
   // Freezes a page, used to transition the page to the FROZEN lifecycle state.
   void Freeze();
 
+  // Register a callback that should be fired when the next swap completes.
+  // The callback is removed once it's executed.
+  bool AddSwapCompletionEventListener(gin::Arguments* args);
+
   RenderFrameImpl* render_frame_;
   mojom::InputInjectorPtr input_injector_;
   DISALLOW_COPY_AND_ASSIGN(GpuBenchmarking);
diff --git a/content/renderer/media/audio/mojo_audio_input_ipc.cc b/content/renderer/media/audio/mojo_audio_input_ipc.cc
index 500e7c7..87a4892 100644
--- a/content/renderer/media/audio/mojo_audio_input_ipc.cc
+++ b/content/renderer/media/audio/mojo_audio_input_ipc.cc
@@ -10,6 +10,7 @@
 #include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "media/audio/audio_device_description.h"
+#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace content {
diff --git a/content/renderer/media/audio/mojo_audio_input_ipc.h b/content/renderer/media/audio/mojo_audio_input_ipc.h
index 03cac6d..8a3bc33 100644
--- a/content/renderer/media/audio/mojo_audio_input_ipc.h
+++ b/content/renderer/media/audio/mojo_audio_input_ipc.h
@@ -19,6 +19,7 @@
 #include "media/mojo/interfaces/audio_input_stream.mojom.h"
 #include "media/webrtc/audio_processor_controls.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/audio/public/mojom/audio_processing.mojom.h"
 
 namespace content {
 
diff --git a/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc b/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
index 9ec98a1..a677d12a 100644
--- a/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
+++ b/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/audio_parameters.h"
+#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/platform_handle.h"
diff --git a/content/renderer/media/audio/mojo_audio_output_ipc.cc b/content/renderer/media/audio/mojo_audio_output_ipc.cc
index 2314b3f..267f7ea 100644
--- a/content/renderer/media/audio/mojo_audio_output_ipc.cc
+++ b/content/renderer/media/audio/mojo_audio_output_ipc.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "media/audio/audio_device_description.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/content/renderer/media/audio/mojo_audio_output_ipc.h b/content/renderer/media/audio/mojo_audio_output_ipc.h
index 3770e2a..05a7ce9 100644
--- a/content/renderer/media/audio/mojo_audio_output_ipc.h
+++ b/content/renderer/media/audio/mojo_audio_output_ipc.h
@@ -17,6 +17,7 @@
 #include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
 #include "media/audio/audio_output_ipc.h"
 #include "media/mojo/interfaces/audio_data_pipe.mojom.h"
+#include "media/mojo/interfaces/audio_output_stream.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 namespace content {
diff --git a/content/renderer/media/stream/audio_service_audio_processor_proxy.h b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
index b83007e..4fed003 100644
--- a/content/renderer/media/stream/audio_service_audio_processor_proxy.h
+++ b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
@@ -15,7 +15,7 @@
 #include "base/timer/timer.h"
 #include "content/common/content_export.h"
 #include "content/renderer/media/stream/aec_dump_message_filter.h"
-#include "media/audio/audio_processing.h"
+#include "media/base/audio_processing.h"
 #include "media/webrtc/audio_processor_controls.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
 #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
diff --git a/content/renderer/media/stream/media_stream_audio_processor_options.h b/content/renderer/media/stream/media_stream_audio_processor_options.h
index ff011f3..c84ce46 100644
--- a/content/renderer/media/stream/media_stream_audio_processor_options.h
+++ b/content/renderer/media/stream/media_stream_audio_processor_options.h
@@ -14,8 +14,8 @@
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "media/audio/audio_processing.h"
 #include "media/base/audio_point.h"
+#include "media/base/audio_processing.h"
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "third_party/blink/public/platform/web_media_constraints.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
diff --git a/content/renderer/media/stream/user_media_processor.cc b/content/renderer/media/stream/user_media_processor.cc
index 9279fd9..e0e837a 100644
--- a/content/renderer/media/stream/user_media_processor.cc
+++ b/content/renderer/media/stream/user_media_processor.cc
@@ -1254,6 +1254,11 @@
       web_request.RequestFailed(
           blink::WebUserMediaRequest::Error::kKillSwitchOn);
       return;
+    case blink::MEDIA_DEVICE_SYSTEM_PERMISSION_DENIED:
+      web_request.RequestFailed(
+          blink::WebUserMediaRequest::Error::kSystemPermissionDenied,
+          "Permission denied by system");
+      return;
   }
   NOTREACHED();
   web_request.RequestFailed(
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
index 44db2197..f85d5ed 100644
--- a/content/renderer/media/video_capture_impl.cc
+++ b/content/renderer/media/video_capture_impl.cc
@@ -24,6 +24,7 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/limits.h"
 #include "media/base/video_frame.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/service_manager/public/cpp/connector.h"
 
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc
index a3cd2ef..1468b24f 100644
--- a/content/renderer/media/video_capture_impl_unittest.cc
+++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/child/child_process.h"
 #include "content/renderer/media/video_capture_impl.h"
 #include "media/capture/mojom/video_capture.mojom.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 0556233..6e674dd 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -40,6 +40,7 @@
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom.h"
 #include "third_party/blink/public/platform/web_effective_connection_type.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/platform/web_string.h"
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index b7b3bbe..6cac5c3 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -644,8 +644,6 @@
   if (!is_starting_installed_worker_)
     (*instance_host_)->OnScriptLoaded();
   TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "LOAD_SCRIPT", this);
-  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_CONTEXT",
-                                    this);
 }
 
 void ServiceWorkerContextClient::WorkerContextStarted(
@@ -677,14 +675,10 @@
     context_->controller_impl = std::make_unique<ControllerServiceWorkerImpl>(
         std::move(pending_controller_request_), GetWeakPtr());
   }
-
-  TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT",
-                                  this);
 }
 
 void ServiceWorkerContextClient::WillEvaluateScript() {
   DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
-  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this);
   start_timing_->script_evaluation_start_time = base::TimeTicks::Now();
 
   // Temporary CHECK for https://crbug.com/881100
@@ -725,10 +719,6 @@
   worker_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&ServiceWorkerContextClient::SendWorkerStarted,
                                 GetWeakPtr(), status));
-
-  TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "EVALUATE_SCRIPT", this,
-                                  "Status",
-                                  ServiceWorkerUtils::MojoEnumToString(status));
 }
 
 void ServiceWorkerContextClient::DidInitializeWorkerContext(
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 53b9bee..5481f706 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 8d607611..97eb16f 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -17,6 +17,7 @@
 #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/worker/shared_worker.mojom.h"
 #include "third_party/blink/public/mojom/worker/shared_worker_host.mojom.h"
diff --git a/content/renderer/shared_worker/shared_worker_factory_impl.cc b/content/renderer/shared_worker/shared_worker_factory_impl.cc
index aa7e208..308d364 100644
--- a/content/renderer/shared_worker/shared_worker_factory_impl.cc
+++ b/content/renderer/shared_worker/shared_worker_factory_impl.cc
@@ -8,6 +8,7 @@
 #include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom.h"
 
 namespace content {
 
diff --git a/content/test/content_test_suite.cc b/content/test/content_test_suite.cc
index a359a7c2..a580e67 100644
--- a/content/test/content_test_suite.cc
+++ b/content/test/content_test_suite.cc
@@ -28,10 +28,6 @@
 #include "base/test/mock_chrome_application_mac.h"
 #endif
 
-#if defined(OS_ANDROID)
-#include "content/browser/media/android/browser_media_player_manager.h"
-#endif
-
 namespace content {
 namespace {
 
diff --git a/content/test/data/accessibility/html/audio-expected-auralinux.txt b/content/test/data/accessibility/html/audio-expected-auralinux.txt
index a11729b..f57da32 100644
--- a/content/test/data/accessibility/html/audio-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/audio-expected-auralinux.txt
@@ -2,8 +2,8 @@
 ++[section]
 ++++[audio]
 ++++++[section]
-++++++++[tool bar] name='audio' description='audio' horizontal
-++++++++++[tool bar] name='audio' description='audio' horizontal
+++++++++[section]
+++++++++++[section]
 ++++++++++++[push button] name='play' xml-roles:button
 ++++++++++++[section] name='elapsed time: 0:00'
 ++++++++++++++[text] name='0:00'
diff --git a/content/test/data/gpu/pixel_video_context_loss.html b/content/test/data/gpu/pixel_video_context_loss.html
new file mode 100644
index 0000000..c146e50
--- /dev/null
+++ b/content/test/data/gpu/pixel_video_context_loss.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+
+<!-- READ BEFORE UPDATING:
+If this test is updated make sure to increment the "revision" value of the
+associated test in content/test/gpu/page_sets/pixel_tests.py. This will ensure
+that the baseline images are regenerated on the next run.
+-->
+
+<html>
+<head>
+<title>Video Context Loss Test</title>
+<style type="text/css">
+.nomargin {
+  margin: 0px auto;
+}
+</style>
+<script>
+var video;
+
+var QueryString = function() {
+  // Allows access to query parameters on the URL; e.g., given a URL like:
+  //    http://<server>/my.html?test=123&bob=123
+  // Parameters can then be accessed via QueryString.test or QueryString.bob.
+  var params = {};
+  // RegEx to split out values by &.
+  var r = /([^&=]+)=?([^&]*)/g;
+  // Lambda function for decoding extracted match values. Replaces '+' with
+  // space so decodeURIComponent functions properly.
+  function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
+  var match;
+  while (match = r.exec(window.location.search.substring(1)))
+    params[d(match[1])] = d(match[2]);
+  return params;
+}();
+
+function CrashGpuProcess() {
+  // Create a canvas element and webgl context.
+  var canvas = document.createElement('canvas');
+  var gl = canvas.getContext('webgl');
+
+  // Now wait for the context loss before starting video playback.
+  canvas.addEventListener('webglcontextlost', function(e) {
+    // Now wait for the video to playback to play until the end end, by which
+    // point a frame should be visible onscreen.
+    video.addEventListener('ended', function(e) {
+      domAutomationController.send("SUCCESS");
+    }, false);
+    video.play();
+  }, false);
+
+  // Essentially invokes chrome://gpucrash.
+  chrome.gpuBenchmarking.crashGpuProcess();
+}
+
+function Main() {
+  video = document.getElementById("video");
+
+  // Wait until we're sure a frame has been displayed before crashing GPU.
+  video.addEventListener('canplaythrough', CrashGpuProcess, false);
+
+  // src needs to be set after listener is added.
+  video.src = QueryString.src;
+}
+</script>
+</head>
+<body onload="Main()">
+<div id="container" style="position:absolute; top:0px; left:0px">
+<video class="nomargin" id="video" width="240" height="135">
+<source type="video/mp4">
+</video>
+</div>
+</body>
+</html>
diff --git a/content/test/data/gpu/pixel_video_test.js b/content/test/data/gpu/pixel_video_test.js
index 85134b2..0026a858 100644
--- a/content/test/data/gpu/pixel_video_test.js
+++ b/content/test/data/gpu/pixel_video_test.js
@@ -7,13 +7,17 @@
 function main() {
   video = document.getElementById("video");
   video.loop = true;
-  video.addEventListener('timeupdate', SendSuccess);
+  video.addEventListener('timeupdate', waitForSwapToComplete);
   video.play();
 }
 
-function SendSuccess() {
+function waitForSwapToComplete() {
   if (video.currentTime > 0) {
-    video.removeEventListener('timeupdate', SendSuccess);
-    domAutomationController.send("SUCCESS");
+    video.removeEventListener('timeupdate', waitForSwapToComplete);
+    chrome.gpuBenchmarking.addSwapCompletionEventListener(sendSuccess);
   }
 }
+
+function sendSuccess() {
+  domAutomationController.send("SUCCESS");
+}
diff --git a/content/test/gpu/OWNERS b/content/test/gpu/OWNERS
index a2f60e1..b29b16b9 100644
--- a/content/test/gpu/OWNERS
+++ b/content/test/gpu/OWNERS
@@ -3,8 +3,7 @@
 zmo@chromium.org
 
 # For Telemetry refactorings.
-nednguyen@chromium.org
-nednguyen@google.com
+crouleau@chromium.org
 
 # Emeritus:
 # dtu@chromium.org
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py
index 3527644..e05b5b77 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -11,6 +11,8 @@
 from gpu_tests import exception_formatter
 from gpu_tests import gpu_test_expectations
 
+_START_BROWSER_RETRIES = 3
+
 
 class GpuIntegrationTest(
     serially_executed_browser_test_case.SeriallyExecutedBrowserTestCase):
@@ -63,10 +65,12 @@
     cls._finder_options = cls._original_finder_options.Copy()
     browser_options = cls._finder_options.browser_options
 
-    # Enable browser log on Windows to debug the crash (crbug.com/917211).
+    # Enable browser log and Telemetry debug log on Windows to debug the crash
+    # (crbug.com/917211).
     # TODO: remove this once the bug is addressed.
     if os.name == 'nt':
       browser_options.logging_verbosity = browser_options.VERBOSE_LOGGING
+      logging.getLogger().setLevel(logging.DEBUG)
 
     # A non-sandboxed, 15-seconds-delayed gpu process is currently running in
     # the browser to collect gpu info. A command line switch is added here to
@@ -115,28 +119,31 @@
     # to push the fetch of the first tab into the lower retry loop
     # without breaking Telemetry's unit tests, and that hook is used
     # to implement the gpu_integration_test_unittests.
-    for x in range(0, 3):
+    for x in range(1, _START_BROWSER_RETRIES+1):  # Index from 1 instead of 0.
       try:
         super(GpuIntegrationTest, cls).StartBrowser()
         cls.tab = cls.browser.tabs[0]
         return
       except Exception:
-        logging.warning('Browser start failed (attempt %d of 3)', (x + 1))
+        logging.warning('Browser start failed (attempt %d of %d)',
+                        x, _START_BROWSER_RETRIES)
         # If we are on the last try and there is an exception take a screenshot
         # to try and capture more about the browser failure and raise
-        if x == 2:
+        if x == _START_BROWSER_RETRIES:
           url = screenshot.TryCaptureScreenShotAndUploadToCloudStorage(
             cls.platform)
           if url is not None:
             logging.info("GpuIntegrationTest screenshot of browser failure " +
               "located at " + url)
           else:
-            logging.warning("GpuIntegrationTest unable to take screenshot")
-          raise
-        # Otherwise, stop the browser to make sure it's in an
+            logging.warning("GpuIntegrationTest unable to take screenshot.")
+        # Stop the browser to make sure it's in an
         # acceptable state to try restarting it.
         if cls.browser:
           cls.StopBrowser()
+    # Re-raise the last exception thrown. Only happens if all the retries
+    # fail.
+    raise
 
   @classmethod
   def _RestartBrowser(cls, reason):
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
index 939d0e3..1db1ed6 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
@@ -7,10 +7,12 @@
 import shutil
 import tempfile
 import unittest
+import mock
 
 from telemetry.testing import browser_test_runner
 
 from gpu_tests import path_util
+from gpu_tests import gpu_integration_test
 
 path_util.AddDirToPathIfNeeded(path_util.GetChromiumSrcDir(), 'tools', 'perf')
 from chrome_telemetry_build import chromium_config
@@ -77,6 +79,30 @@
       ['--also-run-disabled-tests'])
     self.assertEquals(self._test_state['num_test_runs'], 1)
 
+  def testStartBrowser_Retries(self):
+    class TestException(Exception):
+      pass
+    def SetBrowserAndRaiseTestException():
+      gpu_integration_test.GpuIntegrationTest.browser = (
+          mock.MagicMock())
+      raise TestException
+    gpu_integration_test.GpuIntegrationTest.browser = None
+    gpu_integration_test.GpuIntegrationTest.platform = None
+    with mock.patch.object(
+        gpu_integration_test.serially_executed_browser_test_case.\
+            SeriallyExecutedBrowserTestCase,
+            'StartBrowser',
+            side_effect=SetBrowserAndRaiseTestException) as mock_start_browser:
+      with mock.patch.object(
+          gpu_integration_test.GpuIntegrationTest,
+          'StopBrowser') as mock_stop_browser:
+        with self.assertRaises(TestException):
+          gpu_integration_test.GpuIntegrationTest.StartBrowser()
+        self.assertEqual(mock_start_browser.call_count,
+                         gpu_integration_test._START_BROWSER_RETRIES)
+        self.assertEqual(mock_stop_browser.call_count,
+                         gpu_integration_test._START_BROWSER_RETRIES)
+
   def _RunIntegrationTest(self, test_name, failures, successes, skips,
                           additional_args):
     config = chromium_config.ChromiumConfig(
@@ -97,14 +123,14 @@
       with open(test_state_path) as f:
         self._test_state = json.load(f)
       actual_successes, actual_failures, actual_skips = (
-          self._ExtracTestResults(test_result))
+          self._ExtractTestResults(test_result))
       self.assertEquals(set(actual_failures), set(failures))
       self.assertEquals(set(actual_successes), set(successes))
       self.assertEquals(set(actual_skips), set(skips))
     finally:
       shutil.rmtree(temp_dir)
 
-  def _ExtracTestResults(self, test_result):
+  def _ExtractTestResults(self, test_result):
     delimiter = test_result['path_delimiter']
     failures = []
     successes = []
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index 6ee446c..49a1a0c9 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -127,9 +127,15 @@
     self.Fail('Pixel_2DCanvasWebGL', bug=836884)
     self.Fail('Pixel_CSS3DBlueBox', bug=836884)
 
+    # We do not have software H.264 decoding on Android, so it can't survive a
+    # context loss which results in hardware decoder loss.
+    self.Skip('Pixel_Video_Context_Loss_MP4', ['android'], bug=580386)
+
     # Fails on Mac Pro FYI Release (AMD)
     self.Fail('Pixel_Video_MP4',
         ['mac', ('amd', 0x679e)], bug=925744)
+    self.Fail('Pixel_Video_Context_Loss_MP4',
+        ['mac', ('amd', 0x679e)], bug=925744)
     self.Fail('Pixel_Video_MP4_FourColors_Aspect_4x3',
         ['mac', ('amd', 0x679e)], bug=911413)
     self.Fail('Pixel_Video_MP4_FourColors_Rot_90',
@@ -139,10 +145,11 @@
     self.Fail('Pixel_Video_MP4_FourColors_Rot_270',
         ['mac', ('amd', 0x679e)], bug=911413)
 
-    # Fail on Nexus 5, 5X, 6, 6P, 9 and Shield TV
+    # Fail on Nexus 5, 5X, 6, 6P, 9 and Shield TV.
     self.Fail('Pixel_Video_MP4', ['android'], bug=925744)
     self.Fail('Pixel_Video_MP4_FourColors_Aspect_4x3', ['android'], bug=925744)
     self.Fail('Pixel_Video_MP4_FourColors_Rot_180', ['android'], bug=925744)
     self.Fail('Pixel_Video_MP4_FourColors_Rot_270', ['android'], bug=925744)
     self.Fail('Pixel_Video_MP4_FourColors_Rot_90', ['android'], bug=925744)
     self.Fail('Pixel_Video_VP9', ['android'], bug=925744)
+    self.Fail('Pixel_Video_Context_Loss_VP9', ['android'], bug=925744)
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index 6dc216bb..3815e38 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -464,6 +464,80 @@
         }
       ]),
 
+    # The MP4 contains H.264 which is primarily hardware decoded on bots.
+    PixelTestPage(
+      'pixel_video_context_loss.html?src=/media/test/data/four-colors.mp4',
+      base_name + '_Video_Context_Loss_MP4',
+      test_rect=[0, 0, 240, 135],
+      revision=0, # Golden image revision is not used
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [5, 5],
+          'size': [110, 57],
+          'color': [255, 255, 15],
+          'tolerance': tolerance
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [125, 5],
+          'size': [110, 57],
+          'color': [255, 17, 24],
+          'tolerance': tolerance
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [5, 72],
+          'size': [110, 57],
+          'color': [12, 12, 255],
+          'tolerance': tolerance
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [125, 72],
+          'size': [110, 57],
+          'color': [44, 255, 16],
+          'tolerance': tolerance
+        }
+      ]),
+
+    # The VP9 test clip is primarily software decoded on bots.
+    PixelTestPage(
+      'pixel_video_context_loss.html?src=/media/test/data/four-colors-vp9.webm',
+      base_name + '_Video_Context_Loss_VP9',
+      test_rect=[0, 0, 240, 135],
+      revision=0, # Golden image revision is not used
+      expected_colors=[
+        {
+          'comment': 'top left video, yellow',
+          'location': [5, 5],
+          'size': [110, 57],
+          'color': [255, 255, 15],
+          'tolerance': tolerance_vp9
+        },
+        {
+          'comment': 'top right video, red',
+          'location': [125, 5],
+          'size': [110, 57],
+          'color': [255, 17, 24],
+          'tolerance': tolerance_vp9
+        },
+        {
+          'comment': 'bottom left video, blue',
+          'location': [5, 72],
+          'size': [110, 57],
+          'color': [12, 12, 255],
+          'tolerance': tolerance_vp9
+        },
+        {
+          'comment': 'bottom right video, green',
+          'location': [125, 72],
+          'size': [110, 57],
+          'color': [44, 255, 16],
+          'tolerance': tolerance_vp9
+        }
+      ]),
+
     PixelTestPage(
       'pixel_webgl_premultiplied_alpha_false.html',
       base_name + '_WebGL_PremultipliedAlpha_False',
diff --git a/content/test/gpu/gpu_tests/trace_test_expectations.py b/content/test/gpu/gpu_tests/trace_test_expectations.py
index 9ad20af..1c02a70f 100644
--- a/content/test/gpu/gpu_tests/trace_test_expectations.py
+++ b/content/test/gpu/gpu_tests/trace_test_expectations.py
@@ -16,3 +16,8 @@
 
     # Device traces are not supported on all machines.
     self.Skip('DeviceTraceTest_*')
+
+    # We do not have software H.264 decoding on Android, so it can't survive a
+    # context loss which results in hardware decoder loss.
+    self.Skip('*_Video_Context_Loss_MP4', ['android'], bug=580386)
+
diff --git a/content/test/not_implemented_network_url_loader_factory.cc b/content/test/not_implemented_network_url_loader_factory.cc
index 55f3b42..ea33208 100644
--- a/content/test/not_implemented_network_url_loader_factory.cc
+++ b/content/test/not_implemented_network_url_loader_factory.cc
@@ -4,6 +4,8 @@
 
 #include "content/test/not_implemented_network_url_loader_factory.h"
 
+#include "services/network/public/mojom/url_loader.mojom.h"
+
 namespace content {
 
 NotImplementedNetworkURLLoaderFactory::NotImplementedNetworkURLLoaderFactory() =
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index b0941f5..c48a590 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "content/common/frame.mojom.h"
+#include "content/common/input/input_handler.mojom.h"
 #include "content/renderer/render_frame_impl.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
diff --git a/extensions/browser/api/idle/BUILD.gn b/extensions/browser/api/idle/BUILD.gn
index edc5714..a635a4f0 100644
--- a/extensions/browser/api/idle/BUILD.gn
+++ b/extensions/browser/api/idle/BUILD.gn
@@ -21,6 +21,7 @@
 
   deps = [
     "//extensions/common/api",
+    "//ui/base/idle",
   ]
 
   public_deps = [
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index ba64c3c..e70e7cd 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -20,6 +20,7 @@
 #include "device/usb/mojo/type_converters.h"
 #include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/public/mojom/device.mojom.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_descriptors.h"
 #include "device/usb/usb_device_handle.h"
diff --git a/extensions/browser/api/usb/usb_device_manager.cc b/extensions/browser/api/usb/usb_device_manager.cc
index 35e7217..aef80a9 100644
--- a/extensions/browser/api/usb/usb_device_manager.cc
+++ b/extensions/browser/api/usb/usb_device_manager.cc
@@ -11,6 +11,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "extensions/browser/api/device_permissions_manager.h"
 #include "extensions/browser/event_router_factory.h"
 #include "extensions/common/api/usb.h"
diff --git a/extensions/browser/api/usb/usb_device_manager.h b/extensions/browser/api/usb/usb_device_manager.h
index a415dc2..809297b2 100644
--- a/extensions/browser/api/usb/usb_device_manager.h
+++ b/extensions/browser/api/usb/usb_device_manager.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "content/public/browser/browser_thread.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
+#include "device/usb/public/mojom/device_manager_client.mojom.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/common/api/usb.h"
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
index ded86db..e6d1e6a9 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
@@ -332,10 +332,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(MimeHandlerViewTest, Iframe) {
-  // TODO(https://crbug.com/923051): Flaky in single process mash.
-  if (features::IsSingleProcessMash())
-    return;
-
   RunTest("test_iframe.html");
 }
 
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
index 5bd9b94..d25a7110 100644
--- a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
+++ b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
@@ -9,6 +9,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "device/usb/public/cpp/usb_utils.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_device.h"
 #include "extensions/common/api/extensions_manifest_types.h"
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc
index 35b339df..45cf5aa 100644
--- a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc
+++ b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "device/usb/public/mojom/device_enumeration_options.mojom.h"
 #include "extensions/common/api/printer_provider/usb_printer_manifest_data.h"
 #include "extensions/common/manifest_test.h"
 #include "extensions/common/value_builder.h"
diff --git a/extensions/common/image_util_unittest.cc b/extensions/common/image_util_unittest.cc
index 326834b..f7ee658 100644
--- a/extensions/common/image_util_unittest.cc
+++ b/extensions/common/image_util_unittest.cc
@@ -4,8 +4,11 @@
 
 #include <string>
 
+#include "base/files/file.h"
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/strings/string_split.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "extensions/common/extension_paths.h"
 #include "extensions/common/image_util.h"
@@ -13,7 +16,9 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/color_utils.h"
+#include "url/gurl.h"
 
 namespace extensions {
 
@@ -315,4 +320,60 @@
   LoggingTimer::Print();
 }
 
+namespace {
+
+void WriteRenderedIcon(const SkBitmap& icon,
+                       SkColor background_color,
+                       const base::FilePath& rendered_icon_path) {
+  SkBitmap bitmap;
+  image_util::RenderIconForVisibilityAnalysis(icon, background_color, &bitmap);
+  std::vector<unsigned char> output_data;
+  ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output_data));
+  const int bytes_to_write = output_data.size();
+  ASSERT_EQ(bytes_to_write,
+            base::WriteFile(rendered_icon_path,
+                            reinterpret_cast<const char*>(&output_data[0]),
+                            bytes_to_write));
+}
+
+}  // namespace
+
+TEST(ImageUtilTest, DISABLED_AnalyzeAllDownloadedIcons) {
+  // See the README in extensions/test/data/icon_visibility for more details
+  // on running this test.
+  // TODO(crbug.com/805600): Remove this test when the bug is closed.
+  base::FilePath test_dir;
+  ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
+  test_dir = test_dir.AppendASCII("icon_visibility");
+  base::FilePath icons_file_path = test_dir.AppendASCII("source_urls.txt");
+  std::string file_data;
+  ASSERT_TRUE(base::ReadFileToString(icons_file_path, &file_data));
+  base::FilePath output_file_path =
+      test_dir.AppendASCII("invisible_source_urls.txt");
+  base::File output_file(output_file_path, base::File::FLAG_CREATE_ALWAYS |
+                                               base::File::FLAG_WRITE);
+  ASSERT_TRUE(output_file.IsValid());
+  base::FilePath rendered_icon_path = test_dir.AppendASCII("rendered_pngs");
+  ASSERT_TRUE(base::CreateDirectory(rendered_icon_path));
+
+  base::FilePath downloaded_icons_path = test_dir.AppendASCII("pngs");
+  ASSERT_TRUE(base::DirectoryExists(downloaded_icons_path));
+
+  const std::vector<base::StringPiece> urls = base::SplitStringPiece(
+      file_data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+  for (const base::StringPiece url : urls) {
+    const std::string file_name = GURL(url).ExtractFileName();
+    base::FilePath icon_path = downloaded_icons_path.AppendASCII(file_name);
+    SkBitmap current_icon;
+    ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &current_icon));
+    if (!image_util::IsRenderedIconSufficientlyVisible(current_icon,
+                                                       SK_ColorWHITE)) {
+      output_file.WriteAtCurrentPos(url.data(), url.length());
+      output_file.WriteAtCurrentPos("\n", 1);
+      WriteRenderedIcon(current_icon, SK_ColorWHITE,
+                        rendered_icon_path.AppendASCII(file_name + ".png"));
+    }
+  }
+}
+
 }  // namespace extensions
diff --git a/extensions/test/data/icon_visibility/README b/extensions/test/data/icon_visibility/README
new file mode 100644
index 0000000..b7268fab
--- /dev/null
+++ b/extensions/test/data/icon_visibility/README
@@ -0,0 +1,40 @@
+This file explains the purpose of this directory and how to set everything up
+to run the related unit test to verify the icon visibility algorithm is
+working reasonably well.
+
+The unit test is in src/extesions/common/image_util_unittest.cc and is
+disabled, so it doesn't run under normal testing:
+
+TEST(ImageUtilTest, DISABLED_AnalyzeAllDownloadedIcons)
+
+There will be two sets of input data: a file that contains the URLs for the
+top 5000 extension icons in web store and the icon image files. These URLs
+are generated by a query against the underlying web store database. The query
+is available in PLX here:
+
+https://plx.corp.google.com/scripts2/script_5c._4ae232_0000_2abb_8c52_001a11c10446
+
+Once the query has executed, download the results to a file called
+"source_urls.txt." Edit this file to remove the first line, which is the column
+name for the CSV format.
+
+Create a directory called "pngs" then change to that directory and use wget
+to download all of the icons:
+
+mkdir pngs
+cd pngs
+wget -i ../source_urls.txt
+
+This will take a while, but once it's completed, you should see all 5000 files
+in the directory.
+
+You can now run the unit test, which will create two output artifacts: A file
+called "invisible_source_urls.txt" which contains the URLs of the icons that
+were considered not sufficiently visible, along with an output directory
+called "invisible_pngs" that contains the rendered icons.
+
+You can then look at the rendered icons to understand what the algorithm does
+and correlate them back to the original icons. If any icons look like they
+should have passed but didn't, it's helpful to create a sample extension using
+the _original_ icon for the browser action, so you can see the icon in the
+toolbar.
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h
index 96f525f0..032d86a 100644
--- a/gpu/config/gpu_preferences.h
+++ b/gpu/config/gpu_preferences.h
@@ -101,9 +101,6 @@
 
   bool log_gpu_control_list_decisions = false;
 
-  // Enable exporting of events to ETW (on Windows).
-  bool enable_trace_export_events_to_etw = false;
-
   // ===================================
   // Settings from //gpu/command_buffer/service/gpu_switches.cc
 
diff --git a/gpu/config/gpu_preferences_unittest.cc b/gpu/config/gpu_preferences_unittest.cc
index 260ef9ce3..d31ea56 100644
--- a/gpu/config/gpu_preferences_unittest.cc
+++ b/gpu/config/gpu_preferences_unittest.cc
@@ -35,8 +35,6 @@
             right.disable_software_rasterizer);
   EXPECT_EQ(left.log_gpu_control_list_decisions,
             right.log_gpu_control_list_decisions);
-  EXPECT_EQ(left.enable_trace_export_events_to_etw,
-            right.enable_trace_export_events_to_etw);
   EXPECT_EQ(left.compile_shader_always_succeeds,
             right.compile_shader_always_succeeds);
   EXPECT_EQ(left.disable_gl_error_limit, right.disable_gl_error_limit);
@@ -127,7 +125,6 @@
     GPU_PREFERENCES_FIELD(enable_media_foundation_vea_on_windows7, true)
     GPU_PREFERENCES_FIELD(disable_software_rasterizer, true)
     GPU_PREFERENCES_FIELD(log_gpu_control_list_decisions, true)
-    GPU_PREFERENCES_FIELD(enable_trace_export_events_to_etw, true)
     GPU_PREFERENCES_FIELD(compile_shader_always_succeeds, true)
     GPU_PREFERENCES_FIELD(disable_gl_error_limit, true)
     GPU_PREFERENCES_FIELD(disable_glsl_translator, true)
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json
index abb9a89..d800fdf 100644
--- a/gpu/config/software_rendering_list.json
+++ b/gpu/config/software_rendering_list.json
@@ -1364,7 +1364,7 @@
     },
     {
       "id": 137,
-      "description": "GPU rasterization on CrOS is blacklisted on anything but Intel, Mali, Imagination, or AMD GPUs for now.",
+      "description": "GPU rasterization on CrOS is blacklisted on anything but Intel, Imagination, or AMD GPUs for now.",
       "cr_bugs": [684094],
       "os": {
         "type": "chromeos"
@@ -1374,7 +1374,6 @@
       ],
       "exceptions": [
         { "vendor_id": "0x8086" },
-        { "gl_renderer": "Mali-T.*" },
         { "gl_renderer": "PowerVR.*" },
         { "vendor_id": "0x1002" }
       ]
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom
index c80521f..37bdcc4 100644
--- a/gpu/ipc/common/gpu_preferences.mojom
+++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -34,7 +34,6 @@
   bool enable_media_foundation_vea_on_windows7;
   bool disable_software_rasterizer;
   bool log_gpu_control_list_decisions;
-  bool enable_trace_export_events_to_etw;
 
   bool compile_shader_always_succeeds;
   bool disable_gl_error_limit;
diff --git a/gpu/ipc/common/gpu_preferences_struct_traits.h b/gpu/ipc/common/gpu_preferences_struct_traits.h
index 3b3b52d0..7bea28c 100644
--- a/gpu/ipc/common/gpu_preferences_struct_traits.h
+++ b/gpu/ipc/common/gpu_preferences_struct_traits.h
@@ -76,8 +76,6 @@
     out->disable_software_rasterizer = prefs.disable_software_rasterizer();
     out->log_gpu_control_list_decisions =
         prefs.log_gpu_control_list_decisions();
-    out->enable_trace_export_events_to_etw =
-        prefs.enable_trace_export_events_to_etw();
     out->compile_shader_always_succeeds =
         prefs.compile_shader_always_succeeds();
     out->disable_gl_error_limit = prefs.disable_gl_error_limit();
@@ -181,10 +179,6 @@
   static bool log_gpu_control_list_decisions(const gpu::GpuPreferences& prefs) {
     return prefs.log_gpu_control_list_decisions;
   }
-  static bool enable_trace_export_events_to_etw(
-      const gpu::GpuPreferences& prefs) {
-    return prefs.enable_trace_export_events_to_etw;
-  }
   static bool compile_shader_always_succeeds(const gpu::GpuPreferences& prefs) {
     return prefs.compile_shader_always_succeeds;
   }
diff --git a/infra/config/global/tricium-prod.cfg b/infra/config/global/tricium-prod.cfg
index bef9ff6..6d63366 100644
--- a/infra/config/global/tricium-prod.cfg
+++ b/infra/config/global/tricium-prod.cfg
@@ -11,7 +11,7 @@
   platform: UBUNTU
   configs {
     name: "filter"
-    value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/include_what_you_use,+build/include_order"
+    value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/header_guard,+build/include_what_you_use,+build/include_order"
   }
   configs {
     name: "verbose"
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 0f826b98..d17989e0 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -2170,7 +2170,7 @@
   DCHECK(_downloadManagerCoordinator);
   _downloadManagerCoordinator.webStateList = self.tabModel.webStateList;
   _downloadManagerCoordinator.bottomMarginHeightAnchor =
-      [NamedGuide guideWithName:kSecondaryToolbarGuide view:self.view]
+      [NamedGuide guideWithName:kSecondaryToolbarGuide view:self.contentArea]
           .heightAnchor;
 
   self.popupMenuCoordinator = [[PopupMenuCoordinator alloc]
@@ -4724,11 +4724,6 @@
 
 - (void)sideSwipeViewDismissAnimationDidEnd:(UIView*)sideSwipeView {
   DCHECK(![self canShowTabStrip]);
-  // Update frame incase orientation changed while |contentArea| was out of
-  // the view hierarchy.
-  self.contentArea.frame = sideSwipeView.frame;
-
-  [self.view insertSubview:self.contentArea aboveSubview:_fakeStatusBarView];
   [self updateToolbar];
 
   // Reset horizontal stack view.
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
index fbd77976da..208b6278 100644
--- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
+++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -546,9 +546,6 @@
     DCHECK([swipeDelegate_ verifyToolbarViewPlacementInView:gesture.view]);
     // Insert above the toolbar.
     [gesture.view addSubview:tabSideSwipeView_];
-
-    // Remove content area so it doesn't receive any pan events.
-    [[swipeDelegate_ sideSwipeContentView] removeFromSuperview];
   }
 
   [tabSideSwipeView_ handleHorizontalPan:gesture];
diff --git a/ios/web/public/test/fakes/test_web_state.h b/ios/web/public/test/fakes/test_web_state.h
index 598d725..7d29f25 100644
--- a/ios/web/public/test/fakes/test_web_state.h
+++ b/ios/web/public/test/fakes/test_web_state.h
@@ -64,8 +64,6 @@
   const GURL& GetVisibleURL() const override;
   const GURL& GetLastCommittedURL() const override;
   GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const override;
-  void ShowTransientContentView(CRWContentView* content_view) override;
-  void ClearTransientContentView();
   void AddScriptCommandCallback(const ScriptCommandCallback& callback,
                                 const std::string& command_prefix) override {}
   void RemoveScriptCommandCallback(const std::string& command_prefix) override {
@@ -107,7 +105,6 @@
   void RemoveWebFrame(std::string frame_id);
 
   // Getters for test data.
-  CRWContentView* GetTransientContentView();
   // Uses |policy_deciders| to return whether the navigation corresponding to
   // |request| should be allowed. Defaults to true.
   bool ShouldAllowRequest(
@@ -135,7 +132,6 @@
   bool is_crashed_;
   bool is_evicted_;
   bool has_opener_;
-  CRWContentView* transient_content_view_;
   GURL url_;
   base::string16 title_;
   base::string16 last_executed_javascript_;
diff --git a/ios/web/public/test/fakes/test_web_state.mm b/ios/web/public/test/fakes/test_web_state.mm
index 8463a3f9..d097c3a7 100644
--- a/ios/web/public/test/fakes/test_web_state.mm
+++ b/ios/web/public/test/fakes/test_web_state.mm
@@ -279,20 +279,6 @@
   }
 }
 
-void TestWebState::ShowTransientContentView(CRWContentView* content_view) {
-  if (content_view) {
-    transient_content_view_ = content_view;
-  }
-}
-
-void TestWebState::ClearTransientContentView() {
-  transient_content_view_ = nil;
-}
-
-CRWContentView* TestWebState::GetTransientContentView() {
-  return transient_content_view_;
-}
-
 bool TestWebState::ShouldAllowRequest(
     NSURLRequest* request,
     const WebStatePolicyDecider::RequestInfo& request_info) {
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h
index e22c028c..9b6fe52 100644
--- a/ios/web/public/web_state/web_state.h
+++ b/ios/web/public/web_state/web_state.h
@@ -225,10 +225,6 @@
   // See http://crbug.com/457679
   virtual GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const = 0;
 
-  // Resizes |content_view| to the content area's size and adds it to the
-  // hierarchy.  A navigation will remove the view from the hierarchy.
-  virtual void ShowTransientContentView(CRWContentView* content_view) = 0;
-
   // Returns true if a WebInterstitial is currently displayed.
   virtual bool IsShowingWebInterstitial() const = 0;
 
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h
index eb0ad5e..98defc2f 100644
--- a/ios/web/web_state/web_state_impl.h
+++ b/ios/web/web_state/web_state_impl.h
@@ -214,7 +214,6 @@
   const GURL& GetVisibleURL() const override;
   const GURL& GetLastCommittedURL() const override;
   GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const override;
-  void ShowTransientContentView(CRWContentView* content_view) override;
   bool IsShowingWebInterstitial() const override;
   WebInterstitial* GetWebInterstitial() const override;
   void AddScriptCommandCallback(const ScriptCommandCallback& callback,
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 8c042bd..58e6503 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -331,13 +331,6 @@
   return item ? item->GetTitleForDisplay() : empty_string16_;
 }
 
-void WebStateImpl::ShowTransientContentView(CRWContentView* content_view) {
-  DCHECK(Configured());
-  DCHECK(content_view);
-  DCHECK(content_view.scrollView);
-  [web_controller_ showTransientContentView:content_view];
-}
-
 bool WebStateImpl::IsShowingWebInterstitial() const {
   // Technically we could have |interstitial_| set but its view isn't
   // being displayed, but there's no code path where that could occur.
@@ -386,9 +379,11 @@
 
 void WebStateImpl::ShowWebInterstitial(WebInterstitialImpl* interstitial) {
   DCHECK(Configured());
-  DCHECK(interstitial);
   interstitial_ = interstitial;
-  ShowTransientContentView(interstitial_->GetContentView());
+
+  DCHECK(interstitial_->GetContentView());
+  DCHECK(interstitial_->GetContentView().scrollView);
+  [web_controller_ showTransientContentView:interstitial_->GetContentView()];
 }
 
 void WebStateImpl::SendChangeLoadProgress(double progress) {
diff --git a/jingle/glue/network_service_async_socket.h b/jingle/glue/network_service_async_socket.h
index 2246dcc..5b6ae01 100644
--- a/jingle/glue/network_service_async_socket.h
+++ b/jingle/glue/network_service_async_socket.h
@@ -24,6 +24,8 @@
 #include "net/base/host_port_pair.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/mojom/proxy_resolving_socket.mojom.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 #include "third_party/libjingle_xmpp/xmpp/asyncsocket.h"
 
 namespace jingle_glue {
diff --git a/jingle/notifier/base/xmpp_connection.cc b/jingle/notifier/base/xmpp_connection.cc
index 853a1d7e..4a1e41f 100644
--- a/jingle/notifier/base/xmpp_connection.cc
+++ b/jingle/notifier/base/xmpp_connection.cc
@@ -15,6 +15,7 @@
 #include "jingle/notifier/base/weak_xmpp_client.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/ssl/ssl_config_service.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 #include "third_party/libjingle_xmpp/xmpp/xmppclientsettings.h"
 
 namespace notifier {
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 98290402..fa3a7b0 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -105,8 +105,6 @@
     "audio_output_stream_sink.h",
     "audio_power_monitor.cc",
     "audio_power_monitor.h",
-    "audio_processing.cc",
-    "audio_processing.h",
     "audio_sink_parameters.cc",
     "audio_sink_parameters.h",
     "audio_source_diverter.h",
diff --git a/media/audio/audio_source_parameters.h b/media/audio/audio_source_parameters.h
index bb12d90..3de2dbb 100644
--- a/media/audio/audio_source_parameters.h
+++ b/media/audio/audio_source_parameters.h
@@ -9,7 +9,7 @@
 
 #include "base/optional.h"
 #include "base/unguessable_token.h"
-#include "media/audio/audio_processing.h"
+#include "media/base/audio_processing.h"
 #include "media/base/media_export.h"
 
 namespace media {
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index c102902e..3e6b561 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -55,6 +55,8 @@
     "audio_fifo.h",
     "audio_hash.cc",
     "audio_hash.h",
+    "audio_processing.cc",
+    "audio_processing.h",
     "audio_pull_fifo.cc",
     "audio_pull_fifo.h",
     "audio_push_fifo.cc",
diff --git a/media/audio/audio_processing.cc b/media/base/audio_processing.cc
similarity index 97%
rename from media/audio/audio_processing.cc
rename to media/base/audio_processing.cc
index b9af669..247e089 100644
--- a/media/audio/audio_processing.cc
+++ b/media/base/audio_processing.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "media/audio/audio_processing.h"
+#include "media/base/audio_processing.h"
 
 #include "base/strings/strcat.h"
 
diff --git a/media/audio/audio_processing.h b/media/base/audio_processing.h
similarity index 93%
rename from media/audio/audio_processing.h
rename to media/base/audio_processing.h
index 519cbce..9a169c90 100644
--- a/media/audio/audio_processing.h
+++ b/media/base/audio_processing.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef MEDIA_AUDIO_AUDIO_PROCESSING_H_
-#define MEDIA_AUDIO_AUDIO_PROCESSING_H_
+#ifndef MEDIA_BASE_AUDIO_PROCESSING_H_
+#define MEDIA_BASE_AUDIO_PROCESSING_H_
 
 #include <string>
 
@@ -56,4 +56,4 @@
 
 }  // namespace media
 
-#endif  // MEDIA_AUDIO_AUDIO_PROCESSING_H_
+#endif  // MEDIA_BASE_AUDIO_PROCESSING_H_
diff --git a/media/blink/video_decode_stats_reporter.cc b/media/blink/video_decode_stats_reporter.cc
index 2adc60e9..6e6a85f2 100644
--- a/media/blink/video_decode_stats_reporter.cc
+++ b/media/blink/video_decode_stats_reporter.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "media/capabilities/bucket_utility.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 
 namespace media {
 
diff --git a/media/blink/video_decode_stats_reporter_unittest.cc b/media/blink/video_decode_stats_reporter_unittest.cc
index ab42686..e67aa94 100644
--- a/media/blink/video_decode_stats_reporter_unittest.cc
+++ b/media/blink/video_decode_stats_reporter_unittest.cc
@@ -16,6 +16,7 @@
 #include "media/base/video_types.h"
 #include "media/blink/video_decode_stats_reporter.h"
 #include "media/capabilities/bucket_utility.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "media/mojo/interfaces/video_decode_stats_recorder.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/media/blink/webmediacapabilitiesclient_impl_unittest.cc b/media/blink/webmediacapabilitiesclient_impl_unittest.cc
index 3f07b8e..fd76ca9 100644
--- a/media/blink/webmediacapabilitiesclient_impl_unittest.cc
+++ b/media/blink/webmediacapabilitiesclient_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "media/blink/webmediacapabilitiesclient_impl.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "media/mojo/interfaces/video_decode_perf_history.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc
index b33fc24..5ff5e5e 100644
--- a/media/capture/video/win/video_capture_device_mf_win.cc
+++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -581,7 +581,8 @@
       retry_delay_in_ms_(50),
       source_(source),
       engine_(engine),
-      is_started_(false) {
+      is_started_(false),
+      has_sent_on_started_to_client_(false) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
@@ -761,6 +762,15 @@
     return;
   }
 
+  // Note, that it is not sufficient to wait for
+  // MF_CAPTURE_ENGINE_PREVIEW_STARTED as an indicator that starting capture has
+  // succeeded. If the capture device is already in use by a different
+  // application, MediaFoundation will still emit
+  // MF_CAPTURE_ENGINE_PREVIEW_STARTED, and only after that raise an error
+  // event. For the lack of any other events indicating success, we have to wait
+  // for the first video frame to arrive before sending our |OnStarted| event to
+  // |client_|.
+  has_sent_on_started_to_client_ = false;
   hr = engine_->StartPreview();
   if (FAILED(hr)) {
     OnError(VideoCaptureError::kWinMediaFoundationEngineStartPreviewFailed,
@@ -771,7 +781,6 @@
   selected_video_capability_.reset(
       new CapabilityWin(best_match_video_capability));
 
-  client_->OnStarted();
   is_started_ = true;
 }
 
@@ -986,7 +995,14 @@
   base::AutoLock lock(lock_);
   DCHECK(data);
 
+  SendOnStartedIfNotYetSent();
+
   if (client_.get()) {
+    if (!has_sent_on_started_to_client_) {
+      has_sent_on_started_to_client_ = true;
+      client_->OnStarted();
+    }
+
     client_->OnIncomingCapturedData(
         data, length, selected_video_capability_->supported_format,
         GetCameraRotation(facing_mode_), reference_time, timestamp);
@@ -1018,6 +1034,9 @@
 void VideoCaptureDeviceMFWin::OnFrameDropped(
     VideoCaptureFrameDropReason reason) {
   base::AutoLock lock(lock_);
+
+  SendOnStartedIfNotYetSent();
+
   if (client_.get()) {
     client_->OnFrameDropped(reason);
   }
@@ -1050,4 +1069,11 @@
                    base::StringPrintf("VideoCaptureDeviceMFWin: %s", message));
 }
 
+void VideoCaptureDeviceMFWin::SendOnStartedIfNotYetSent() {
+  if (!client_ || has_sent_on_started_to_client_)
+    return;
+  has_sent_on_started_to_client_ = true;
+  client_->OnStarted();
+}
+
 }  // namespace media
diff --git a/media/capture/video/win/video_capture_device_mf_win.h b/media/capture/video/win/video_capture_device_mf_win.h
index fb0452b..36111a1 100644
--- a/media/capture/video/win/video_capture_device_mf_win.h
+++ b/media/capture/video/win/video_capture_device_mf_win.h
@@ -115,6 +115,7 @@
   void OnError(VideoCaptureError error,
                const base::Location& from_here,
                const char* message);
+  void SendOnStartedIfNotYetSent();
 
   VideoFacingMode facing_mode_;
   CreateMFPhotoCallbackCB create_mf_photo_callback_;
@@ -135,6 +136,7 @@
   CapabilityList photo_capabilities_;
   std::unique_ptr<CapabilityWin> selected_photo_capability_;
   bool is_started_;
+  bool has_sent_on_started_to_client_;
   base::queue<TakePhotoCallback> video_stream_take_photo_callbacks_;
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/media/capture/video/win/video_capture_device_mf_win_unittest.cc b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
index 7e2b4275..a4d32062 100644
--- a/media/capture/video/win/video_capture_device_mf_win_unittest.cc
+++ b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
@@ -780,11 +780,17 @@
 
   STDMETHOD(CopyAllItems)(IMFAttributes* pDest) override { return E_NOTIMPL; }
 
-  STDMETHOD(GetType)(MediaEventType* pmet) override { return E_NOTIMPL; }
+  STDMETHOD(GetType)(MediaEventType* pmet) override {
+    *pmet = DoGetType();
+    return S_OK;
+  }
+  MOCK_METHOD0(DoGetType, MediaEventType());
 
   STDMETHOD(GetExtendedType)(GUID* pguidExtendedType) override {
-    return E_NOTIMPL;
+    *pguidExtendedType = DoGetExtendedType();
+    return S_OK;
   }
+  MOCK_METHOD0(DoGetExtendedType, GUID());
 
   STDMETHOD(GetStatus)(HRESULT* status) override {
     *status = DoGetStatus();
@@ -1059,7 +1065,7 @@
   EXPECT_CALL(*(engine_.Get()), OnStopPreview());
 
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
-
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
   device_->StopAndDeAllocate();
 }
 
@@ -1077,6 +1083,7 @@
   EXPECT_CALL(*media_event_error, DoGetStatus()).WillRepeatedly(Return(E_FAIL));
 
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
   engine_->event_callback->OnEvent(media_event_error.get());
 }
 
@@ -1118,18 +1125,20 @@
         return S_OK;
       }));
 
+  auto mock_sink = base::MakeRefCounted<MockCapturePreviewSink>();
   EXPECT_CALL(*(engine_.Get()),
               DoGetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, _))
-      .WillRepeatedly(Invoke(
-          [](MF_CAPTURE_ENGINE_SINK_TYPE sink_type, IMFCaptureSink** sink) {
-            *sink = new MockCapturePreviewSink();
-            (*sink)->AddRef();
-            return S_OK;
-          }));
+      .WillRepeatedly(Invoke([&mock_sink](MF_CAPTURE_ENGINE_SINK_TYPE sink_type,
+                                          IMFCaptureSink** sink) {
+        *sink = mock_sink.get();
+        (*sink)->AddRef();
+        return S_OK;
+      }));
 
   EXPECT_CALL(*(engine_.Get()), OnStartPreview());
   EXPECT_CALL(*client_, OnStarted());
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  mock_sink->sample_callback->OnSample(nullptr);
 }
 
 // Allocates device with methods always failing with MF_E_INVALIDREQUEST and
@@ -1145,6 +1154,36 @@
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
 }
 
+TEST_F(VideoCaptureDeviceMFWinTest,
+       SendsOnErrorWithoutOnStartedIfDeviceIsBusy) {
+  if (ShouldSkipTest())
+    return;
+
+  PrepareMFDeviceWithOneVideoStream(MFVideoFormat_MJPG);
+
+  EXPECT_CALL(*(engine_.Get()), OnStartPreview());
+  EXPECT_CALL(*client_, OnStarted()).Times(0);
+  EXPECT_CALL(*client_, OnError(_, _, _));
+
+  scoped_refptr<MockMFMediaEvent> media_event_preview_started =
+      new MockMFMediaEvent();
+  ON_CALL(*media_event_preview_started, DoGetStatus())
+      .WillByDefault(Return(S_OK));
+  ON_CALL(*media_event_preview_started, DoGetType())
+      .WillByDefault(Return(MEExtendedType));
+  ON_CALL(*media_event_preview_started, DoGetExtendedType())
+      .WillByDefault(Return(MF_CAPTURE_ENGINE_PREVIEW_STARTED));
+
+  scoped_refptr<MockMFMediaEvent> media_event_error = new MockMFMediaEvent();
+  EXPECT_CALL(*media_event_error, DoGetStatus()).WillRepeatedly(Return(E_FAIL));
+
+  device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  // Even if the device is busy, MediaFoundation sends
+  // MF_CAPTURE_ENGINE_PREVIEW_STARTED before sending an error event.
+  engine_->event_callback->OnEvent(media_event_preview_started.get());
+  engine_->event_callback->OnEvent(media_event_error.get());
+}
+
 // Given an |IMFCaptureSource| offering a video stream without photo stream to
 // |VideoCaptureDevice|, when asking the photo state from |VideoCaptureDevice|
 // then expect the returned state to match the video resolution
@@ -1158,6 +1197,7 @@
   EXPECT_CALL(*client_, OnStarted());
 
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
 
   VideoCaptureDevice::GetPhotoStateCallback get_photo_state_callback =
       base::BindOnce(&MockImageCaptureClient::DoOnGetPhotoState,
@@ -1187,6 +1227,8 @@
   EXPECT_CALL(*client_, OnStarted());
 
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
+
   VideoCaptureDevice::GetPhotoStateCallback get_photo_state_callback =
       base::BindOnce(&MockImageCaptureClient::DoOnGetPhotoState,
                      image_capture_client_);
@@ -1217,6 +1259,7 @@
   EXPECT_CALL(*(engine_.Get()), OnTakePhoto());
 
   device_->AllocateAndStart(VideoCaptureParams(), std::move(client_));
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
   VideoCaptureDevice::TakePhotoCallback take_photo_callback = base::BindOnce(
       &MockImageCaptureClient::DoOnPhotoTaken, image_capture_client_);
   device_->TakePhoto(std::move(take_photo_callback));
@@ -1277,6 +1320,7 @@
   VideoCaptureParams video_capture_params;
   video_capture_params.requested_format = format;
   device_->AllocateAndStart(video_capture_params, std::move(client_));
+  capture_preview_sink_->sample_callback->OnSample(nullptr);
 }
 
 }  // namespace media
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn
index aa3932a..0d87a47 100644
--- a/media/filters/BUILD.gn
+++ b/media/filters/BUILD.gn
@@ -214,7 +214,10 @@
       "fuchsia/fuchsia_video_decoder.cc",
       "fuchsia/fuchsia_video_decoder.h",
     ]
-    deps += [ "//third_party/fuchsia-sdk/sdk:mediacodec" ]
+    deps += [
+      "//third_party/fuchsia-sdk/sdk:media",
+      "//third_party/fuchsia-sdk/sdk:mediacodec",
+    ]
   }
 }
 
diff --git a/media/filters/frame_processor.cc b/media/filters/frame_processor.cc
index cacb304..a6c2287 100644
--- a/media/filters/frame_processor.cc
+++ b/media/filters/frame_processor.cc
@@ -32,7 +32,8 @@
  public:
   MseTrackBuffer(ChunkDemuxerStream* stream,
                  MediaLog* media_log,
-                 const SourceBufferParseWarningCB& parse_warning_cb);
+                 const SourceBufferParseWarningCB& parse_warning_cb,
+                 ChunkDemuxerStream::RangeApi range_api);
   ~MseTrackBuffer();
 
   // Get/set |last_decode_timestamp_|.
@@ -95,8 +96,11 @@
   // monotonically increasing.
   void SetHighestPresentationTimestampIfIncreased(base::TimeDelta timestamp);
 
-  // Adds |frame| to the end of |processed_frames_|.
-  void EnqueueProcessedFrame(scoped_refptr<StreamParserBuffer> frame);
+  // Adds |frame| to the end of |processed_frames_|. In some BufferingByPts
+  // SAP-Type-2 conditions, may also flush any previously enqueued frames, which
+  // can fail. Returns the result of such flushing, or true if no flushing was
+  // done.
+  bool EnqueueProcessedFrame(scoped_refptr<StreamParserBuffer> frame);
 
   // Appends |processed_frames_|, if not empty, to |stream_| and clears
   // |processed_frames_|. Returns false if append failed, true otherwise.
@@ -143,6 +147,15 @@
   //    coded frame group needs to be signalled.
   base::TimeDelta last_keyframe_presentation_timestamp_;
 
+  // These are used to determine if more incremental flushing is needed to
+  // correctly buffer a SAP-Type-2 non-keyframe when buffering by PTS.  They are
+  // updated (if necessary) in FlushProcessedFrames() and
+  // NotifyStartOfCodedFrameGroup(), and they are consulted (if necessary) in
+  // EnqueueProcessedFrame().
+  base::TimeDelta last_signalled_group_start_pts_;
+  bool have_flushed_since_last_group_start_;
+  ChunkDemuxerStream::RangeApi range_api_;
+
   // The coded frame duration of the last coded frame appended in the current
   // coded frame group. Initially kNoTimestamp, meaning "unset".
   base::TimeDelta last_frame_duration_;
@@ -183,11 +196,15 @@
 MseTrackBuffer::MseTrackBuffer(
     ChunkDemuxerStream* stream,
     MediaLog* media_log,
-    const SourceBufferParseWarningCB& parse_warning_cb)
+    const SourceBufferParseWarningCB& parse_warning_cb,
+    ChunkDemuxerStream::RangeApi range_api)
     : last_decode_timestamp_(kNoDecodeTimestamp()),
       last_processed_decode_timestamp_(DecodeTimestamp()),
       pending_group_start_pts_(kNoTimestamp),
       last_keyframe_presentation_timestamp_(kNoTimestamp),
+      last_signalled_group_start_pts_(kNoTimestamp),
+      have_flushed_since_last_group_start_(false),
+      range_api_(range_api),
       last_frame_duration_(kNoTimestamp),
       highest_presentation_timestamp_(kNoTimestamp),
       needs_random_access_point_(true),
@@ -224,7 +241,7 @@
   }
 }
 
-void MseTrackBuffer::EnqueueProcessedFrame(
+bool MseTrackBuffer::EnqueueProcessedFrame(
     scoped_refptr<StreamParserBuffer> frame) {
   if (frame->is_key_frame()) {
     last_keyframe_presentation_timestamp_ = frame->timestamp();
@@ -258,6 +275,42 @@
           << ") that depends on it. This type of random access point is not "
              "well supported by MSE; buffered range reporting may be less "
              "precise.";
+
+      // SAP-Type-2 GOPs (when buffering ByPts), by definition, contain at
+      // least one non-keyframe with PTS prior to the keyframe's PTS, with DTS
+      // continuous from keyframe forward to at least that non-keyframe. If
+      // such a non-keyframe overlaps the end of a previously buffered GOP
+      // sufficiently (such that, say, some previous GOP's non-keyframes
+      // depending on the overlapped non-keyframe(s) must be dropped), then a
+      // gap might need to result. But if we attempt to buffer the new GOP's
+      // keyframe through at least that first non-keyframe that does such
+      // overlapping all at once, the buffering mechanism doesn't expect such
+      // a discontinuity could occur (failing assumptions in places like
+      // SourceBufferRangeByPts).
+      //
+      // To prevent such failure, we can first flush what's previously been
+      // enqueued (if anything), but do this conservatively to not flush
+      // unnecessarily: we suppress such a flush if this nonkeyframe's PTS is
+      // still higher than the last coded frame group start time signalled for
+      // this track and no flush has yet occurred for this track since then, or
+      // if there has been a flush since then but this nonkeyframe's PTS is no
+      // lower than the PTS of the first frame pending flush currently.
+      if (range_api_ == ChunkDemuxerStream::RangeApi::kNewByPts &&
+          !processed_frames_.empty()) {
+        DCHECK(kNoTimestamp != last_signalled_group_start_pts_);
+
+        if (!have_flushed_since_last_group_start_) {
+          if (frame->timestamp() < last_signalled_group_start_pts_) {
+            if (!FlushProcessedFrames())
+              return false;
+          }
+        } else {
+          if (frame->timestamp() < processed_frames_.front()->timestamp()) {
+            if (!FlushProcessedFrames())
+              return false;
+          }
+        }
+      }
     }
   }
 
@@ -266,6 +319,7 @@
   pending_group_start_pts_ = kNoTimestamp;
   last_processed_decode_timestamp_ = frame->GetDecodeTimestamp();
   processed_frames_.emplace_back(std::move(frame));
+  return true;
 }
 
 bool MseTrackBuffer::FlushProcessedFrames() {
@@ -274,6 +328,7 @@
 
   bool result = stream_->Append(processed_frames_);
   processed_frames_.clear();
+  have_flushed_since_last_group_start_ = true;
 
   DVLOG_IF(3, !result) << __func__
                        << "(): Failure appending processed frames to stream";
@@ -286,6 +341,8 @@
   last_keyframe_presentation_timestamp_ = kNoTimestamp;
   last_processed_decode_timestamp_ = start_dts;
   pending_group_start_pts_ = start_pts;
+  have_flushed_since_last_group_start_ = false;
+  last_signalled_group_start_pts_ = start_pts;
   stream_->OnStartOfCodedFrameGroup(start_dts, start_pts);
 }
 
@@ -429,8 +486,8 @@
     return false;
   }
 
-  track_buffers_[id] =
-      std::make_unique<MseTrackBuffer>(stream, media_log_, parse_warning_cb_);
+  track_buffers_[id] = std::make_unique<MseTrackBuffer>(
+      stream, media_log_, parse_warning_cb_, range_api_);
   return true;
 }
 
@@ -987,14 +1044,15 @@
       }
     }
 
-    DVLOG(3) << __func__ << ": Sending processed frame to stream, "
+    DVLOG(3) << __func__ << ": Enqueueing processed frame "
              << "PTS=" << presentation_timestamp.InMicroseconds()
              << "us, DTS=" << decode_timestamp.InMicroseconds() << "us";
 
     // Steps 11-16: Note, we optimize by appending groups of contiguous
     // processed frames for each track buffer at end of ProcessFrames() or prior
     // to signalling coded frame group starts.
-    track_buffer->EnqueueProcessedFrame(std::move(frame));
+    if (!track_buffer->EnqueueProcessedFrame(std::move(frame)))
+      return false;
 
     // 17. Set last decode timestamp for track buffer to decode timestamp.
     track_buffer->set_last_decode_timestamp(decode_timestamp);
diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc
index a616c780..7835c1f3 100644
--- a/media/filters/frame_processor_unittest.cc
+++ b/media/filters/frame_processor_unittest.cc
@@ -1377,6 +1377,7 @@
                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("1.06", "1"));
   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(1070)));
   EXPECT_TRUE(ProcessFrames(
       "", "1060|0K 1000|10 1050|20 1010|30 1040|40 1020|50 1030|60"));
@@ -1528,6 +1529,7 @@
                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.12", "0.1"));
   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(140)));
   EXPECT_TRUE(ProcessFrames("", "120|0K 100|10 130|20 110|30"));
   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
@@ -1536,6 +1538,7 @@
   // since the next GOP's keyframe PTS is after the first GOP and close enough
   // to be assured adjacent.
   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(165)));
   EXPECT_TRUE(ProcessFrames("", "145|40K 125|50 155|60 135|70"));
   EXPECT_EQ(Milliseconds(0), timestamp_offset_);
@@ -1575,6 +1578,7 @@
                   SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
   EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.12", "0.1"));
   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
   // There is a second GOP that is SAP-Type-2 within this first ProcessFrames,
   // with PTS jumping forward far enough to trigger group start signalling and a
   // flush.
@@ -1595,6 +1599,7 @@
                    DecodeTimestamp::FromPresentationTime(Milliseconds(70)),
                    Milliseconds(155)));
   EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
   // TODO(wolenetz): Duration shouldn't be allowed to possibly increase to 180ms
   // here. See https://crbug.com/763620.
   EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(180)));
@@ -1610,6 +1615,204 @@
 }
 
 TEST_P(FrameProcessorTest,
+       BufferingByPts_ContinuousDts_NewSap2GopEndOverlapsLastGop_3_GopByGop) {
+  // API user might craft a continuous-in-DTS-with-previous-append GOP that has
+  // PTS interval overlapping the previous append, using SAP Type 2 GOPs.  Tests
+  // SAP-Type 2 GOPs, where newly appended GOP overlaps enough nonkeyframes of
+  // the previous GOP such that dropped decode dependencies might cause problems
+  // if the first nonkeyframe with PTS prior to the GOP's keyframe PTS is
+  // flushed at the same time as its keyframe, but the second GOP's keyframe PTS
+  // is close enough to the end of the first GOP's presentation interval to not
+  // signal a new coded frame group start.
+  if (range_api_ == ChunkDemuxerStream::RangeApi::kLegacyByDts) {
+    DVLOG(1) << "Skipping kLegacyByDts versions of this test";
+    return;
+  }
+
+  InSequence s;
+  AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
+  frame_processor_->SetSequenceMode(use_sequence_mode_);
+
+  // Make the sequence mode buffering appear just like segments mode to simplify
+  // this test case.
+  if (use_sequence_mode_)
+    SetTimestampOffset(Milliseconds(500));
+
+  EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
+                                       Milliseconds(500)));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
+  EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
+
+  EXPECT_CALL(callbacks_,
+              OnParseWarning(
+                  SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
+  EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.54", "0.52"));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
+  EXPECT_TRUE(ProcessFrames("", "540|30K 520|40 530|50"));
+
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,550) }");
+  SeekStream(video_.get(), Milliseconds(500));
+  CheckReadsThenReadStalls(video_.get(), "500 520 510 540 520 530");
+}
+
+TEST_P(
+    FrameProcessorTest,
+    BufferingByPts_ContinuousDts_NewSap2GopEndOverlapsLastGop_3_FrameByFrame) {
+  // Tests that the buffered range results match the previous GopByGop test if
+  // each frame of the second GOP is explicitly appended by the app
+  // one-at-a-time.
+  if (range_api_ == ChunkDemuxerStream::RangeApi::kLegacyByDts) {
+    DVLOG(1) << "Skipping kLegacyByDts versions of this test";
+    return;
+  }
+
+  InSequence s;
+  AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
+  frame_processor_->SetSequenceMode(use_sequence_mode_);
+
+  // Make the sequence mode buffering appear just like segments mode to simplify
+  // this test case.
+  if (use_sequence_mode_)
+    SetTimestampOffset(Milliseconds(500));
+
+  EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
+                                       Milliseconds(500)));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
+  EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
+
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
+  EXPECT_TRUE(ProcessFrames("", "540|30K"));
+
+  EXPECT_CALL(callbacks_,
+              OnParseWarning(
+                  SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
+  EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.54", "0.52"));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
+  EXPECT_TRUE(ProcessFrames("", "520|40"));
+
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(550)));
+  EXPECT_TRUE(ProcessFrames("", "530|50"));
+
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,550) }");
+  SeekStream(video_.get(), Milliseconds(500));
+  CheckReadsThenReadStalls(video_.get(), "500 520 510 540 520 530");
+}
+
+TEST_P(FrameProcessorTest,
+       BufferingByPts_ContinuousDts_NewSap2GopEndOverlapsLastGop_4_GopByGop) {
+  // API user might craft a continuous-in-DTS-with-previous-append GOP that has
+  // PTS interval overlapping the previous append, using SAP Type 2 GOPs.  Tests
+  // SAP-Type 2 GOPs, where newly appended GOP overlaps enough nonkeyframes of
+  // the previous GOP such that dropped decode dependencies might cause problems
+  // if the first nonkeyframe with PTS prior to the GOP's keyframe PTS is
+  // flushed at the same time as its keyframe.
+  if (range_api_ == ChunkDemuxerStream::RangeApi::kLegacyByDts) {
+    DVLOG(1) << "Skipping kLegacyByDts versions of this test";
+    return;
+  }
+
+  InSequence s;
+  AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
+  frame_processor_->SetSequenceMode(use_sequence_mode_);
+
+  // Make the sequence mode buffering appear just like segments mode to simplify
+  // this test case.
+  if (use_sequence_mode_)
+    SetTimestampOffset(Milliseconds(500));
+
+  EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
+                                       Milliseconds(500)));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
+  EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
+
+  EXPECT_CALL(
+      callbacks_,
+      OnGroupStart(DemuxerStream::VIDEO,
+                   DecodeTimestamp::FromPresentationTime(Milliseconds(20)),
+                   Milliseconds(530)));
+  EXPECT_CALL(callbacks_,
+              OnParseWarning(
+                  SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
+  EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.55", "0.52"));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
+  EXPECT_TRUE(ProcessFrames("", "550|30K 520|40 530|50 540|60"));
+
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,560) }");
+  SeekStream(video_.get(), Milliseconds(500));
+  CheckReadsThenReadStalls(video_.get(), "500 520 510 550 520 530 540");
+}
+
+TEST_P(
+    FrameProcessorTest,
+    BufferingByPts_ContinuousDts_NewSap2GopEndOverlapsLastGop_4_FrameByFrame) {
+  // Tests that the buffered range results match the previous GopByGop test if
+  // each frame of the second GOP is explicitly appended by the app
+  // one-at-a-time.
+  if (range_api_ == ChunkDemuxerStream::RangeApi::kLegacyByDts) {
+    DVLOG(1) << "Skipping kLegacyByDts versions of this test";
+    return;
+  }
+
+  InSequence s;
+  AddTestTracks(HAS_VIDEO | OBSERVE_APPENDS_AND_GROUP_STARTS);
+  frame_processor_->SetSequenceMode(use_sequence_mode_);
+
+  // Make the sequence mode buffering appear just like segments mode to simplify
+  // this test case.
+  if (use_sequence_mode_)
+    SetTimestampOffset(Milliseconds(500));
+
+  EXPECT_CALL(callbacks_, OnGroupStart(DemuxerStream::VIDEO, DecodeTimestamp(),
+                                       Milliseconds(500)));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(530)));
+  EXPECT_TRUE(ProcessFrames("", "500|0K 520|10 510|20"));
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,530) }");
+
+  EXPECT_CALL(
+      callbacks_,
+      OnGroupStart(DemuxerStream::VIDEO,
+                   DecodeTimestamp::FromPresentationTime(Milliseconds(20)),
+                   Milliseconds(530)));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
+  EXPECT_TRUE(ProcessFrames("", "550|30K"));
+
+  EXPECT_CALL(callbacks_,
+              OnParseWarning(
+                  SourceBufferParseWarning::kKeyframeTimeGreaterThanDependant));
+  EXPECT_MEDIA_LOG(KeyframeTimeGreaterThanDependant("0.55", "0.52"));
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
+  EXPECT_TRUE(ProcessFrames("", "520|40"));
+
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
+  EXPECT_TRUE(ProcessFrames("", "530|50"));
+
+  EXPECT_CALL(callbacks_, OnAppend(DemuxerStream::VIDEO, _));
+  EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(560)));
+  EXPECT_TRUE(ProcessFrames("", "540|60"));
+
+  CheckExpectedRangesByTimestamp(video_.get(), "{ [500,560) }");
+  SeekStream(video_.get(), Milliseconds(500));
+  CheckReadsThenReadStalls(video_.get(), "500 520 510 550 520 530 540");
+}
+
+TEST_P(FrameProcessorTest,
        BufferingByPts_ContinuousDts_GopKeyframePtsOrder_2_1_3) {
   // White-box test, demonstrating expected behavior for a specially crafted
   // sequence that "should" be unusual, but gracefully handled:
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc
index 731a619b..7a84dd6b 100644
--- a/media/filters/fuchsia/fuchsia_video_decoder.cc
+++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -4,6 +4,7 @@
 
 #include "media/filters/fuchsia/fuchsia_video_decoder.h"
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <fuchsia/mediacodec/cpp/fidl.h>
 #include <zircon/rights.h>
 
@@ -102,8 +103,7 @@
  public:
   CodecBuffer() = default;
 
-  bool Initialize(
-      const fuchsia::mediacodec::CodecBufferConstraints& constraints) {
+  bool Initialize(const fuchsia::media::StreamBufferConstraints& constraints) {
     size_ = constraints.per_packet_buffer_bytes_recommended;
 
     if (constraints.is_physically_contiguous_required) {
@@ -121,7 +121,7 @@
   bool ToFidlCodecBuffer(uint64_t buffer_lifetime_ordinal,
                          uint32_t buffer_index,
                          bool read_only,
-                         fuchsia::mediacodec::CodecBuffer* buffer) {
+                         fuchsia::media::StreamBuffer* buffer) {
     zx::vmo vmo_dup;
     zx_status_t status = vmo_.duplicate(
         read_only ? kReadOnlyVmoRights : ZX_RIGHT_SAME_RIGHTS, &vmo_dup);
@@ -130,7 +130,7 @@
       return false;
     }
 
-    fuchsia::mediacodec::CodecBufferDataVmo buf_data;
+    fuchsia::media::StreamBufferDataVmo buf_data;
     buf_data.vmo_handle = std::move(vmo_dup);
 
     buf_data.vmo_usable_start = 0;
@@ -156,8 +156,7 @@
 
   ~InputBuffer() { CallDecodeCallbackIfAny(DecodeStatus::ABORTED); }
 
-  bool Initialize(
-      const fuchsia::mediacodec::CodecBufferConstraints& constraints) {
+  bool Initialize(const fuchsia::media::StreamBufferConstraints& constraints) {
     return buffer_.Initialize(constraints);
   }
 
@@ -218,8 +217,7 @@
  public:
   OutputBuffer() = default;
 
-  bool Initialize(
-      const fuchsia::mediacodec::CodecBufferConstraints& constraints) {
+  bool Initialize(const fuchsia::media::StreamBufferConstraints& constraints) {
     if (!buffer_.Initialize(constraints)) {
       return false;
     }
@@ -290,11 +288,10 @@
   // Event handlers for |codec_|.
   void OnStreamFailed(uint64_t stream_lifetime_ordinal);
   void OnInputConstraints(
-      fuchsia::mediacodec::CodecBufferConstraints input_constraints);
-  void OnFreeInputPacket(
-      fuchsia::mediacodec::CodecPacketHeader free_input_packet);
-  void OnOutputConfig(fuchsia::mediacodec::CodecOutputConfig output_config);
-  void OnOutputPacket(fuchsia::mediacodec::CodecPacket output_packet,
+      fuchsia::media::StreamBufferConstraints input_constraints);
+  void OnFreeInputPacket(fuchsia::media::PacketHeader free_input_packet);
+  void OnOutputConfig(fuchsia::media::StreamOutputConfig output_config);
+  void OnOutputPacket(fuchsia::media::Packet output_packet,
                       bool error_detected_before,
                       bool error_detected_during);
   void OnOutputEndOfStream(uint64_t stream_lifetime_ordinal,
@@ -304,14 +301,14 @@
 
   // Called by OnInputConstraints() to initialize input buffers.
   bool InitializeInputBuffers(
-      fuchsia::mediacodec::CodecBufferConstraints constraints);
+      fuchsia::media::StreamBufferConstraints constraints);
 
   // Pumps |pending_decodes_| to the decoder.
   void PumpInput();
 
   // Called by OnInputConstraints() to initialize input buffers.
   bool InitializeOutputBuffers(
-      fuchsia::mediacodec::CodecBufferConstraints constraints);
+      fuchsia::media::StreamBufferConstraints constraints);
 
   // Destruction callback for the output VideoFrame instances.
   void OnFrameDestroyed(scoped_refptr<OutputBuffer> buffer,
@@ -326,7 +323,7 @@
   // value is used only if the aspect ratio is not specified in the bitstream.
   float container_pixel_aspect_ratio_ = 1.0;
 
-  fuchsia::mediacodec::CodecPtr codec_;
+  fuchsia::media::StreamProcessorPtr codec_;
 
   uint64_t stream_lifetime_ordinal_ = 1;
 
@@ -339,7 +336,7 @@
   std::vector<InputBuffer> input_buffers_;
   int num_used_input_buffers_ = 0;
 
-  fuchsia::mediacodec::VideoUncompressedFormat output_format_;
+  fuchsia::media::VideoUncompressedFormat output_format_;
   uint64_t output_buffer_lifetime_ordinal_ = 1;
   std::vector<scoped_refptr<OutputBuffer>> output_buffers_;
   int num_used_output_buffers_ = 0;
@@ -407,7 +404,7 @@
   auto codec_factory =
       base::fuchsia::ComponentContext::GetDefault()
           ->ConnectToService<fuchsia::mediacodec::CodecFactory>();
-  codec_factory->CreateDecoder(std::move(codec_params), codec_.NewRequest());
+  codec_factory->CreateDecoder2(std::move(codec_params), codec_.NewRequest());
 
   codec_.set_error_handler(
       [this](zx_status_t status) {
@@ -494,7 +491,7 @@
 }
 
 void FuchsiaVideoDecoder::OnInputConstraints(
-    fuchsia::mediacodec::CodecBufferConstraints input_constraints) {
+    fuchsia::media::StreamBufferConstraints input_constraints) {
   if (!InitializeInputBuffers(std::move(input_constraints))) {
     DLOG(ERROR) << "Failed to initialize input buffers.";
     OnError();
@@ -505,7 +502,7 @@
 }
 
 void FuchsiaVideoDecoder::OnFreeInputPacket(
-    fuchsia::mediacodec::CodecPacketHeader free_input_packet) {
+    fuchsia::media::PacketHeader free_input_packet) {
   if (free_input_packet.buffer_lifetime_ordinal !=
       input_buffer_lifetime_ordinal_) {
     return;
@@ -530,7 +527,7 @@
 }
 
 void FuchsiaVideoDecoder::OnOutputConfig(
-    fuchsia::mediacodec::CodecOutputConfig output_config) {
+    fuchsia::media::StreamOutputConfig output_config) {
   if (output_config.stream_lifetime_ordinal != stream_lifetime_ordinal_)
     return;
 
@@ -553,10 +550,9 @@
   output_format_ = std::move(format.domain->video().uncompressed());
 }
 
-void FuchsiaVideoDecoder::OnOutputPacket(
-    fuchsia::mediacodec::CodecPacket output_packet,
-    bool error_detected_before,
-    bool error_detected_during) {
+void FuchsiaVideoDecoder::OnOutputPacket(fuchsia::media::Packet output_packet,
+                                         bool error_detected_before,
+                                         bool error_detected_during) {
   if (output_packet.header.buffer_lifetime_ordinal !=
       output_buffer_lifetime_ordinal_) {
     return;
@@ -693,7 +689,7 @@
 }
 
 bool FuchsiaVideoDecoder::InitializeInputBuffers(
-    fuchsia::mediacodec::CodecBufferConstraints constraints) {
+    fuchsia::media::StreamBufferConstraints constraints) {
   input_buffer_lifetime_ordinal_ += 2;
 
   auto settings = constraints.default_settings;
@@ -702,11 +698,11 @@
   codec_->SetInputBufferSettings(settings);
 
   int total_buffers =
-      settings.packet_count_for_codec + settings.packet_count_for_client;
+      settings.packet_count_for_server + settings.packet_count_for_client;
   std::vector<InputBuffer> new_buffers(total_buffers);
 
   for (int i = 0; i < total_buffers; ++i) {
-    fuchsia::mediacodec::CodecBuffer codec_buffer;
+    fuchsia::media::StreamBuffer codec_buffer;
 
     if (!new_buffers[i].Initialize(constraints) ||
         !new_buffers[i].buffer().ToFidlCodecBuffer(
@@ -758,7 +754,7 @@
     size_t bytes_filled =
         input_buffer->FillFromDecodeBuffer(&pending_decodes_.front());
 
-    fuchsia::mediacodec::CodecPacket packet;
+    fuchsia::media::Packet packet;
     packet.header.buffer_lifetime_ordinal = input_buffer_lifetime_ordinal_;
     packet.header.packet_index = input_buffer - input_buffers_.begin();
     packet.buffer_index = packet.header.packet_index;
@@ -779,7 +775,7 @@
 }
 
 bool FuchsiaVideoDecoder::InitializeOutputBuffers(
-    fuchsia::mediacodec::CodecBufferConstraints constraints) {
+    fuchsia::media::StreamBufferConstraints constraints) {
   // mediacodec API expects odd buffer lifetime ordinal, which is incremented by
   // 2 for each buffer generation.
   output_buffer_lifetime_ordinal_ += 2;
@@ -794,11 +790,11 @@
   codec_->SetOutputBufferSettings(std::move(settings));
 
   int total_buffers =
-      settings.packet_count_for_codec + settings.packet_count_for_client;
+      settings.packet_count_for_server + settings.packet_count_for_client;
   std::vector<scoped_refptr<OutputBuffer>> new_buffers(total_buffers);
 
   for (int i = 0; i < total_buffers; ++i) {
-    fuchsia::mediacodec::CodecBuffer codec_buffer;
+    fuchsia::media::StreamBuffer codec_buffer;
     new_buffers[i] = new OutputBuffer();
     if (!new_buffers[i]->Initialize(constraints) ||
         !new_buffers[i]->buffer().ToFidlCodecBuffer(
@@ -825,8 +821,8 @@
   if (buffer_lifetime_ordinal == output_buffer_lifetime_ordinal_) {
     DCHECK_GT(num_used_output_buffers_, 0);
     num_used_output_buffers_--;
-    codec_->RecycleOutputPacket(fuchsia::mediacodec::CodecPacketHeader{
-        buffer_lifetime_ordinal, packet_index});
+    codec_->RecycleOutputPacket(
+        fuchsia::media::PacketHeader{buffer_lifetime_ordinal, packet_index});
   }
 }
 
diff --git a/media/learning/mojo/mojo_learning_session_impl_unittest.cc b/media/learning/mojo/mojo_learning_session_impl_unittest.cc
index ba75f87..5399d20 100644
--- a/media/learning/mojo/mojo_learning_session_impl_unittest.cc
+++ b/media/learning/mojo/mojo_learning_session_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "media/learning/common/learning_session.h"
 #include "media/learning/mojo/mojo_learning_session_impl.h"
+#include "media/learning/mojo/public/mojom/learning_types.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
diff --git a/media/mojo/services/interface_factory_impl.h b/media/mojo/services/interface_factory_impl.h
index 9e3d0533..224a376 100644
--- a/media/mojo/services/interface_factory_impl.h
+++ b/media/mojo/services/interface_factory_impl.h
@@ -10,7 +10,13 @@
 #include "base/macros.h"
 #include "media/base/media_util.h"
 #include "media/mojo/buildflags.h"
+#include "media/mojo/interfaces/audio_decoder.mojom.h"
+#include "media/mojo/interfaces/cdm_proxy.mojom.h"
+#include "media/mojo/interfaces/content_decryption_module.mojom.h"
+#include "media/mojo/interfaces/decryptor.mojom.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
+#include "media/mojo/interfaces/renderer.mojom.h"
+#include "media/mojo/interfaces/video_decoder.mojom.h"
 #include "media/mojo/services/deferred_destroy_strong_binding_set.h"
 #include "media/mojo/services/mojo_cdm_service_context.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc
index 2a05263..1c0f8cb 100644
--- a/media/mojo/services/media_service_unittest.cc
+++ b/media/mojo/services/media_service_unittest.cc
@@ -21,6 +21,7 @@
 #include "media/mojo/clients/mojo_decryptor.h"
 #include "media/mojo/clients/mojo_demuxer_stream_impl.h"
 #include "media/mojo/common/media_type_converters.h"
+#include "media/mojo/interfaces/cdm_proxy.mojom.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
 #include "media/mojo/interfaces/decryptor.mojom.h"
diff --git a/media/mojo/services/video_decode_perf_history.cc b/media/mojo/services/video_decode_perf_history.cc
index 3b07a3be..f2e70af 100644
--- a/media/mojo/services/video_decode_perf_history.cc
+++ b/media/mojo/services/video_decode_perf_history.cc
@@ -15,6 +15,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/video_codecs.h"
 #include "media/capabilities/learning_helper.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
diff --git a/media/mojo/services/video_decode_perf_history_unittest.cc b/media/mojo/services/video_decode_perf_history_unittest.cc
index 7641bdb..4c015f9 100644
--- a/media/mojo/services/video_decode_perf_history_unittest.cc
+++ b/media/mojo/services/video_decode_perf_history_unittest.cc
@@ -18,6 +18,7 @@
 #include "components/ukm/test_ukm_recorder.h"
 #include "media/base/media_switches.h"
 #include "media/capabilities/video_decode_stats_db.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/media/mojo/services/video_decode_stats_recorder.h b/media/mojo/services/video_decode_stats_recorder.h
index 149c19029..29204e49 100644
--- a/media/mojo/services/video_decode_stats_recorder.h
+++ b/media/mojo/services/video_decode_stats_recorder.h
@@ -10,6 +10,7 @@
 
 #include "base/time/time.h"
 #include "media/base/video_codecs.h"
+#include "media/mojo/interfaces/media_types.mojom.h"
 #include "media/mojo/interfaces/video_decode_stats_recorder.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
 #include "media/mojo/services/video_decode_perf_history.h"
diff --git a/media/webrtc/audio_processor.h b/media/webrtc/audio_processor.h
index de288965..c7e7c93 100644
--- a/media/webrtc/audio_processor.h
+++ b/media/webrtc/audio_processor.h
@@ -15,8 +15,8 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "media/audio/audio_io.h"
-#include "media/audio/audio_processing.h"
 #include "media/base/audio_parameters.h"
+#include "media/base/audio_processing.h"
 #include "media/webrtc/audio_delay_stats_reporter.h"
 #include "media/webrtc/audio_processor_controls.h"
 #include "media/webrtc/echo_information.h"
diff --git a/mojo/core/dispatcher.h b/mojo/core/dispatcher.h
index 58cd7a7..be62e70 100644
--- a/mojo/core/dispatcher.h
+++ b/mojo/core/dispatcher.h
@@ -41,8 +41,14 @@
 
 using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>;
 
-// A |Dispatcher| implements Mojo EDK calls that are associated with a
+// A |Dispatcher| implements Mojo core API calls that are associated with a
 // particular MojoHandle.
+//
+// Every MojoHandle in the system is an opaque reference to some implementation
+// of this class. See MessagePipeDispatcher, SharedBufferDispatcher,
+// DataPipeConsumerDispatcher, DataPipeProducerDispatcher, WatcherDispatcher
+// (which should really be renamed to TrapDispatcher now), and
+// InvitationDispatcher.
 class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
     : public base::RefCountedThreadSafe<Dispatcher> {
  public:
@@ -75,67 +81,130 @@
 
   ///////////// Watcher API ////////////////////
 
+  // Supports the |MojoAddTrigger()| API if implemented by this Dispatcher.
+  // |dispatcher| is the resolved Dispatcher implementation from the given
+  // MojoHandle to watch. The remaining arguments correspond directly to
+  // arguments on the original |MojoAddTrigger()| API call. See
+  // |MojoAddTrigger()| documentation.
   virtual MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher,
                                      MojoHandleSignals signals,
                                      MojoTriggerCondition condition,
                                      uintptr_t context);
+
+  // Supports the |MojoRemoveTrigger()| API if implemented by this Dispatcher.
+  // Arguments correspond directly to arguments on the original
+  // |MojoRemoveTrigger()| API call. See |MojoRemoveTrigger()| documentation.
   virtual MojoResult CancelWatch(uintptr_t context);
+
+  // Supports the |MojoArmTrap()| API if implemented by this Dispatcher.
+  // Arguments correspond directly to arguments on the original |MojoArmTrap()|
+  // API call. See |MojoArmTrap()| documentation.
   virtual MojoResult Arm(uint32_t* num_blocking_events,
                          MojoTrapEvent* blocking_events);
 
   ///////////// Message pipe API /////////////
 
+  // Supports the |MojoWriteMessage()| API if implemented by this Dispatcher.
+  // |message| is the message object referenced by the MojoMessageHandle passed
+  // to the original API call. See |MojoWriteMessage()| documentation.
   virtual MojoResult WriteMessage(
       std::unique_ptr<ports::UserMessageEvent> message);
 
+  // Supports the |MojoReadMessage()| API if implemented by this Dispatcher.
+  // If successful, |*message| contains a newly read message object, which will
+  // be yielded to the API caller as an opaque MojoMessageHandle value. See
+  // |MojoReadMessage()| documentation.
   virtual MojoResult ReadMessage(
       std::unique_ptr<ports::UserMessageEvent>* message);
 
   ///////////// Shared buffer API /////////////
 
+  // Supports the |MojoDuplicateBufferHandle()| API if implemented by this
+  // Dispatcher.
+  //
   // |options| may be null. |new_dispatcher| must not be null, but
   // |*new_dispatcher| should be null (and will contain the dispatcher for the
   // new handle on success).
+  //
+  // See |MojoDuplicateBufferHandle()| documentation.
   virtual MojoResult DuplicateBufferHandle(
       const MojoDuplicateBufferHandleOptions* options,
       scoped_refptr<Dispatcher>* new_dispatcher);
 
+  // Supports the |MojoMapBuffer()| API if implemented by this Dispatcher.
+  // |offset| and |num_bytes| correspond to arguments given to the original API
+  // call. On success, |*mapping| will contain a memory mapping that Mojo Core
+  // will internally retain until the buffer is unmapped by |MojoUnmapBuffer()|.
+  // See |MojoMapBuffer()| documentation.
   virtual MojoResult MapBuffer(
       uint64_t offset,
       uint64_t num_bytes,
       std::unique_ptr<PlatformSharedMemoryMapping>* mapping);
 
+  // Supports the |MojoGetBufferInfo()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoGetBufferInfo()| documentation.
   virtual MojoResult GetBufferInfo(MojoSharedBufferInfo* info);
 
   ///////////// Data pipe consumer API /////////////
 
+  // Supports the the |MojoReadData()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoReadData()| documentation.
   virtual MojoResult ReadData(const MojoReadDataOptions& options,
                               void* elements,
                               uint32_t* num_bytes);
 
+  // Supports the the |MojoBeginReadData()| API if implemented by this
+  // Dispatcher. Arguments correspond to the ones given to the original API
+  // call. See |MojoBeginReadData()| documentation.
   virtual MojoResult BeginReadData(const void** buffer,
                                    uint32_t* buffer_num_bytes);
 
+  // Supports the the |MojoEndReadData()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoEndReadData()| documentation.
   virtual MojoResult EndReadData(uint32_t num_bytes_read);
 
   ///////////// Data pipe producer API /////////////
 
+  // Supports the the |MojoWriteData()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoWriteData()| documentation.
   virtual MojoResult WriteData(const void* elements,
                                uint32_t* num_bytes,
                                const MojoWriteDataOptions& options);
 
+  // Supports the the |MojoBeginWriteData()| API if implemented by this
+  // Dispatcher. Arguments correspond to the ones given to the original API
+  // call. See |MojoBeginWriteData()| documentation.
   virtual MojoResult BeginWriteData(void** buffer, uint32_t* buffer_num_bytes);
 
+  // Supports the the |MojoEndWriteData()| API if implemented by this
+  // Dispatcher. Arguments correspond to the ones given to the original API
+  // call. See |MojoEndWriteData()| documentation.
   virtual MojoResult EndWriteData(uint32_t num_bytes_written);
 
-  // Invitation API.
+  // Supports the |MojoAttachMessagePipeToInvitation()| API if implemented by
+  // this Dispatcher. Arguments correspond to the ones given to the original API
+  // call. See |MojoAttachMessagePipeToInvitation()| documentation.
   virtual MojoResult AttachMessagePipe(base::StringPiece name,
                                        ports::PortRef remote_peer_port);
+
+  // Supports the |MojoExtractMessagePipeFromInvitation()| API if implemented by
+  // this Dispatcher. Arguments correspond to the ones given to the original API
+  // call. See |MojoExtractMessagePipeFromInvitation()| documentation.
   virtual MojoResult ExtractMessagePipe(base::StringPiece name,
                                         MojoHandle* message_pipe_handle);
 
-  // Quota API.
+  // Supports the |MojoSetQuota()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoSetQuota()| documentation.
   virtual MojoResult SetQuota(MojoQuotaType type, uint64_t limit);
+
+  // Supports the |MojoQueryQuota()| API if implemented by this Dispatcher.
+  // Arguments correspond to the ones given to the original API call. See
+  // |MojoQueryQuota()| documentation.
   virtual MojoResult QueryQuota(MojoQuotaType type,
                                 uint64_t* limit,
                                 uint64_t* usage);
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 853c946..e4866fc 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2667,6 +2667,8 @@
     "nqe/network_quality_estimator_test_util.h",
     "proxy_resolution/mock_pac_file_fetcher.cc",
     "proxy_resolution/mock_pac_file_fetcher.h",
+    "proxy_resolution/mock_proxy_host_resolver.cc",
+    "proxy_resolution/mock_proxy_host_resolver.h",
     "proxy_resolution/mock_proxy_resolver.cc",
     "proxy_resolution/mock_proxy_resolver.h",
     "proxy_resolution/proxy_config_service_common_unittest.cc",
@@ -2844,6 +2846,7 @@
 if (use_v8_in_net) {
   component("net_with_v8") {
     sources = [
+      "proxy_resolution/proxy_host_resolver.h",
       "proxy_resolution/proxy_resolver_v8.cc",
       "proxy_resolution/proxy_resolver_v8.h",
       "proxy_resolution/proxy_resolver_v8_tracing.cc",
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index 4fe090c..e9b0c4c 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -674,13 +674,18 @@
   CookieStatusList excluded_cookies;
   if (HasCookieableScheme(url)) {
     std::vector<CanonicalCookie*> cookie_ptrs;
-    FindCookiesForHostAndDomain(url, options, &cookie_ptrs);
-    std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
+    FindCookiesForRegistryControlledHost(url, &cookie_ptrs);
 
     cookies.reserve(cookie_ptrs.size());
-    for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
-         it != cookie_ptrs.end(); it++)
-      cookies.push_back(**it);
+    std::vector<CanonicalCookie*> filtered_cookie_ptrs;
+    FilterCookiesWithOptions(url, options, &cookie_ptrs, &filtered_cookie_ptrs);
+
+    std::sort(filtered_cookie_ptrs.begin(), filtered_cookie_ptrs.end(),
+              CookieSorter);
+
+    for (auto* cookie : filtered_cookie_ptrs) {
+      cookies.push_back(*cookie);
+    }
   }
   MaybeRunCookieCallback(std::move(callback), cookies, excluded_cookies);
 }
@@ -775,15 +780,17 @@
   options.set_same_site_cookie_mode(
       CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
   // Get the cookies for this host and its domain(s).
-  std::vector<CanonicalCookie*> cookies;
-  FindCookiesForHostAndDomain(url, options, &cookies);
+  std::vector<CanonicalCookie*> cookie_ptrs;
+  std::vector<CanonicalCookie*> filtered_cookie_ptrs;
+  FindCookiesForRegistryControlledHost(url, &cookie_ptrs);
+  FilterCookiesWithOptions(url, options, &cookie_ptrs, &filtered_cookie_ptrs);
   std::set<CanonicalCookie*> matching_cookies;
 
-  for (auto* cookie : cookies) {
+  for (auto* cookie : filtered_cookie_ptrs) {
+    DCHECK(cookie->IsOnPath(url.path()));
+    DCHECK(cookie->IsDomainMatch(url.host()));
     if (cookie->Name() != cookie_name)
       continue;
-    if (!cookie->IsOnPath(url.path()))
-      continue;
     matching_cookies.insert(cookie);
   }
 
@@ -1077,32 +1084,15 @@
   DCHECK_EQ(num_duplicates, num_duplicates_found);
 }
 
-void CookieMonster::FindCookiesForHostAndDomain(
+void CookieMonster::FindCookiesForRegistryControlledHost(
     const GURL& url,
-    const CookieOptions& options,
     std::vector<CanonicalCookie*>* cookies) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  const Time current_time(CurrentTime());
+  Time current_time(CurrentTime());
 
-  // Probe to save statistics relatively frequently.  We do it here rather
-  // than in the set path as many websites won't set cookies, and we
-  // want to collect statistics whenever the browser's being used.
-  RecordPeriodicStats(current_time);
-
-  // Can just dispatch to FindCookiesForKey
+  // Retrieve all cookies for a given key
   const std::string key(GetKey(url.host_piece()));
-  FindCookiesForKey(key, url, options, current_time, cookies);
-}
-
-void CookieMonster::FindCookiesForKey(const std::string& key,
-                                      const GURL& url,
-                                      const CookieOptions& options,
-                                      const Time& current,
-                                      std::vector<CanonicalCookie*>* cookies) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  std::vector<CanonicalCookie*> full_cookie_list;
 
   for (CookieMapItPair its = cookies_.equal_range(key);
        its.first != its.second;) {
@@ -1111,27 +1101,41 @@
     ++its.first;
 
     // If the cookie is expired, delete it.
-    if (cc->IsExpired(current)) {
+    if (cc->IsExpired(current_time)) {
       InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
       continue;
     }
-    full_cookie_list.push_back(cc);
+    cookies->push_back(cc);
   }
+}
 
-  for (CanonicalCookie* cc : full_cookie_list) {
+void CookieMonster::FilterCookiesWithOptions(
+    const GURL url,
+    const CookieOptions options,
+    std::vector<CanonicalCookie*>* cookie_ptrs,
+    std::vector<CanonicalCookie*>* cookies) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  // Probe to save statistics relatively frequently.  We do it here rather
+  // than in the set path as many websites won't set cookies, and we
+  // want to collect statistics whenever the browser's being used.
+  Time current_time(CurrentTime());
+  RecordPeriodicStats(current_time);
+
+  for (std::vector<CanonicalCookie*>::iterator it = cookie_ptrs->begin();
+       it != cookie_ptrs->end(); it++) {
     // Filter out cookies that should not be included for a request to the
     // given |url|. HTTP only cookies are filtered depending on the passed
     // cookie |options|.
-    if (cc->IncludeForRequestURL(url, options) !=
-        CanonicalCookie::CookieInclusionStatus::INCLUDE)
+    if ((*it)->IncludeForRequestURL(url, options) !=
+        CanonicalCookie::CookieInclusionStatus::INCLUDE) {
       continue;
-
-    // Add this cookie to the set of matching cookies. Update the access
-    // time if we've been requested to do so.
-    if (options.update_access_time()) {
-      InternalUpdateCookieAccessTime(cc, current);
     }
-    cookies->push_back(cc);
+
+    if (options.update_access_time())
+      InternalUpdateCookieAccessTime(*it, current_time);
+
+    cookies->push_back(*it);
   }
 }
 
@@ -1714,8 +1718,8 @@
 
 // A wrapper around registry_controlled_domains::GetDomainAndRegistry
 // to make clear we're creating a key for our local map or for the persistent
-// store's use. Here and in FindCookiesForHostAndDomain() are the only two
-// places where we need to conditionalize based on key type.
+// store's use. Here and in FindCookiesForRegistryControlledHost() are the only
+// two places where we need to conditionalize based on key type.
 //
 // Note that this key algorithm explicitly ignores the scheme.  This is
 // because when we're entering cookies into the map from the backing store,
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 9251db4d..a4bb4e81 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -446,16 +446,14 @@
 
   void SetDefaultCookieableSchemes();
 
-  void FindCookiesForHostAndDomain(const GURL& url,
-                                   const CookieOptions& options,
-                                   std::vector<CanonicalCookie*>* cookies);
+  void FindCookiesForRegistryControlledHost(
+      const GURL& url,
+      std::vector<CanonicalCookie*>* cookies);
 
-  void FindCookiesForKey(const std::string& key,
-                         const GURL& url,
-                         const CookieOptions& options,
-                         const base::Time& current,
-                         std::vector<CanonicalCookie*>* cookies);
-
+  void FilterCookiesWithOptions(const GURL url,
+                                const CookieOptions options,
+                                std::vector<CanonicalCookie*>* cookie_ptrs,
+                                std::vector<CanonicalCookie*>* cookies);
   // Delete any cookies that are equivalent to |ecc| (same path, domain, etc).
   // |source_secure| indicates if the source may override existing secure
   // cookies.
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 5f53061..33d2459 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -1578,6 +1578,10 @@
       cm.get(), https_www_foo_.url(),
       http_www_foo_.Format("E=F; domain=.%D; secure"), options));
 
+  EXPECT_TRUE(SetCookieWithOptions(cm.get(), http_www_bar_.url(),
+                                   http_www_bar_.Format("G=H; domain=.%D"),
+                                   options));
+
   const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
 
   base::PlatformThread::Sleep(kAccessDelay);
@@ -1724,6 +1728,26 @@
   EXPECT_NE(the_not_so_distant_past, cookies[0].CreationDate());
 }
 
+// Check that GetAllCookiesForURL() does not return expired cookies and deletes
+// them.
+TEST_F(CookieMonsterTest, DeleteExpiredCookiesOnGet) {
+  std::unique_ptr<CookieMonster> cm(
+      new CookieMonster(nullptr, nullptr, &net_log_));
+
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B;"));
+
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "C=D;"));
+
+  CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_foo_.url());
+  EXPECT_EQ(2u, cookies.size());
+
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(),
+                        "C=D; expires=Thu, 01-Jan-1970 00:00:00 GMT"));
+
+  cookies = GetAllCookiesForURL(cm.get(), http_www_foo_.url());
+  EXPECT_EQ(1u, cookies.size());
+}
+
 TEST_F(CookieMonsterTest, DeleteCookieByName) {
   std::unique_ptr<CookieMonster> cm(
       new CookieMonster(nullptr, nullptr, &net_log_));
@@ -1731,6 +1755,8 @@
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A1; path=/"));
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A2; path=/foo"));
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A3; path=/bar"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_bar_foo_.url(), "A=A4; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), http_www_bar_.url(), "A=A5; path=/foo"));
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B1; path=/"));
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B2; path=/foo"));
   EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/bar"));
@@ -1738,7 +1764,7 @@
   DeleteCookie(cm.get(), http_www_foo_.AppendPath("foo/bar"), "A");
 
   CookieList cookies = GetAllCookies(cm.get());
-  size_t expected_size = 4;
+  size_t expected_size = 6;
   EXPECT_EQ(expected_size, cookies.size());
   for (auto it = cookies.begin(); it != cookies.end(); ++it) {
     EXPECT_NE("A1", it->Value());
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index d8b92f1..c15f43c 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -108,6 +108,8 @@
  protected:
   CookieStoreTest()
       : http_www_foo_("http://www.foo.com"),
+        http_bar_foo_("http://bar.foo.com"),
+        http_www_bar_("http://www.bar.com"),
         https_www_foo_("https://www.foo.com"),
         ftp_foo_("ftp://ftp.foo.com/"),
         ws_www_foo_("ws://www.foo.com"),
@@ -337,6 +339,8 @@
   }
 
   const CookieURLHelper http_www_foo_;
+  const CookieURLHelper http_bar_foo_;
+  const CookieURLHelper http_www_bar_;
   const CookieURLHelper https_www_foo_;
   const CookieURLHelper ftp_foo_;
   const CookieURLHelper ws_www_foo_;
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc
index b16213c..e4b61208 100644
--- a/net/dns/address_sorter_posix_unittest.cc
+++ b/net/dns/address_sorter_posix_unittest.cc
@@ -181,8 +181,6 @@
     NOTIMPLEMENTED();
     return nullptr;
   }
-  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
-
   void AddMapping(const IPAddress& dst, const IPAddress& src) {
     mapping_[dst] = src;
   }
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc
index 9c3e4646..8e1d709 100644
--- a/net/dns/dns_session_unittest.cc
+++ b/net/dns/dns_session_unittest.cc
@@ -69,8 +69,6 @@
     return nullptr;
   }
 
-  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
-
  private:
   std::list<std::unique_ptr<SocketDataProvider>> data_providers_;
 };
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index afa541e9..75cd94d 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -41,12 +41,10 @@
 
 namespace {
 
-base::AtomicSequenceNumber g_next_shard_id;
-
 std::unique_ptr<ClientSocketPoolManager> CreateSocketPoolManager(
     HttpNetworkSession::SocketPoolType pool_type,
     const HttpNetworkSession::Context& context,
-    const std::string& ssl_session_cache_shard,
+    SSLClientSessionCache* ssl_client_session_cache,
     WebSocketEndpointLockManager* websocket_endpoint_lock_manager) {
   // TODO(yutak): Differentiate WebSocket pool manager and allow more
   // simultaneous connections for WebSockets.
@@ -58,7 +56,7 @@
       context.network_quality_estimator, context.host_resolver,
       context.cert_verifier, context.channel_id_service,
       context.transport_security_state, context.cert_transparency_verifier,
-      context.ct_policy_enforcer, ssl_session_cache_shard,
+      context.ct_policy_enforcer, ssl_client_session_cache,
       context.ssl_config_service, websocket_endpoint_lock_manager,
       context.proxy_delegate, pool_type);
 }
@@ -194,6 +192,7 @@
 #endif
       proxy_resolution_service_(context.proxy_resolution_service),
       ssl_config_service_(context.ssl_config_service),
+      ssl_client_session_cache_(SSLClientSessionCache::Config()),
       push_delegate_(nullptr),
       quic_stream_factory_(
           context.net_log,
@@ -257,13 +256,11 @@
   DCHECK(ssl_config_service_);
   CHECK(http_server_properties_);
 
-  const std::string ssl_session_cache_shard =
-      "http_network_session/" + base::IntToString(g_next_shard_id.GetNext());
   normal_socket_pool_manager_ = CreateSocketPoolManager(
-      NORMAL_SOCKET_POOL, context, ssl_session_cache_shard,
+      NORMAL_SOCKET_POOL, context, &ssl_client_session_cache_,
       &websocket_endpoint_lock_manager_);
   websocket_socket_pool_manager_ = CreateSocketPoolManager(
-      WEBSOCKET_SOCKET_POOL, context, ssl_session_cache_shard,
+      WEBSOCKET_SOCKET_POOL, context, &ssl_client_session_cache_,
       &websocket_endpoint_lock_manager_);
 
   if (params_.enable_http2) {
@@ -490,6 +487,7 @@
     }
     quic_stream_factory_.DumpMemoryStats(
         pmd, http_network_session_dump->absolute_name());
+    ssl_client_session_cache_.DumpMemoryStats(pmd, name);
   }
 
   // Create an empty row under parent's dump so size can be attributed correctly
@@ -509,6 +507,10 @@
   params_.enable_quic = false;
 }
 
+void HttpNetworkSession::ClearSSLSessionCache() {
+  ssl_client_session_cache_.Flush();
+}
+
 ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
     SocketPoolType pool_type) {
   switch (pool_type) {
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 4310ef4..e38e051b 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -35,6 +35,7 @@
 #include "net/socket/websocket_endpoint_lock_manager.h"
 #include "net/spdy/spdy_session_pool.h"
 #include "net/ssl/ssl_client_auth_cache.h"
+#include "net/ssl/ssl_client_session_cache.h"
 #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
 
 namespace base {
@@ -375,6 +376,9 @@
   // Disable QUIC for new streams.
   void DisableQuic();
 
+  // Clear the SSL session cache.
+  void ClearSSLSessionCache();
+
  private:
   friend class HttpNetworkSessionPeer;
 
@@ -398,6 +402,7 @@
 
   HttpAuthCache http_auth_cache_;
   SSLClientAuthCache ssl_client_auth_cache_;
+  SSLClientSessionCache ssl_client_session_cache_;
   WebSocketEndpointLockManager websocket_endpoint_lock_manager_;
   std::unique_ptr<ClientSocketPoolManager> normal_socket_pool_manager_;
   std::unique_ptr<ClientSocketPoolManager> websocket_socket_pool_manager_;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index d269eb84..40ec06b 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -724,7 +724,7 @@
                           NULL,
                           NULL,
                           NULL,
-                          std::string(),
+                          NULL,
                           NULL,
                           NULL,
                           NULL,
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 2fb6f3a..20372b6 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -93,7 +93,7 @@
                          NULL /* transport_security_state */,
                          NULL /* cert_transparency_verifier */,
                          NULL /* ct_policy_enforcer */,
-                         std::string() /* ssl_session_cache_shard */,
+                         NULL /* ssl_client_session_cache */,
                          &socket_factory_,
                          &transport_socket_pool_,
                          NULL /* socks_pool */,
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index c43a683..9d4471da6 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -504,14 +504,14 @@
                           transport_security_state,
                           cert_transparency_verifier,
                           ct_policy_enforcer,
-                          std::string(),  // ssl_session_cache_shard
-                          nullptr,        // deterministic_socket_factory
-                          nullptr,        // transport_socket_pool
-                          nullptr,        // socks_pool
-                          nullptr,        // http_proxy_pool
-                          nullptr,        // ssl_config_service
-                          nullptr,        // network_quality_estimator
-                          nullptr),       // net_log
+                          nullptr,   // ssl_client_session_cache
+                          nullptr,   // deterministic_socket_factory
+                          nullptr,   // transport_socket_pool
+                          nullptr,   // socks_pool
+                          nullptr,   // http_proxy_pool
+                          nullptr,   // ssl_config_service
+                          nullptr,   // network_quality_estimator
+                          nullptr),  // net_log
       last_num_streams_(-1) {}
 
 using HttpStreamFactoryTest = TestWithScopedTaskEnvironment;
diff --git a/net/proxy_resolution/mock_proxy_host_resolver.cc b/net/proxy_resolution/mock_proxy_host_resolver.cc
new file mode 100644
index 0000000..d124c1e6
--- /dev/null
+++ b/net/proxy_resolution/mock_proxy_host_resolver.cc
@@ -0,0 +1,135 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/proxy_resolution/mock_proxy_host_resolver.h"
+
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/base/completion_once_callback.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+class MockProxyHostResolver::RequestImpl
+    : public Request,
+      public base::SupportsWeakPtr<RequestImpl> {
+ public:
+  RequestImpl(std::vector<IPAddress> results, bool synchronous_mode)
+      : results_(std::move(results)), synchronous_mode_(synchronous_mode) {}
+  ~RequestImpl() override = default;
+
+  int Start(CompletionOnceCallback callback) override {
+    if (!synchronous_mode_) {
+      callback_ = std::move(callback);
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(&RequestImpl::SendResults, AsWeakPtr()));
+      return ERR_IO_PENDING;
+    }
+
+    if (results_.empty())
+      return ERR_NAME_NOT_RESOLVED;
+
+    return OK;
+  }
+
+  const std::vector<IPAddress>& GetResults() const override {
+    DCHECK(!callback_);
+    return results_;
+  }
+
+ private:
+  void SendResults() {
+    if (results_.empty())
+      std::move(callback_).Run(ERR_NAME_NOT_RESOLVED);
+    else
+      std::move(callback_).Run(OK);
+  }
+
+  const std::vector<IPAddress> results_;
+  const bool synchronous_mode_;
+
+  CompletionOnceCallback callback_;
+};
+
+MockProxyHostResolver::MockProxyHostResolver(bool synchronous_mode)
+    : num_resolve_(0), fail_all_(false), synchronous_mode_(synchronous_mode) {}
+
+MockProxyHostResolver::~MockProxyHostResolver() = default;
+
+std::unique_ptr<ProxyHostResolver::Request>
+MockProxyHostResolver::CreateRequest(
+    const std::string& hostname,
+    ProxyResolverV8::JSBindings::ResolveDnsOperation operation) {
+  ++num_resolve_;
+
+  if (fail_all_)
+    return std::make_unique<RequestImpl>(std::vector<IPAddress>(),
+                                         synchronous_mode_);
+
+  auto match = results_.find({hostname, operation});
+  if (match == results_.end())
+    return std::make_unique<RequestImpl>(
+        std::vector<IPAddress>({IPAddress(127, 0, 0, 1)}), synchronous_mode_);
+
+  return std::make_unique<RequestImpl>(match->second, synchronous_mode_);
+}
+
+void MockProxyHostResolver::SetError(
+    const std::string& hostname,
+    ProxyResolverV8::JSBindings::ResolveDnsOperation operation) {
+  fail_all_ = false;
+  results_[{hostname, operation}].clear();
+}
+
+void MockProxyHostResolver::SetResult(
+    const std::string& hostname,
+    ProxyResolverV8::JSBindings::ResolveDnsOperation operation,
+    std::vector<IPAddress> result) {
+  DCHECK(!result.empty());
+  fail_all_ = false;
+  results_[{hostname, operation}] = std::move(result);
+}
+
+void MockProxyHostResolver::FailAll() {
+  results_.clear();
+  fail_all_ = true;
+}
+
+class HangingProxyHostResolver::RequestImpl : public Request {
+ public:
+  explicit RequestImpl(HangingProxyHostResolver* resolver)
+      : resolver_(resolver) {}
+  ~RequestImpl() override { ++resolver_->num_cancelled_requests_; }
+
+  int Start(CompletionOnceCallback callback) override {
+    if (resolver_->hang_callback_)
+      resolver_->hang_callback_.Run();
+    return ERR_IO_PENDING;
+  }
+
+  const std::vector<IPAddress>& GetResults() const override {
+    IMMEDIATE_CRASH();
+  }
+
+ private:
+  HangingProxyHostResolver* resolver_;
+};
+
+HangingProxyHostResolver::HangingProxyHostResolver(
+    base::RepeatingClosure hang_callback)
+    : num_cancelled_requests_(0), hang_callback_(std::move(hang_callback)) {}
+
+HangingProxyHostResolver::~HangingProxyHostResolver() = default;
+
+std::unique_ptr<ProxyHostResolver::Request>
+HangingProxyHostResolver::CreateRequest(
+    const std::string& hostname,
+    ProxyResolverV8::JSBindings::ResolveDnsOperation operation) {
+  return std::make_unique<RequestImpl>(this);
+}
+
+}  // namespace net
diff --git a/net/proxy_resolution/mock_proxy_host_resolver.h b/net/proxy_resolution/mock_proxy_host_resolver.h
new file mode 100644
index 0000000..62598c3
--- /dev/null
+++ b/net/proxy_resolution/mock_proxy_host_resolver.h
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_PROXY_RESOLUTION_MOCK_PROXY_HOST_RESOLVER_H_
+#define NET_PROXY_RESOLUTION_MOCK_PROXY_HOST_RESOLVER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "net/base/ip_address.h"
+#include "net/proxy_resolution/proxy_host_resolver.h"
+#include "net/proxy_resolution/proxy_resolver_v8.h"
+
+namespace net {
+
+// Mock of ProxyHostResolver that resolves by default to 127.0.0.1, except for
+// hostnames with more specific results set using SetError() or SetResult().
+// Also allows returning failure for all results with FailAll().
+class MockProxyHostResolver : public ProxyHostResolver {
+ public:
+  // If |synchronous_mode| set to |true|, all results will be returned
+  // synchronously.  Otherwise, all results will be asynchronous.
+  explicit MockProxyHostResolver(bool synchronous_mode = false);
+  ~MockProxyHostResolver() override;
+
+  std::unique_ptr<Request> CreateRequest(
+      const std::string& hostname,
+      ProxyResolverV8::JSBindings::ResolveDnsOperation operation) override;
+
+  void SetError(const std::string& hostname,
+                ProxyResolverV8::JSBindings::ResolveDnsOperation operation);
+
+  void SetResult(const std::string& hostname,
+                 ProxyResolverV8::JSBindings::ResolveDnsOperation operation,
+                 std::vector<IPAddress> result);
+
+  void FailAll();
+
+  unsigned num_resolve() const { return num_resolve_; }
+
+ private:
+  using ResultKey =
+      std::pair<std::string, ProxyResolverV8::JSBindings::ResolveDnsOperation>;
+
+  class RequestImpl;
+
+  // Any entry with an empty value signifies an ERR_NAME_NOT_RESOLVED result.
+  std::map<ResultKey, std::vector<IPAddress>> results_;
+  unsigned num_resolve_;
+  bool fail_all_;
+  bool synchronous_mode_;
+};
+
+// Mock of ProxyHostResolver that always hangs until cancelled.
+class HangingProxyHostResolver : public ProxyHostResolver {
+ public:
+  // If not null, |hang_callback| will be invoked whenever a request is started.
+  HangingProxyHostResolver(
+      base::RepeatingClosure hang_callback = base::RepeatingClosure());
+  ~HangingProxyHostResolver() override;
+
+  std::unique_ptr<Request> CreateRequest(
+      const std::string& hostname,
+      ProxyResolverV8::JSBindings::ResolveDnsOperation operation) override;
+
+  int num_cancelled_requests() const { return num_cancelled_requests_; }
+
+  void set_hang_callback(base::RepeatingClosure hang_callback) {
+    hang_callback_ = hang_callback;
+  }
+
+ private:
+  class RequestImpl;
+
+  int num_cancelled_requests_;
+  base::RepeatingClosure hang_callback_;
+};
+
+}  // namespace net
+
+#endif  // NET_PROXY_RESOLUTION_MOCK_PROXY_HOST_RESOLVER_H_
diff --git a/net/proxy_resolution/pac_library_unittest.cc b/net/proxy_resolution/pac_library_unittest.cc
index 67642c02..0c44e91 100644
--- a/net/proxy_resolution/pac_library_unittest.cc
+++ b/net/proxy_resolution/pac_library_unittest.cc
@@ -276,10 +276,6 @@
     ADD_FAILURE() << "Called CreateProxyClientSocket()";
     return nullptr;
   }
-  void ClearSSLSessionCache() override {
-    ADD_FAILURE() << "Called ClearSSLSessionCache()";
-  }
-
  private:
   std::vector<std::unique_ptr<MockUDPSocket>> udp_sockets_;
 
diff --git a/net/proxy_resolution/proxy_host_resolver.h b/net/proxy_resolution/proxy_host_resolver.h
new file mode 100644
index 0000000..2f32efb
--- /dev/null
+++ b/net/proxy_resolution/proxy_host_resolver.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_PROXY_RESOLUTION_PROXY_HOST_RESOLVER_H_
+#define NET_PROXY_RESOLUTION_PROXY_HOST_RESOLVER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "net/base/completion_once_callback.h"
+#include "net/base/ip_address.h"
+#include "net/proxy_resolution/proxy_resolver_v8.h"
+
+namespace net {
+
+// Interface for a limited (compared to the standard HostResolver) host resolver
+// used just for proxy resolution.
+class NET_EXPORT ProxyHostResolver {
+ public:
+  virtual ~ProxyHostResolver() {}
+
+  class Request {
+   public:
+    virtual ~Request() {}
+    virtual int Start(CompletionOnceCallback callback) = 0;
+    virtual const std::vector<IPAddress>& GetResults() const = 0;
+  };
+
+  virtual std::unique_ptr<Request> CreateRequest(
+      const std::string& hostname,
+      ProxyResolverV8::JSBindings::ResolveDnsOperation operation) = 0;
+};
+
+}  // namespace net
+
+#endif  // NET_PROXY_RESOLUTION_PROXY_HOST_RESOLVER_H_
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index de98df3..66a2d45 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -8,7 +8,6 @@
 
 #include "base/lazy_instance.h"
 #include "build/build_config.h"
-#include "net/cert/cert_database.h"
 #include "net/http/http_proxy_client_socket.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/ssl_client_socket_impl.h"
@@ -21,23 +20,12 @@
 
 namespace {
 
-class DefaultClientSocketFactory : public ClientSocketFactory,
-                                   public CertDatabase::Observer {
+class DefaultClientSocketFactory : public ClientSocketFactory {
  public:
-  DefaultClientSocketFactory() {
-    CertDatabase::GetInstance()->AddObserver(this);
-  }
+  DefaultClientSocketFactory() {}
 
-  ~DefaultClientSocketFactory() override {
-    // Note: This code never runs, as the factory is defined as a Leaky
-    // singleton.
-    CertDatabase::GetInstance()->RemoveObserver(this);
-  }
-
-  void OnCertDBChanged() override {
-    // Flush sockets whenever CA trust changes.
-    ClearSSLSessionCache();
-  }
+  // Note: This code never runs, as the factory is defined as a Leaky singleton.
+  ~DefaultClientSocketFactory() override {}
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
@@ -82,8 +70,6 @@
         http_auth_controller, tunnel, using_spdy, negotiated_protocol,
         proxy_delegate, is_https_proxy, traffic_annotation);
   }
-
-  void ClearSSLSessionCache() override { SSLClientSocket::ClearSessionCache(); }
 };
 
 static base::LazyInstance<DefaultClientSocketFactory>::Leaky
diff --git a/net/socket/client_socket_factory.h b/net/socket/client_socket_factory.h
index 6123167..4d72619 100644
--- a/net/socket/client_socket_factory.h
+++ b/net/socket/client_socket_factory.h
@@ -72,9 +72,6 @@
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) = 0;
 
-  // Clears cache used for SSL session resumption.
-  virtual void ClearSSLSessionCache() = 0;
-
   // Returns the default ClientSocketFactory.
   static ClientSocketFactory* GetDefaultFactory();
 };
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index d4720ae..8816f82a1 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -256,8 +256,6 @@
     return nullptr;
   }
 
-  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
-
   void WaitForSignal(TestConnectJob* job) { waiting_jobs_.push_back(job); }
 
   void SignalJobs();
diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc
index 4edeb48..8a7f10b 100644
--- a/net/socket/client_socket_pool_manager_impl.cc
+++ b/net/socket/client_socket_pool_manager_impl.cc
@@ -50,7 +50,7 @@
     TransportSecurityState* transport_security_state,
     CTVerifier* cert_transparency_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
-    const std::string& ssl_session_cache_shard,
+    SSLClientSessionCache* ssl_client_session_cache,
     SSLConfigService* ssl_config_service,
     WebSocketEndpointLockManager* websocket_endpoint_lock_manager,
     ProxyDelegate* proxy_delegate,
@@ -65,7 +65,7 @@
       transport_security_state_(transport_security_state),
       cert_transparency_verifier_(cert_transparency_verifier),
       ct_policy_enforcer_(ct_policy_enforcer),
-      ssl_session_cache_shard_(ssl_session_cache_shard),
+      ssl_client_session_cache_(ssl_client_session_cache),
       ssl_config_service_(ssl_config_service),
       proxy_delegate_(proxy_delegate),
       pool_type_(pool_type),
@@ -81,7 +81,7 @@
                                        transport_security_state,
                                        cert_transparency_verifier,
                                        ct_policy_enforcer,
-                                       ssl_session_cache_shard,
+                                       ssl_session_cache_shard_,
                                        ssl_config_service,
                                        network_quality_estimator,
                                        websocket_endpoint_lock_manager,
@@ -96,7 +96,7 @@
                                        transport_security_state,
                                        cert_transparency_verifier,
                                        ct_policy_enforcer,
-                                       ssl_session_cache_shard,
+                                       ssl_session_cache_shard_,
                                        ssl_config_service,
                                        socket_performance_watcher_factory_,
                                        network_quality_estimator,
@@ -108,7 +108,7 @@
                                                transport_security_state,
                                                cert_transparency_verifier,
                                                ct_policy_enforcer,
-                                               ssl_session_cache_shard,
+                                               ssl_client_session_cache,
                                                socket_factory,
                                                transport_socket_pool_.get(),
                                                nullptr /* no socks proxy */,
@@ -281,7 +281,7 @@
               sockets_per_proxy_server, sockets_per_group, cert_verifier_,
               channel_id_service_, transport_security_state_,
               cert_transparency_verifier_, ct_policy_enforcer_,
-              ssl_session_cache_shard_, socket_factory_,
+              ssl_client_session_cache_, socket_factory_,
               tcp_https_ret.first->second.get() /* https proxy */,
               nullptr /* no socks proxy */, nullptr /* no http proxy */,
               ssl_config_service_, network_quality_estimator_, net_log_)));
@@ -316,7 +316,7 @@
               sockets_per_proxy_server, sockets_per_group, cert_verifier_,
               channel_id_service_, transport_security_state_,
               cert_transparency_verifier_, ct_policy_enforcer_,
-              ssl_session_cache_shard_, socket_factory_,
+              ssl_client_session_cache_, socket_factory_,
               nullptr, /* no tcp pool, we always go through a proxy */
               proxy_server.is_socks() ? GetSocketPoolForSOCKSProxy(proxy_server)
                                       : nullptr,
diff --git a/net/socket/client_socket_pool_manager_impl.h b/net/socket/client_socket_pool_manager_impl.h
index e8f3fa2..66650fd 100644
--- a/net/socket/client_socket_pool_manager_impl.h
+++ b/net/socket/client_socket_pool_manager_impl.h
@@ -38,6 +38,7 @@
 class ProxyDelegate;
 class ProxyServer;
 class SocketPerformanceWatcherFactory;
+class SSLClientSessionCache;
 class SSLClientSocketPool;
 class SSLConfigService;
 class TransportClientSocketPool;
@@ -59,7 +60,7 @@
       TransportSecurityState* transport_security_state,
       CTVerifier* cert_transparency_verifier,
       CTPolicyEnforcer* ct_policy_enforcer,
-      const std::string& ssl_session_cache_shard,
+      SSLClientSessionCache* ssl_client_session_cache,
       SSLConfigService* ssl_config_service,
       WebSocketEndpointLockManager* websocket_endpoint_lock_manager,
       ProxyDelegate* proxy_delegate,
@@ -110,6 +111,7 @@
   TransportSecurityState* const transport_security_state_;
   CTVerifier* const cert_transparency_verifier_;
   CTPolicyEnforcer* const ct_policy_enforcer_;
+  SSLClientSessionCache* const ssl_client_session_cache_;
   const std::string ssl_session_cache_shard_;
   SSLConfigService* const ssl_config_service_;
   ProxyDelegate* const proxy_delegate_;
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc
index 136072cc..21cd1656 100644
--- a/net/socket/fuzzed_socket_factory.cc
+++ b/net/socket/fuzzed_socket_factory.cc
@@ -168,6 +168,4 @@
   return nullptr;
 }
 
-void FuzzedSocketFactory::ClearSSLSessionCache() {}
-
 }  // namespace net
diff --git a/net/socket/fuzzed_socket_factory.h b/net/socket/fuzzed_socket_factory.h
index 46153a7..3f179727 100644
--- a/net/socket/fuzzed_socket_factory.h
+++ b/net/socket/fuzzed_socket_factory.h
@@ -65,8 +65,6 @@
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
 
-  void ClearSSLSessionCache() override;
-
   // Sets whether Connect()ions on returned sockets can be asynchronously
   // delayed or outright fail. Defaults to true.
   void set_fuzz_connect_result(bool v) { fuzz_connect_result_ = v; }
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 646a5a5..1c7e378d 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -816,9 +816,6 @@
   }
 }
 
-void MockClientSocketFactory::ClearSSLSessionCache() {
-}
-
 MockClientSocket::MockClientSocket(const NetLogWithSource& net_log)
     : connected_(false), net_log_(net_log), weak_factory_(this) {
   local_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 123);
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index f9d53ce..2cb7d900 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -639,8 +639,6 @@
       ProxyDelegate* proxy_delegate,
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
-  void ClearSSLSessionCache() override;
-
   const std::vector<uint16_t>& udp_client_socket_ports() const {
     return udp_client_socket_ports_;
   }
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index 79b89f2..c514674 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -25,6 +25,7 @@
 class CertVerifier;
 class ChannelIDService;
 class CTVerifier;
+class SSLClientSessionCache;
 class SSLKeyLogger;
 class TransportSecurityState;
 
@@ -37,12 +38,14 @@
                          TransportSecurityState* transport_security_state_arg,
                          CTVerifier* cert_transparency_verifier_arg,
                          CTPolicyEnforcer* ct_policy_enforcer_arg,
+                         SSLClientSessionCache* ssl_client_session_cache_arg,
                          const std::string& ssl_session_cache_shard_arg)
       : cert_verifier(cert_verifier_arg),
         channel_id_service(channel_id_service_arg),
         transport_security_state(transport_security_state_arg),
         cert_transparency_verifier(cert_transparency_verifier_arg),
         ct_policy_enforcer(ct_policy_enforcer_arg),
+        ssl_client_session_cache(ssl_client_session_cache_arg),
         ssl_session_cache_shard(ssl_session_cache_shard_arg) {}
 
   CertVerifier* cert_verifier = nullptr;
@@ -50,6 +53,7 @@
   TransportSecurityState* transport_security_state = nullptr;
   CTVerifier* cert_transparency_verifier = nullptr;
   CTPolicyEnforcer* ct_policy_enforcer = nullptr;
+  SSLClientSessionCache* ssl_client_session_cache = nullptr;
   // ssl_session_cache_shard is an opaque string that identifies a shard of the
   // SSL session cache. SSL sockets with the same ssl_session_cache_shard may
   // resume each other's SSL sessions but we'll never sessions between shards.
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index 59e931a..0533c90 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -24,7 +24,6 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
-#include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
 #include "crypto/ec_private_key.h"
@@ -273,7 +272,6 @@
                            base::LeakySingletonTraits<SSLContext>>::get();
   }
   SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
-  SSLClientSessionCache* session_cache() { return &session_cache_; }
 
   SSLClientSocketImpl* GetClientSocketFromSSL(const SSL* ssl) {
     DCHECK(ssl);
@@ -298,7 +296,7 @@
  private:
   friend struct base::DefaultSingletonTraits<SSLContext>;
 
-  SSLContext() : session_cache_(SSLClientSessionCache::Config()) {
+  SSLContext() {
     crypto::EnsureOpenSSLInit();
     ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
     DCHECK_NE(ssl_socket_data_index_, -1);
@@ -395,13 +393,6 @@
   bssl::UniquePtr<SSL_CTX> ssl_ctx_;
 
   std::unique_ptr<SSLKeyLogger> ssl_key_logger_;
-
-  // TODO(davidben): Use a separate cache per URLRequestContext.
-  // https://crbug.com/458365
-  //
-  // TODO(davidben): Sessions should be invalidated on fatal
-  // alerts. https://crbug.com/466352
-  SSLClientSessionCache session_cache_;
 };
 
 const SSL_PRIVATE_KEY_METHOD
@@ -411,13 +402,6 @@
         &SSLClientSocketImpl::SSLContext::PrivateKeyCompleteCallback,
 };
 
-// static
-void SSLClientSocket::ClearSessionCache() {
-  SSLClientSocketImpl::SSLContext* context =
-      SSLClientSocketImpl::SSLContext::GetInstance();
-  context->session_cache()->Flush();
-}
-
 SSLClientSocketImpl::SSLClientSocketImpl(
     std::unique_ptr<ClientSocketHandle> transport_socket,
     const HostPortPair& host_and_port,
@@ -433,6 +417,7 @@
       transport_(std::move(transport_socket)),
       host_and_port_(host_and_port),
       ssl_config_(ssl_config),
+      ssl_client_session_cache_(context.ssl_client_session_cache),
       ssl_session_cache_shard_(context.ssl_session_cache_shard),
       next_handshake_state_(STATE_NONE),
       in_confirm_handshake_(false),
@@ -709,12 +694,6 @@
   return transport_->socket()->ApplySocketTag(tag);
 }
 
-// static
-void SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(
-    base::trace_event::ProcessMemoryDump* pmd) {
-  SSLContext::GetInstance()->session_cache()->DumpMemoryStats(pmd);
-}
-
 int SSLClientSocketImpl::Read(IOBuffer* buf,
                               int buf_len,
                               CompletionOnceCallback callback) {
@@ -817,9 +796,9 @@
     return ERR_UNEXPECTED;
   }
 
-  if (!ssl_session_cache_shard_.empty()) {
+  if (IsCachingEnabled()) {
     bssl::UniquePtr<SSL_SESSION> session =
-        context->session_cache()->Lookup(GetSessionCacheKey());
+        ssl_client_session_cache_->Lookup(GetSessionCacheKey());
     if (session)
       SSL_set_session(ssl_.get(), session.get());
   }
@@ -990,9 +969,8 @@
     return ERR_SSL_VERSION_INTERFERENCE;
   }
 
-  if (!ssl_session_cache_shard_.empty()) {
-    SSLContext::GetInstance()->session_cache()->ResetLookupCount(
-        GetSessionCacheKey());
+  if (IsCachingEnabled()) {
+    ssl_client_session_cache_->ResetLookupCount(GetSessionCacheKey());
   }
 
   const uint8_t* alpn_proto = NULL;
@@ -1623,14 +1601,12 @@
   return 1;
 }
 
-// Returns whether we took ownership of the pointer.
 int SSLClientSocketImpl::NewSessionCallback(SSL_SESSION* session) {
-  if (ssl_session_cache_shard_.empty())
+  if (!IsCachingEnabled())
     return 0;
 
   // OpenSSL passes a reference to |session|.
-  SSLContext::GetInstance()->session_cache()->Insert(GetSessionCacheKey(),
-                                                     session);
+  ssl_client_session_cache_->Insert(GetSessionCacheKey(), session);
   return 0;
 }
 
@@ -1639,11 +1615,6 @@
 }
 
 std::string SSLClientSocketImpl::GetSessionCacheKey() const {
-  // If there is no session cache shard configured, disable session
-  // caching. GetSessionCacheKey may not be called. When
-  // https://crbug.com/458365 is fixed, this check will not be needed.
-  DCHECK(!ssl_session_cache_shard_.empty());
-
   std::string result = host_and_port_.ToString();
   result.push_back('/');
   result.append(ssl_session_cache_shard_);
@@ -1664,6 +1635,10 @@
   return false;
 }
 
+bool SSLClientSocketImpl::IsCachingEnabled() const {
+  return ssl_client_session_cache_ != nullptr;
+}
+
 ssl_private_key_result_t SSLClientSocketImpl::PrivateKeySignCallback(
     uint8_t* out,
     size_t* out_len,
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h
index ee1b18c..0dda5dd 100644
--- a/net/socket/ssl_client_socket_impl.h
+++ b/net/socket/ssl_client_socket_impl.h
@@ -34,12 +34,6 @@
 #include "third_party/boringssl/src/include/openssl/base.h"
 #include "third_party/boringssl/src/include/openssl/ssl.h"
 
-namespace base {
-namespace trace_event {
-class ProcessMemoryDump;
-}
-}
-
 namespace crypto {
 class OpenSSLErrStackTracer;
 }
@@ -104,10 +98,6 @@
 
   void ApplySocketTag(const SocketTag& tag) override;
 
-  // Dumps memory allocation stats. |pmd| is the browser process memory dump.
-  static void DumpSSLClientSessionMemoryStats(
-      base::trace_event::ProcessMemoryDump* pmd);
-
   // Socket implementation.
   int Read(IOBuffer* buf,
            int buf_len,
@@ -183,6 +173,9 @@
   // Returns true if renegotiations are allowed.
   bool IsRenegotiationAllowed() const;
 
+  // Returns true when we should be using the ssl_client_session_cache_
+  bool IsCachingEnabled() const;
+
   // Callbacks for operations with the private key.
   ssl_private_key_result_t PrivateKeySignCallback(uint8_t* out,
                                                   size_t* out_len,
@@ -272,6 +265,8 @@
   std::unique_ptr<SocketBIOAdapter> transport_adapter_;
   const HostPortPair host_and_port_;
   SSLConfig ssl_config_;
+  // ssl_client_session_cache_ is a non-owning pointer to session cache
+  SSLClientSessionCache* ssl_client_session_cache_;
   // ssl_session_cache_shard_ is an opaque string that partitions the SSL
   // session cache. i.e. sessions created with one value will not attempt to
   // resume on the socket with a different value.
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index bb79c46..fe44613d 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -43,7 +43,7 @@
     TransportSecurityState* transport_security_state,
     CTVerifier* cert_transparency_verifier,
     CTPolicyEnforcer* ct_policy_enforcer,
-    const std::string& ssl_session_cache_shard,
+    SSLClientSessionCache* ssl_client_session_cache,
     ClientSocketFactory* client_socket_factory,
     TransportClientSocketPool* transport_pool,
     TransportClientSocketPool* socks_pool,
@@ -69,7 +69,8 @@
                                        transport_security_state,
                                        cert_transparency_verifier,
                                        ct_policy_enforcer,
-                                       ssl_session_cache_shard),
+                                       ssl_client_session_cache,
+                                       "shardkey"),
                 network_quality_estimator,
                 net_log)),
       ssl_config_service_(ssl_config_service) {
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index ec70ef1..682e66d 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -50,7 +50,7 @@
                       TransportSecurityState* transport_security_state,
                       CTVerifier* cert_transparency_verifier,
                       CTPolicyEnforcer* ct_policy_enforcer,
-                      const std::string& ssl_session_cache_shard,
+                      SSLClientSessionCache* ssl_client_session_cache,
                       ClientSocketFactory* client_socket_factory,
                       TransportClientSocketPool* transport_pool,
                       TransportClientSocketPool* socks_pool,
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index f5920a8..820115a 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -107,7 +107,7 @@
         kMaxSockets, kMaxSocketsPerGroup, cert_verifier_.get(),
         NULL /* channel_id_service */, transport_security_state_.get(),
         &ct_verifier_, &ct_policy_enforcer_,
-        std::string() /* ssl_session_cache_shard */, &socket_factory_,
+        nullptr /* ssl_client_session_cache */, &socket_factory_,
         transport_pool ? &transport_socket_pool_ : nullptr, nullptr,
         http_proxy_pool ? &http_proxy_socket_pool_ : nullptr,
         nullptr /* ssl_config_service */,
@@ -273,7 +273,7 @@
                            cert_verifier_.get(), NULL /* channel_id_service */,
                            transport_security_state_.get(), &ct_verifier_,
                            &ct_policy_enforcer_,
-                           std::string() /* ssl_session_cache_shard */,
+                           nullptr /* ssl_client_session_cache */,
                            ClientSocketFactory::GetDefaultFactory(), &tcp_pool,
                            NULL, NULL, NULL, NULL, NULL);
   TestCompletionCallback callback;
@@ -351,7 +351,7 @@
                            cert_verifier_.get(), NULL /* channel_id_service */,
                            transport_security_state_.get(), &ct_verifier_,
                            &ct_policy_enforcer_,
-                           std::string() /* ssl_session_cache_shard */,
+                           nullptr /* ssl_client_session_cache */,
                            ClientSocketFactory::GetDefaultFactory(), &tcp_pool,
                            NULL, NULL, NULL, NULL, NULL);
   ClientSocketHandle handle;
@@ -421,7 +421,7 @@
                            cert_verifier_.get(), NULL /* channel_id_service */,
                            transport_security_state_.get(), &ct_verifier_,
                            &ct_policy_enforcer_,
-                           std::string() /* ssl_session_cache_shard */,
+                           nullptr /* ssl_client_session_cache */,
                            ClientSocketFactory::GetDefaultFactory(), &tcp_pool,
                            NULL, NULL, NULL, NULL, NULL);
   TestCompletionCallback callback;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 10cbb93..9a66192 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -61,6 +61,7 @@
 #include "net/socket/tcp_client_socket.h"
 #include "net/socket/tcp_server_socket.h"
 #include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_client_session_cache.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/ssl/ssl_info.h"
@@ -791,13 +792,16 @@
         cert_verifier_(new MockCertVerifier),
         transport_security_state_(new TransportSecurityState),
         ct_verifier_(new DoNothingCTVerifier),
-        ct_policy_enforcer_(new MockCTPolicyEnforcer) {
+        ct_policy_enforcer_(new MockCTPolicyEnforcer),
+        ssl_client_session_cache_(
+            new SSLClientSessionCache(SSLClientSessionCache::Config())) {
     cert_verifier_->set_default_result(OK);
     context_.cert_verifier = cert_verifier_.get();
     context_.transport_security_state = transport_security_state_.get();
     context_.cert_transparency_verifier = ct_verifier_.get();
     context_.ct_policy_enforcer = ct_policy_enforcer_.get();
-    // Set a dummy session cache shard to enable session caching.
+    // Set a dummy session cache (and shard) to enable session caching.
+    context_.ssl_client_session_cache = ssl_client_session_cache_.get();
     context_.ssl_session_cache_shard = "shard";
 
     EXPECT_CALL(*ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -911,6 +915,7 @@
   std::unique_ptr<TransportSecurityState> transport_security_state_;
   std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
   std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
+  std::unique_ptr<SSLClientSessionCache> ssl_client_session_cache_;
   SSLClientSocketContext context_;
   std::unique_ptr<SSLClientSocket> sock_;
   TestNetLog log_;
@@ -2435,12 +2440,6 @@
   EXPECT_NE(memcmp(client_out1, client_out2, kKeyingMaterialSize), 0);
 }
 
-// Verifies that SSLClientSocket::ClearSessionCache can be called without
-// explicit NSS initialization.
-TEST(SSLClientSocket, ClearSessionCache) {
-  SSLClientSocket::ClearSessionCache();
-}
-
 TEST(SSLClientSocket, SerializeNextProtos) {
   NextProtoVector next_protos;
   next_protos.push_back(kProtoHTTP11);
@@ -3018,7 +3017,7 @@
   EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type);
   sock.reset();
 
-  SSLClientSocket::ClearSessionCache();
+  context_.ssl_client_session_cache->Flush();
 
   // After clearing the session cache, the next handshake doesn't resume.
   ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
@@ -4823,18 +4822,6 @@
   ASSERT_THAT(rv, IsOk());
   ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
   EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type);
-
-  // The empty shard never resumes.
-  context_.ssl_session_cache_shard = "";
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
-  ASSERT_THAT(rv, IsOk());
-  ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
-  EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type);
-
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
-  ASSERT_THAT(rv, IsOk());
-  ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
-  EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type);
 }
 
 TEST_F(SSLClientSocketTest, Tag) {
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc
index b54e232d..b37c478 100644
--- a/net/socket/ssl_connect_job.cc
+++ b/net/socket/ssl_connect_job.cc
@@ -333,7 +333,7 @@
   connect_timing_.ssl_start = base::TimeTicks::Now();
 
   // If privacy mode is enabled and the session shard is non-empty, prefix the
-  // SSL session shard with "pm/"
+  // SSL session shard with "pm/". Otherwise, prefix with "nopm/".
   // TODO(mmenke): Consider moving this up to the socket pool layer, after
   // giving socket pools knowledge of privacy mode.
   SSLClientSocketContext context_with_privacy_mode(
@@ -342,10 +342,9 @@
       ssl_client_socket_context().transport_security_state,
       ssl_client_socket_context().cert_transparency_verifier,
       ssl_client_socket_context().ct_policy_enforcer,
-      (!ssl_client_socket_context().ssl_session_cache_shard.empty() &&
-               params_->privacy_mode() == PRIVACY_MODE_ENABLED
-           ? "pm/" + ssl_client_socket_context().ssl_session_cache_shard
-           : ssl_client_socket_context().ssl_session_cache_shard));
+      ssl_client_socket_context().ssl_client_session_cache,
+      (params_->privacy_mode() == PRIVACY_MODE_ENABLED ? "pm/" : "nopm/") +
+          ssl_client_socket_context().ssl_session_cache_shard);
   ssl_socket_ = client_socket_factory()->CreateSSLClientSocket(
       std::move(transport_socket_handle_), params_->host_and_port(),
       params_->ssl_config(), context_with_privacy_mode);
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc
index d9986d55..24d4c17 100644
--- a/net/socket/ssl_connect_job_unittest.cc
+++ b/net/socket/ssl_connect_job_unittest.cc
@@ -95,6 +95,7 @@
                                    &transport_security_state_,
                                    &ct_verifier_,
                                    &ct_policy_enforcer_,
+                                   nullptr /* ssl_client_session_cache */,
                                    std::string() /* ssl_session_cache_shard */),
         direct_transport_socket_params_(
             new TransportSocketParams(HostPortPair("host", 443),
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 781ba95..48352a7 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -59,6 +59,7 @@
 #include "net/socket/stream_socket.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/ssl/ssl_cipher_suite_names.h"
+#include "net/ssl/ssl_client_session_cache.h"
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/ssl/ssl_info.h"
 #include "net/ssl/ssl_private_key.h"
@@ -361,7 +362,9 @@
         client_cert_verifier_(new MockClientCertVerifier()),
         transport_security_state_(new TransportSecurityState),
         ct_verifier_(new DoNothingCTVerifier),
-        ct_policy_enforcer_(new MockCTPolicyEnforcer) {}
+        ct_policy_enforcer_(new MockCTPolicyEnforcer),
+        ssl_client_session_cache_(
+            new SSLClientSessionCache(SSLClientSessionCache::Config())) {}
 
   void SetUp() override {
     PlatformTest::SetUp();
@@ -427,7 +430,8 @@
     context.transport_security_state = transport_security_state_.get();
     context.cert_transparency_verifier = ct_verifier_.get();
     context.ct_policy_enforcer = ct_policy_enforcer_.get();
-    // Set a dummy session cache shard to enable session caching.
+    // Set a dummy session cache (and shard) to enable session caching.
+    context.ssl_client_session_cache = ssl_client_session_cache_.get();
     context.ssl_session_cache_shard = "shard";
 
     client_socket_ = socket_factory_->CreateSSLClientSocket(
@@ -526,6 +530,7 @@
   std::unique_ptr<TransportSecurityState> transport_security_state_;
   std::unique_ptr<DoNothingCTVerifier> ct_verifier_;
   std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
+  std::unique_ptr<SSLClientSessionCache> ssl_client_session_cache_;
   std::unique_ptr<SSLServerContext> server_context_;
   std::unique_ptr<crypto::RSAPrivateKey> server_private_key_;
   scoped_refptr<SSLPrivateKey> server_ssl_private_key_;
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc
index ae4a224..bc068321 100644
--- a/net/socket/transport_client_socket_pool.cc
+++ b/net/socket/transport_client_socket_pool.cc
@@ -106,6 +106,7 @@
                                        transport_security_state,
                                        cert_transparency_verifier,
                                        ct_policy_enforcer,
+                                       nullptr,
                                        ssl_session_cache_shard),
                 socket_performance_watcher_factory,
                 network_quality_estimator,
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc
index 11bc686..d192fff 100644
--- a/net/socket/transport_client_socket_pool_test_util.cc
+++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -469,10 +469,6 @@
   return nullptr;
 }
 
-void MockTransportClientSocketFactory::ClearSSLSessionCache() {
-  NOTIMPLEMENTED();
-}
-
 void MockTransportClientSocketFactory::set_client_socket_types(
     ClientSocketType* type_list,
     int num_types) {
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h
index e4213ea5..da6146cd 100644
--- a/net/socket/transport_client_socket_pool_test_util.h
+++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -104,8 +104,6 @@
       bool is_https_proxy,
       const NetworkTrafficAnnotationTag& traffic_annotation) override;
 
-  void ClearSSLSessionCache() override;
-
   int allocation_count() const { return allocation_count_; }
 
   // Set the default ClientSocketType.
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc
index 98833df..b5061c51 100644
--- a/net/socket/websocket_transport_client_socket_pool.cc
+++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -64,6 +64,7 @@
                                  transport_security_state,
                                  cert_transparency_verifier,
                                  ct_policy_enforcer,
+                                 nullptr,
                                  ssl_session_cache_shard),
       network_quality_estimator_(network_quality_estimator),
       websocket_endpoint_lock_manager_(websocket_endpoint_lock_manager),
diff --git a/net/ssl/ssl_client_session_cache.cc b/net/ssl/ssl_client_session_cache.cc
index 4541bbf..bd9d463 100644
--- a/net/ssl/ssl_client_session_cache.cc
+++ b/net/ssl/ssl_client_session_cache.cc
@@ -22,9 +22,15 @@
       lookups_since_flush_(0) {
   memory_pressure_listener_.reset(new base::MemoryPressureListener(base::Bind(
       &SSLClientSessionCache::OnMemoryPressure, base::Unretained(this))));
+  CertDatabase::GetInstance()->AddObserver(this);
 }
 
 SSLClientSessionCache::~SSLClientSessionCache() {
+  CertDatabase::GetInstance()->RemoveObserver(this);
+  Flush();
+}
+
+void SSLClientSessionCache::OnCertDBChanged() {
   Flush();
 }
 
@@ -34,8 +40,6 @@
 
 bssl::UniquePtr<SSL_SESSION> SSLClientSessionCache::Lookup(
     const std::string& cache_key) {
-  base::AutoLock lock(lock_);
-
   // Expire stale sessions.
   lookups_since_flush_++;
   if (lookups_since_flush_ >= config_.expiration_check_count) {
@@ -58,8 +62,6 @@
 }
 
 void SSLClientSessionCache::ResetLookupCount(const std::string& cache_key) {
-  base::AutoLock lock(lock_);
-
   // It's possible that the cached session for this key was deleted after the
   // Lookup. If that's the case, don't do anything.
   auto iter = cache_.Get(cache_key);
@@ -69,8 +71,6 @@
 
 void SSLClientSessionCache::Insert(const std::string& cache_key,
                                    SSL_SESSION* session) {
-  base::AutoLock lock(lock_);
-
   auto iter = cache_.Get(cache_key);
   if (iter == cache_.end())
     iter = cache_.Put(cache_key, Entry());
@@ -78,8 +78,6 @@
 }
 
 void SSLClientSessionCache::Flush() {
-  base::AutoLock lock(lock_);
-
   cache_.Clear();
 }
 
@@ -97,17 +95,11 @@
 }
 
 void SSLClientSessionCache::DumpMemoryStats(
-    base::trace_event::ProcessMemoryDump* pmd) {
-  std::string absolute_name = "net/ssl_session_cache";
+    base::trace_event::ProcessMemoryDump* pmd,
+    const std::string& parent_absolute_name) const {
+  std::string name = parent_absolute_name + "/ssl_client_session_cache";
   base::trace_event::MemoryAllocatorDump* cache_dump =
-      pmd->GetAllocatorDump(absolute_name);
-  // This method can be reached from different URLRequestContexts. Since this is
-  // a singleton, only log memory stats once.
-  // TODO(xunjieli): Change this once crbug.com/458365 is fixed.
-  if (cache_dump)
-    return;
-  cache_dump = pmd->CreateAllocatorDump(absolute_name);
-  base::AutoLock lock(lock_);
+      pmd->CreateAllocatorDump(name);
   size_t cert_size = 0;
   size_t cert_count = 0;
   size_t undeduped_cert_size = 0;
diff --git a/net/ssl/ssl_client_session_cache.h b/net/ssl/ssl_client_session_cache.h
index 7002ab5..784a6f90 100644
--- a/net/ssl/ssl_client_session_cache.h
+++ b/net/ssl/ssl_client_session_cache.h
@@ -15,10 +15,10 @@
 #include "base/containers/mru_cache.h"
 #include "base/macros.h"
 #include "base/memory/memory_pressure_monitor.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
+#include "base/trace_event/memory_dump_provider.h"
 #include "net/base/net_export.h"
+#include "net/cert/cert_database.h"
 #include "third_party/boringssl/src/include/openssl/base.h"
 
 namespace base {
@@ -30,7 +30,7 @@
 
 namespace net {
 
-class NET_EXPORT SSLClientSessionCache {
+class NET_EXPORT SSLClientSessionCache : public CertDatabase::Observer {
  public:
   struct Config {
     // The maximum number of entries in the cache.
@@ -40,7 +40,9 @@
   };
 
   explicit SSLClientSessionCache(const Config& config);
-  ~SSLClientSessionCache();
+  ~SSLClientSessionCache() override;
+
+  void OnCertDBChanged() override;
 
   // Returns true if |entry| is expired as of |now|.
   static bool IsExpired(SSL_SESSION* session, time_t now);
@@ -67,7 +69,8 @@
 
   // Dumps memory allocation stats. |pmd| is the ProcessMemoryDump of the
   // browser process.
-  void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd);
+  void DumpMemoryStats(base::trace_event::ProcessMemoryDump* pmd,
+                       const std::string& parent_absolute_name) const;
 
  private:
   struct Entry {
@@ -87,7 +90,7 @@
     // deleted.
     bool ExpireSessions(time_t now);
 
-    bssl::UniquePtr<SSL_SESSION> sessions[2] = {nullptr};
+    bssl::UniquePtr<SSL_SESSION> sessions[2];
   };
 
   // Removes all expired sessions from the cache.
@@ -101,12 +104,6 @@
   Config config_;
   base::HashingMRUCache<std::string, Entry> cache_;
   size_t lookups_since_flush_;
-
-  // TODO(davidben): After https://crbug.com/458365 is fixed, replace this with
-  // a ThreadChecker. The session cache should be single-threaded like other
-  // classes in net.
-  base::Lock lock_;
-
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLClientSessionCache);
diff --git a/net/ssl/ssl_client_session_cache_unittest.cc b/net/ssl/ssl_client_session_cache_unittest.cc
index adb1382b..ef1eac24 100644
--- a/net/ssl/ssl_client_session_cache_unittest.cc
+++ b/net/ssl/ssl_client_session_cache_unittest.cc
@@ -435,11 +435,17 @@
   base::trace_event::MemoryDumpArgs dump_args = {GetParam()};
   std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump(
       new base::trace_event::ProcessMemoryDump(dump_args));
-  cache.DumpMemoryStats(process_memory_dump.get());
+
+  const std::string parent_absolute_name =
+      "net/http_network_session_0xdeadbeef";
+  const std::string expected_dump_name =
+      parent_absolute_name + "/ssl_client_session_cache";
+
+  cache.DumpMemoryStats(process_memory_dump.get(), parent_absolute_name);
 
   using Entry = base::trace_event::MemoryAllocatorDump::Entry;
   const base::trace_event::MemoryAllocatorDump* dump =
-      process_memory_dump->GetAllocatorDump("net/ssl_session_cache");
+      process_memory_dump->GetAllocatorDump(expected_dump_name);
   ASSERT_NE(nullptr, dump);
   const std::vector<Entry>& entries = dump->entries();
   EXPECT_THAT(entries, Contains(Field(&Entry::name, Eq("cert_count"))));
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 74d2c25..f4fe7c4 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -156,8 +156,6 @@
 bool URLRequestContext::OnMemoryDump(
     const base::trace_event::MemoryDumpArgs& args,
     base::trace_event::ProcessMemoryDump* pmd) {
-  SSLClientSocketImpl::DumpSSLClientSessionMemoryStats(pmd);
-
   std::string dump_name =
       base::StringPrintf("net/url_request_context/%s/0x%" PRIxPTR,
                          name_.c_str(), reinterpret_cast<uintptr_t>(this));
diff --git a/net/url_request/url_request_context_unittest.cc b/net/url_request/url_request_context_unittest.cc
index 68e54e148..642c22f 100644
--- a/net/url_request/url_request_context_unittest.cc
+++ b/net/url_request/url_request_context_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/url_request/url_request_context.h"
 
+#include "base/strings/pattern.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
@@ -47,7 +48,9 @@
     const std::string& dump_name = it.first;
     if (dump_name.find("net/http_network_session") != std::string::npos)
       did_dump_http_network_session = true;
-    if (dump_name.find("net/ssl_session_cache") != std::string::npos)
+    // Match against a relaxed form of the memory dump whitelist pattern.
+    if (base::MatchPattern(
+            dump_name, "net/http_network_session_0x*/ssl_client_session_cache"))
       did_dump_ssl_client_session_cache = true;
     if (dump_name.find("net/url_request_context") != std::string::npos) {
       // A sub allocator dump to take into account of the sharing relationship.
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 47c52540..ca738bd 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -9797,7 +9797,9 @@
   default_context_.http_transaction_factory()
       ->GetSession()
       ->CloseAllConnections();
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   // Connecting again should not call OnCertificateRequested. The identity is
   // taken from the client auth cache.
@@ -9877,7 +9879,9 @@
   default_context_.http_transaction_factory()
       ->GetSession()
       ->CloseAllConnections();
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   // The bad identity should have been evicted from the cache, so connecting
   // again should call OnCertificateRequested again.
@@ -9955,7 +9959,9 @@
   default_context_.http_transaction_factory()
       ->GetSession()
       ->CloseAllConnections();
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   // Cause the private key to fail. Connecting again should attempt to use it,
   // notice the failure, and then request a new identity via
@@ -9996,7 +10002,9 @@
       base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
   ASSERT_TRUE(test_server.Start());
 
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   {
     TestDelegate d;
@@ -10069,7 +10077,9 @@
       base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
   ASSERT_TRUE(test_server.Start());
 
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   {
     TestDelegate d;
@@ -10249,7 +10259,9 @@
       base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
   ASSERT_TRUE(test_server.Start());
 
-  SSLClientSocket::ClearSessionCache();
+  default_context_.http_transaction_factory()
+      ->GetSession()
+      ->ClearSSLSessionCache();
 
   // Simulate the certificate being expired and attempt a connection.
   cert_verifier_.set_default_result(ERR_CERT_DATE_INVALID);
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc
index 747f7b7..335d743 100644
--- a/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -69,7 +69,7 @@
             nullptr,
             nullptr,
             nullptr,
-            "test_shard",
+            nullptr,
             nullptr,
             &websocket_endpoint_lock_manager_,
             nullptr,
diff --git a/services/audio/input_controller_unittest.cc b/services/audio/input_controller_unittest.cc
index 9a962618..4ffa904 100644
--- a/services/audio/input_controller_unittest.cc
+++ b/services/audio/input_controller_unittest.cc
@@ -13,11 +13,11 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "media/audio/audio_manager.h"
-#include "media/audio/audio_processing.h"
 #include "media/audio/fake_audio_input_stream.h"
 #include "media/audio/fake_audio_log_factory.h"
 #include "media/audio/fake_audio_manager.h"
 #include "media/audio/test_audio_thread.h"
+#include "media/base/audio_processing.h"
 #include "media/base/user_input_monitor.h"
 #include "media/webrtc/audio_processor.h"
 #include "media/webrtc/webrtc_switches.h"
diff --git a/services/audio/public/cpp/audio_processing.typemap b/services/audio/public/cpp/audio_processing.typemap
index 63968907..fcc6cc7d 100644
--- a/services/audio/public/cpp/audio_processing.typemap
+++ b/services/audio/public/cpp/audio_processing.typemap
@@ -4,7 +4,7 @@
 
 mojom = "//services/audio/public/mojom/audio_processing.mojom"
 public_headers = [
-  "//media/audio/audio_processing.h",
+  "//media/base/audio_processing.h",
   "//third_party/webrtc/api/media_stream_interface.h",
 ]
 traits_headers =
diff --git a/services/audio/public/cpp/audio_processing_mojom_traits.h b/services/audio/public/cpp/audio_processing_mojom_traits.h
index b5ef2467..58bd591 100644
--- a/services/audio/public/cpp/audio_processing_mojom_traits.h
+++ b/services/audio/public/cpp/audio_processing_mojom_traits.h
@@ -5,7 +5,7 @@
 #ifndef SERVICES_AUDIO_PUBLIC_CPP_AUDIO_PROCESSING_MOJOM_TRAITS_H_
 #define SERVICES_AUDIO_PUBLIC_CPP_AUDIO_PROCESSING_MOJOM_TRAITS_H_
 
-#include "media/audio/audio_processing.h"
+#include "media/base/audio_processing.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "services/audio/public/mojom/audio_processing.mojom.h"
 
diff --git a/services/device/device_service_test_base.cc b/services/device/device_service_test_base.cc
index dbb7b8d..2bc3152c 100644
--- a/services/device/device_service_test_base.cc
+++ b/services/device/device_service_test_base.cc
@@ -11,6 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/device/device_service.h"
 #include "services/device/public/cpp/geolocation/location_provider.h"
@@ -51,19 +52,17 @@
 }  // namespace
 
 DeviceServiceTestBase::DeviceServiceTestBase()
-    : file_thread_("DeviceServiceTestFileThread"),
-      io_thread_("DeviceServiceTestIOThread"),
-      connector_(test_connector_factory_.CreateConnector()) {
-  file_thread_.Start();
-  io_thread_.StartWithOptions(
-      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-}
+    : file_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BEST_EFFORT})),
+      io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
+          {base::TaskPriority::USER_VISIBLE})),
+      connector_(test_connector_factory_.CreateConnector()) {}
 
 DeviceServiceTestBase::~DeviceServiceTestBase() = default;
 
 void DeviceServiceTestBase::SetUp() {
   service_ = CreateTestDeviceService(
-      file_thread_.task_runner(), io_thread_.task_runner(),
+      file_task_runner_, io_task_runner_,
       base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
           &test_url_loader_factory_),
       test_connector_factory_.RegisterInstance(mojom::kServiceName));
diff --git a/services/device/device_service_test_base.h b/services/device/device_service_test_base.h
index a839fa4..9585d3d 100644
--- a/services/device/device_service_test_base.h
+++ b/services/device/device_service_test_base.h
@@ -7,7 +7,6 @@
 
 #include "base/macros.h"
 #include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -33,8 +32,12 @@
   service_manager::Connector* connector() { return connector_.get(); }
 
   base::test::ScopedTaskEnvironment task_environment_;
-  base::Thread file_thread_;
-  base::Thread io_thread_;
+
+  // Both of these task runners should be deprecated in favor of individual
+  // components of the device service creating their own.
+  scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
   network::TestURLLoaderFactory test_url_loader_factory_;
 
  private:
diff --git a/services/device/generic_sensor/generic_sensor_service_unittest.cc b/services/device/generic_sensor/generic_sensor_service_unittest.cc
index e0b676d..a442982 100644
--- a/services/device/generic_sensor/generic_sensor_service_unittest.cc
+++ b/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -155,8 +155,7 @@
 class GenericSensorServiceTest : public DeviceServiceTestBase {
  public:
   GenericSensorServiceTest()
-      : io_thread_task_runner_(io_thread_.task_runner()),
-        io_loop_finished_event_(
+      : io_loop_finished_event_(
             base::WaitableEvent::ResetPolicy::AUTOMATIC,
             base::WaitableEvent::InitialState::NOT_SIGNALED) {}
 
@@ -164,7 +163,7 @@
     scoped_feature_list_.InitWithFeatures(
         {features::kGenericSensor, features::kGenericSensorExtraClasses}, {});
     DeviceServiceTestBase::SetUp();
-    io_thread_task_runner_->PostTask(
+    io_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&GenericSensorServiceTest::SetUpOnIOThread,
                                   base::Unretained(this)));
     io_loop_finished_event_.Wait();
@@ -173,7 +172,7 @@
   }
 
   void TearDown() override {
-    io_thread_task_runner_->PostTask(
+    io_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&GenericSensorServiceTest::TearDownOnIOThread,
                                   base::Unretained(this)));
     io_loop_finished_event_.Wait();
@@ -196,7 +195,6 @@
     io_loop_finished_event_.Signal();
   }
   mojom::SensorProviderPtr sensor_provider_;
-  scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
   base::WaitableEvent io_loop_finished_event_;
   base::test::ScopedFeatureList scoped_feature_list_;
 
diff --git a/services/device/geolocation/OWNERS b/services/device/geolocation/OWNERS
index 9a6b2e1b..2ce1e4a 100644
--- a/services/device/geolocation/OWNERS
+++ b/services/device/geolocation/OWNERS
@@ -1,3 +1,4 @@
+mattreynolds@chromium.org
 mcasas@chromium.org
 timvolodine@chromium.org
 
diff --git a/services/device/hid/test_report_descriptors.cc b/services/device/hid/test_report_descriptors.cc
index 0234145..0ba7a09 100644
--- a/services/device/hid/test_report_descriptors.cc
+++ b/services/device/hid/test_report_descriptors.cc
@@ -26,10 +26,10 @@
     0x26, 0xe0, 0x2e,  //   Logical Maximum (12000)
     0x35, 0x00,        //   Physical Minimum (0)
     0x45, 0x0c,        //   Physical Maximum (12)
-    0x65, 0x13,        //   Unit (Inch)
+    0x65, 0x13,        //   Unit (19)
     0x55, 0x00,        //   Unit Exponent (0)
     0xa4,              //   Push
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x05, 0x0d,        //   Usage Page (Digitizer)
     0x09, 0x32,        //   Usage (0x32)
     0x09, 0x44,        //   Usage (0x44)
@@ -41,10 +41,10 @@
     0x75, 0x01,        //   Report Size (1)
     0x95, 0x03,        //   Report Count (3)
     0x65, 0x00,        //   Unit (0)
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x01,        //   Report Count (1)
     0x75, 0x05,        //   Report Size (5)
-    0x81, 0x03,        //   Input (Con|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x03,        //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xc0,              //  End Collection
     0x85, 0x02,        //  Report ID (0x2)
     0x09, 0x20,        //  Usage (0x20)
@@ -53,7 +53,7 @@
     0xa4,              //   Push
     0x09, 0x30,        //   Usage (0x30)
     0x09, 0x31,        //   Usage (0x31)
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x05, 0x0d,        //   Usage Page (Digitizer)
     0x09, 0x32,        //   Usage (0x32)
     0x15, 0x00,        //   Logical Minimum (0)
@@ -62,15 +62,15 @@
     0x45, 0x01,        //   Physical Maximum (1)
     0x65, 0x00,        //   Unit (0)
     0x75, 0x01,        //   Report Size (1)
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x05, 0x09,        //   Usage Page (Button)
     0x19, 0x00,        //   Usage Minimum (0)
     0x29, 0x10,        //   Usage Maximum (16)
     0x25, 0x10,        //   Logical Maximum (16)
     0x75, 0x05,        //   Report Size (5)
-    0x81, 0x40,        //   Input (Dat|Arr|Abs|NoWrp|Lin|Prf|Null|BitF)
+    0x81, 0x40,        //   Input (Dat|Var|Rel|NoWrp|Lin|Prf|Null|BitF)
     0x75, 0x02,        //   Report Size (2)
-    0x81, 0x01,        //   Input (Con|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x01,        //   Input (Con|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xc0,              //  End Collection
     0x85, 0x03,        //  Report ID (0x3)
     0x05, 0x0d,        //  Usage Page (Digitizer)
@@ -79,7 +79,7 @@
     0xb4,              //   Pop
     0x09, 0x30,        //   Usage (0x30)
     0x09, 0x31,        //   Usage (0x31)
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x05, 0x0d,        //   Usage Page (Digitizer)
     0x09, 0x32,        //   Usage (0x32)
     0x09, 0x44,        //   Usage (0x44)
@@ -89,20 +89,20 @@
     0x35, 0x00,        //   Physical Minimum (0)
     0x45, 0x01,        //   Physical Maximum (1)
     0x65, 0x00,        //   Unit (0)
-    0x81, 0x02,        //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,        //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x06,        //   Report Count (6)
-    0x81, 0x03,        //   Input (Con|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x03,        //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x09, 0x30,        //   Usage (0x30)
     0x15, 0x00,        //   Logical Minimum (0)
     0x25, 0x7f,        //   Logical Maximum (127)
     0x35, 0x00,        //   Physical Minimum (0)
     0x45, 0x2d,        //   Physical Maximum (45)
-    0x67, 0x11, 0xe1,  //   Unit (Newtons)
+    0x67, 0x11, 0xe1,  //   Unit (57617)
     0x00, 0x00,        //   Default
     0x55, 0x04,        //   Unit Exponent (4)
     0x75, 0x08,        //   Report Size (8)
     0x95, 0x01,        //   Report Count (1)
-    0x81, 0x12,        //   Input (Dat|Var|Abs|NoWrp|NoLin|Prf|NoNull|BitF)
+    0x81, 0x12,        //   Input (Dat|Arr|Rel|NoWrp|NoLin|Prf|NoNull|BitF)
     0xc0,              //  End Collection
     0xc0               // End Collection
 };
@@ -121,19 +121,19 @@
     0x25, 0x01,  //  Logical Maximum (1)
     0x75, 0x01,  //  Report Size (1)
     0x95, 0x08,  //  Report Count (8)
-    0x81, 0x02,  //  Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,  //  Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x01,  //  Report Count (1)
     0x75, 0x08,  //  Report Size (8)
-    0x81, 0x03,  //  Input (Con|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x03,  //  Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x05,  //  Report Count (5)
     0x75, 0x01,  //  Report Size (1)
     0x05, 0x08,  //  Usage Page (Led)
     0x19, 0x01,  //  Usage Minimum (1)
     0x29, 0x05,  //  Usage Maximum (5)
-    0x91, 0x02,  //  Output (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x02,  //  Output (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x01,  //  Report Count (1)
     0x75, 0x03,  //  Report Size (3)
-    0x91, 0x03,  //  Output (Con|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x03,  //  Output (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x06,  //  Report Count (6)
     0x75, 0x08,  //  Report Size (8)
     0x15, 0x00,  //  Logical Minimum (0)
@@ -141,7 +141,7 @@
     0x05, 0x07,  //  Usage Page (Keyboard)
     0x19, 0x00,  //  Usage Minimum (0)
     0x29, 0x65,  //  Usage Maximum (101)
-    0x81, 0x00,  //  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x00,  //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xc0         // End Collection
 };
 const size_t kKeyboardSize = base::size(kKeyboard);
@@ -158,11 +158,11 @@
     0x75, 0x08,        //  Report Size (8)
     0x95, 0x80,        //  Report Count (128)
     0x09, 0x02,        //  Usage (0x2)
-    0xb2, 0x02, 0x01,  //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|Buff)
+    0xb2, 0x02, 0x01,  //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff)
     0x85, 0x02,        //  Report ID (0x2)
     0x95, 0xf3,        //  Report Count (243)
     0x09, 0x03,        //  Usage (0x3)
-    0xb2, 0x02, 0x01,  //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|Buff)
+    0xb2, 0x02, 0x01,  //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|Buff)
     0x85, 0x03,        //  Report ID (0x3)
     0x05, 0x82,        //  Usage Page (Monitor 2)
     0x67, 0xE1, 0x00,  //  Unit (System: SI, Lum. Intensity: Candela)
@@ -172,11 +172,11 @@
     0x75, 0x10,        //  Report Size (16)
     0x26, 0xc8, 0x00,  //  Logical Maximum (200)
     0x09, 0x10,        //  Usage (0x10)
-    0xb1, 0x02,        //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x85, 0x04,        //  Report ID (0x4)
     0x25, 0x64,        //  Logical Maximum (100)
     0x09, 0x12,        //  Usage (0x12)
-    0xb1, 0x02,        //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x06,        //  Report Count (6)
     0x26, 0xff, 0x00,  //  Logical Maximum (255)
     0x09, 0x16,        //  Usage (0x16)
@@ -185,7 +185,7 @@
     0x09, 0x6c,        //  Usage (0x6C)
     0x09, 0x6e,        //  Usage (0x6E)
     0x09, 0x70,        //  Usage (0x70)
-    0xb1, 0x02,        //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x85, 0x05,        //  Report ID (0x5)
     0x25, 0x7f,        //  Logical Maximum (127)
     0x09, 0x20,        //  Usage (0x20)
@@ -194,7 +194,7 @@
     0x09, 0x32,        //  Usage (0x32)
     0x09, 0x42,        //  Usage (0x42)
     0x09, 0x44,        //  Usage (0x44)
-    0xb1, 0x02,        //  Feature (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0xb1, 0x02,        //  Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xc0               // End Collection
 };
 const size_t kMonitorSize = base::size(kMonitor);
@@ -214,10 +214,10 @@
     0x25, 0x01,  //   Logical Maximum (1)
     0x95, 0x03,  //   Report Count (3)
     0x75, 0x01,  //   Report Size (1)
-    0x81, 0x02,  //   Input (Dat|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x02,  //   Input (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x95, 0x01,  //   Report Count (1)
     0x75, 0x05,  //   Report Size (5)
-    0x81, 0x03,  //   Input (Con|Var|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x03,  //   Input (Con|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x05, 0x01,  //   Usage Page (Generic Desktop)
     0x09, 0x30,  //   Usage (0x30)
     0x09, 0x31,  //   Usage (0x31)
@@ -225,7 +225,7 @@
     0x25, 0x7f,  //   Logical Maximum (127)
     0x75, 0x08,  //   Report Size (8)
     0x95, 0x02,  //   Report Count (2)
-    0x81, 0x06,  //   Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x06,  //   Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
     0xc0,        //  End Collection
     0xc0         // End Collection
 };
@@ -242,9 +242,9 @@
     0x15, 0x00,        //  Logical Minimum (0)
     0x26, 0xFF, 0x00,  //  Logical Maximum (255)
     0x09, 0x01,        //  Usage (0x1)
-    0x81, 0x00,        //  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x09, 0x01,        //  Usage (0x1)
-    0x91, 0x00,        //  Output (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xC0,              // End Collection
     0x06, 0x00, 0xFF,  // Usage Page (Vendor)
     0x09, 0x02,        // Usage (0x2)
@@ -255,9 +255,9 @@
     0x15, 0x00,        //  Logical Minimum (0)
     0x26, 0xFF, 0x00,  //  Logical Maximum (255)
     0x09, 0x02,        //  Usage (0x2)
-    0x81, 0x00,        //  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x09, 0x02,        //  Usage (0x2)
-    0x91, 0x00,        //  Output (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xC0,              // End Collection
     0x06, 0x00, 0xFF,  // Usage Page (Vendor)
     0x09, 0x04,        // Usage (0x4)
@@ -268,17 +268,17 @@
     0x15, 0x00,        //  Logical Minimum (0)
     0x26, 0xFF, 0x00,  //  Logical Maximum (255)
     0x09, 0x41,        //  Usage (0x41)
-    0x81, 0x00,        //  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x09, 0x41,        //  Usage (0x41)
-    0x91, 0x00,        //  Output (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x85, 0x21,        //  Report ID (0x21)
     0x95, 0x1F,        //  Report Count (31)
     0x15, 0x00,        //  Logical Minimum (0)
     0x26, 0xFF, 0x00,  //  Logical Maximum (255)
     0x09, 0x42,        //  Usage (0x42)
-    0x81, 0x00,        //  Input (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x81, 0x00,        //  Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0x09, 0x42,        //  Usage (0x42)
-    0x91, 0x00,        //  Output (Dat|Arr|Abs|NoWrp|Lin|Prf|NoNull|BitF)
+    0x91, 0x00,        //  Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF)
     0xC0               // End Collection
 };
 const size_t kLogitechUnifyingReceiverSize =
@@ -288,8 +288,8 @@
 const uint8_t kSonyDualshock3[] = {
     0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
     0x09, 0x04,        // Usage (Joystick)
-    0xA1, 0x01,        // Collection (Application)
-    0xA1, 0x02,        //   Collection (Logical)
+    0xA1, 0x01,        // Collection (Physical)
+    0xA1, 0x02,        //   Collection (Application)
     0x85, 0x01,        //     Report ID (1)
     0x75, 0x08,        //     Report Size (8)
     0x95, 0x01,        //     Report Count (1)
@@ -318,7 +318,7 @@
     0x26, 0xFF, 0x00,  //     Logical Maximum (255)
     0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
     0x09, 0x01,        //     Usage (Pointer)
-    0xA1, 0x00,        //     Collection (Physical)
+    0xA1, 0x00,        //     Collection (Undefined)
     0x75, 0x08,        //       Report Size (8)
     0x95, 0x04,        //       Report Count (4)
     0x35, 0x00,        //       Physical Minimum (0)
@@ -347,7 +347,7 @@
     0xB1, 0x02,        //     Feature (Data,Var,Abs,No Wrap,Linear,Preferred
                        //     State,No Null Position,Non-volatile)
     0xC0,              //   End Collection
-    0xA1, 0x02,        //   Collection (Logical)
+    0xA1, 0x02,        //   Collection (Application)
     0x85, 0x02,        //     Report ID (2)
     0x75, 0x08,        //     Report Size (8)
     0x95, 0x30,        //     Report Count (48)
@@ -355,7 +355,7 @@
     0xB1, 0x02,        //     Feature (Data,Var,Abs,No Wrap,Linear,Preferred
                        //     State,No Null Position,Non-volatile)
     0xC0,              //   End Collection
-    0xA1, 0x02,        //   Collection (Logical)
+    0xA1, 0x02,        //   Collection (Application)
     0x85, 0xEE,        //     Report ID (238)
     0x75, 0x08,        //     Report Size (8)
     0x95, 0x30,        //     Report Count (48)
@@ -363,7 +363,7 @@
     0xB1, 0x02,        //     Feature (Data,Var,Abs,No Wrap,Linear,Preferred
                        //     State,No Null Position,Non-volatile)
     0xC0,              //   End Collection
-    0xA1, 0x02,        //   Collection (Logical)
+    0xA1, 0x02,        //   Collection (Application)
     0x85, 0xEF,        //     Report ID (239)
     0x75, 0x08,        //     Report Size (8)
     0x95, 0x30,        //     Report Count (48)
@@ -1642,328 +1642,4 @@
 const size_t kMicrosoftXboxAdaptiveControllerSize =
     base::size(kMicrosoftXboxAdaptiveController);
 
-const uint8_t kNexusPlayerController[] = {
-    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x05,        // Usage (Game Pad)
-    0xA1, 0x01,        // Collection (Application)
-    0x85, 0x01,        //   Report ID (1)
-    0x05, 0x09,        //   Usage Page (Button)
-    0x0A, 0x01, 0x00,  //   Usage (0x01)
-    0x0A, 0x02, 0x00,  //   Usage (0x02)
-    0x0A, 0x04, 0x00,  //   Usage (0x04)
-    0x0A, 0x05, 0x00,  //   Usage (0x05)
-    0x0A, 0x07, 0x00,  //   Usage (0x07)
-    0x0A, 0x08, 0x00,  //   Usage (0x08)
-    0x0A, 0x0E, 0x00,  //   Usage (0x0E)
-    0x0A, 0x0F, 0x00,  //   Usage (0x0F)
-    0x0A, 0x0D, 0x00,  //   Usage (0x0D)
-    0x05, 0x0C,        //   Usage Page (Consumer)
-    0x0A, 0x24, 0x02,  //   Usage (AC Back)
-    0x0A, 0x23, 0x02,  //   Usage (AC Home)
-    0x15, 0x00,        //   Logical Minimum (0)
-    0x25, 0x01,        //   Logical Maximum (1)
-    0x75, 0x01,        //   Report Size (1)
-    0x95, 0x0B,        //   Report Count (11)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x75, 0x01,        //   Report Size (1)
-    0x95, 0x01,        //   Report Count (1)
-    0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x05, 0x01,        //   Usage Page (Generic Desktop Ctrls)
-    0x75, 0x04,        //   Report Size (4)
-    0x95, 0x01,        //   Report Count (1)
-    0x25, 0x07,        //   Logical Maximum (7)
-    0x46, 0x3B, 0x01,  //   Physical Maximum (315)
-    0x66, 0x14, 0x00,  //   Unit (System: English Rotation, Length: Centimeter)
-    0x09, 0x39,        //   Usage (Hat switch)
-    0x81, 0x42,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   Null State)
-    0x66, 0x00, 0x00,  //   Unit (None)
-    0xA1, 0x00,        //   Collection (Physical)
-    0x09, 0x30,        //     Usage (X)
-    0x09, 0x31,        //     Usage (Y)
-    0x09, 0x32,        //     Usage (Z)
-    0x09, 0x35,        //     Usage (Rz)
-    0x05, 0x02,        //     Usage Page (Sim Ctrls)
-    0x09, 0xC5,        //     Usage (Brake)
-    0x09, 0xC4,        //     Usage (Accelerator)
-    0x15, 0x00,        //     Logical Minimum (0)
-    0x26, 0xFF, 0x00,  //     Logical Maximum (255)
-    0x35, 0x00,        //     Physical Minimum (0)
-    0x46, 0xFF, 0x00,  //     Physical Maximum (255)
-    0x75, 0x08,        //     Report Size (8)
-    0x95, 0x06,        //     Report Count (6)
-    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred
-                       //     State,No Null Position)
-    0xC0,              //   End Collection
-    0x85, 0x02,        //   Report ID (2)
-    0x05, 0x08,        //   Usage Page (LEDs)
-    0x0A, 0x01, 0x00,  //   Usage (Num Lock)
-    0x0A, 0x02, 0x00,  //   Usage (Caps Lock)
-    0x0A, 0x03, 0x00,  //   Usage (Scroll Lock)
-    0x0A, 0x04, 0x00,  //   Usage (Compose)
-    0x15, 0x00,        //   Logical Minimum (0)
-    0x25, 0x01,        //   Logical Maximum (1)
-    0x75, 0x01,        //   Report Size (1)
-    0x95, 0x04,        //   Report Count (4)
-    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position,Non-volatile)
-    0x75, 0x04,        //   Report Size (4)
-    0x95, 0x01,        //   Report Count (1)
-    0x91, 0x03,        //   Output (Const,Var,Abs,No Wrap,Linear,Preferred
-                       //   State,No Null Position,Non-volatile)
-    0xC0,              // End Collection
-    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x05,        // Usage (Game Pad)
-    0xA1, 0x01,        // Collection (Application)
-    0x85, 0x03,        //   Report ID (3)
-    0x05, 0x06,        //   Usage Page (Generic Dev Ctrls)
-    0x09, 0x20,        //   Usage (Battery Strength)
-    0x15, 0x00,        //   Logical Minimum (0)
-    0x26, 0xFF, 0x00,  //   Logical Maximum (255)
-    0x75, 0x08,        //   Report Size (8)
-    0x95, 0x01,        //   Report Count (1)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x06, 0xBC, 0xFF,  //   Usage Page (Vendor Defined 0xFFBC)
-    0x0A, 0xAD, 0xBD,  //   Usage (0xBDAD)
-    0x75, 0x08,        //   Report Size (8)
-    0x95, 0x06,        //   Report Count (6)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0xC0,              // End Collection
-    0x00,              // Unknown (bTag: 0x00, bType: 0x00)
-};
-const size_t kNexusPlayerControllerSize = base::size(kNexusPlayerController);
-
-const uint8_t kSteamControllerKeyboard[] = {
-    0x05, 0x01,  // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x06,  // Usage (Keyboard)
-    0x95, 0x01,  // Report Count (1)
-    0xA1, 0x01,  // Collection (Application)
-    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
-    0x19, 0xE0,  //   Usage Minimum (0xE0)
-    0x29, 0xE7,  //   Usage Maximum (0xE7)
-    0x15, 0x00,  //   Logical Minimum (0)
-    0x25, 0x01,  //   Logical Maximum (1)
-    0x75, 0x01,  //   Report Size (1)
-    0x95, 0x08,  //   Report Count (8)
-    0x81, 0x02,  //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                 //   No Null Position)
-    0x95, 0x01,  //   Report Count (1)
-    0x75, 0x08,  //   Report Size (8)
-    0x81, 0x01,  //   Input (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //   State,No Null Position)
-    0x95, 0x05,  //   Report Count (5)
-    0x75, 0x01,  //   Report Size (1)
-    0x05, 0x08,  //   Usage Page (LEDs)
-    0x19, 0x01,  //   Usage Minimum (Num Lock)
-    0x29, 0x05,  //   Usage Maximum (Kana)
-    0x91, 0x02,  //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                 //   No Null Position,Non-volatile)
-    0x95, 0x01,  //   Report Count (1)
-    0x75, 0x03,  //   Report Size (3)
-    0x91, 0x01,  //   Output (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //   State,No Null Position,Non-volatile)
-    0x95, 0x06,  //   Report Count (6)
-    0x75, 0x08,  //   Report Size (8)
-    0x15, 0x00,  //   Logical Minimum (0)
-    0x25, 0x65,  //   Logical Maximum (101)
-    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
-    0x19, 0x00,  //   Usage Minimum (0x00)
-    0x29, 0x65,  //   Usage Maximum (0x65)
-    0x81, 0x00,  //   Input (Data,Array,Abs,No Wrap,Linear,Preferred
-                 //   State,No Null Position)
-    0xC0,        // End Collection
-};
-const size_t kSteamControllerKeyboardSize =
-    base::size(kSteamControllerKeyboard);
-
-const uint8_t kSteamControllerMouse[] = {
-    0x05, 0x01,  // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x02,  // Usage (Mouse)
-    0xA1, 0x01,  // Collection (Application)
-    0x09, 0x01,  //   Usage (Pointer)
-    0xA1, 0x00,  //   Collection (Physical)
-    0x05, 0x09,  //     Usage Page (Button)
-    0x19, 0x01,  //     Usage Minimum (0x01)
-    0x29, 0x05,  //     Usage Maximum (0x05)
-    0x15, 0x00,  //     Logical Minimum (0)
-    0x25, 0x01,  //     Logical Maximum (1)
-    0x95, 0x05,  //     Report Count (5)
-    0x75, 0x01,  //     Report Size (1)
-    0x81, 0x02,  //     Input (Data,Var,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0x95, 0x01,  //     Report Count (1)
-    0x75, 0x03,  //     Report Size (3)
-    0x81, 0x01,  //     Input (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0x05, 0x01,  //     Usage Page (Generic Desktop Ctrls)
-    0x09, 0x30,  //     Usage (X)
-    0x09, 0x31,  //     Usage (Y)
-    0x09, 0x38,  //     Usage (Wheel)
-    0x15, 0x81,  //     Logical Minimum (-127)
-    0x25, 0x7F,  //     Logical Maximum (127)
-    0x75, 0x08,  //     Report Size (8)
-    0x95, 0x03,  //     Report Count (3)
-    0x81, 0x06,  //     Input (Data,Var,Rel,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0xC0,        //   End Collection
-    0xC0,        // End Collection
-};
-const size_t kSteamControllerMouseSize = base::size(kSteamControllerMouse);
-
-const uint8_t kSteamControllerVendor[] = {
-    0x06, 0x00, 0xFF,  // Usage Page (Vendor Defined 0xFF00)
-    0x09, 0x01,        // Usage (0x01)
-    0xA1, 0x01,        // Collection (Application)
-    0x15, 0x00,        //   Logical Minimum (0)
-    0x26, 0xFF, 0x00,  //   Logical Maximum (255)
-    0x75, 0x08,        //   Report Size (8)
-    0x95, 0x40,        //   Report Count (64)
-    0x09, 0x01,        //   Usage (0x01)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x95, 0x40,        //   Report Count (64)
-    0x09, 0x01,        //   Usage (0x01)
-    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position,Non-volatile)
-    0x95, 0x40,        //   Report Count (64)
-    0x09, 0x01,        //   Usage (0x01)
-    0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred
-                       //   State,No Null Position,Non-volatile)
-    0xC0,              // End Collection
-};
-const size_t kSteamControllerVendorSize = base::size(kSteamControllerVendor);
-
-const uint8_t kXSkillsUsbAdapter[] = {
-    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x04,        // Usage (Joystick)
-    0xA1, 0x01,        // Collection (Application)
-    0x05, 0x09,        //   Usage Page (Button)
-    0x19, 0x01,        //   Usage Minimum (0x01)
-    0x29, 0x0C,        //   Usage Maximum (0x0C)
-    0x15, 0x00,        //   Logical Minimum (0)
-    0x25, 0x01,        //   Logical Maximum (1)
-    0x35, 0x00,        //   Physical Minimum (0)
-    0x45, 0x01,        //   Physical Maximum (1)
-    0x75, 0x01,        //   Report Size (1)
-    0x95, 0x0C,        //   Report Count (12)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x95, 0x04,        //   Report Count (4)
-    0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x05, 0x01,        //   Usage Page (Generic Desktop Ctrls)
-    0x09, 0x30,        //   Usage (X)
-    0x09, 0x31,        //   Usage (Y)
-    0x09, 0x35,        //   Usage (Rz)
-    0x09, 0x32,        //   Usage (Z)
-    0x26, 0xFF, 0x00,  //   Logical Maximum (255)
-    0x46, 0xFF, 0x00,  //   Physical Maximum (255)
-    0x66, 0x00, 0x00,  //   Unit (None)
-    0x75, 0x08,        //   Report Size (8)
-    0x95, 0x04,        //   Report Count (4)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x09, 0x33,        //   Usage (Rx)
-    0x09, 0x34,        //   Usage (Ry)
-    0x26, 0x0F, 0x00,  //   Logical Maximum (15)
-    0x46, 0x0F, 0x00,  //   Physical Maximum (15)
-    0x75, 0x04,        //   Report Size (4)
-    0x95, 0x02,        //   Report Count (2)
-    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position)
-    0x75, 0x08,        //   Report Size (8)
-    0x06, 0x00, 0xFF,  //   Usage Page (Vendor Defined 0xFF00)
-    0x19, 0x01,        //   Usage Minimum (0x01)
-    0x29, 0x04,        //   Usage Maximum (0x04)
-    0x95, 0x04,        //   Report Count (4)
-    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                       //   No Null Position,Non-volatile)
-    0xC0,              // End Collection
-};
-const size_t kXSkillsUsbAdapterSize = base::size(kXSkillsUsbAdapter);
-
-const uint8_t kBelkinNostromoKeyboard[] = {
-    0x05, 0x01,  // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x06,  // Usage (Keyboard)
-    0xA1, 0x01,  // Collection (Application)
-    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
-    0x19, 0xE0,  //   Usage Minimum (0xE0)
-    0x29, 0xE7,  //   Usage Maximum (0xE7)
-    0x15, 0x00,  //   Logical Minimum (0)
-    0x25, 0x01,  //   Logical Maximum (1)
-    0x75, 0x01,  //   Report Size (1)
-    0x95, 0x08,  //   Report Count (8)
-    0x81, 0x02,  //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,
-                 //   No Null Position)
-    0x95, 0x01,  //   Report Count (1)
-    0x75, 0x08,  //   Report Size (8)
-    0x81, 0x01,  //   Input (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //   State,No Null Position)
-    0x95, 0x06,  //   Report Count (6)
-    0x75, 0x08,  //   Report Size (8)
-    0x15, 0x00,  //   Logical Minimum (0)
-    0x25, 0x65,  //   Logical Maximum (101)
-    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
-    0x19, 0x00,  //   Usage Minimum (0x00)
-    0x29, 0x65,  //   Usage Maximum (0x65)
-    0x81, 0x00,  //   Input (Data,Array,Abs,No Wrap,Linear,Preferred
-                 //   State,No Null Position)
-    0xC0,        // End Collection
-};
-const size_t kBelkinNostromoKeyboardSize = base::size(kBelkinNostromoKeyboard);
-
-const uint8_t kBelkinNostromoMouseAndExtra[] = {
-    0x05, 0x01,  // Usage Page (Generic Desktop Ctrls)
-    0x09, 0x02,  // Usage (Mouse)
-    0xA1, 0x01,  // Collection (Application)
-    0x09, 0x01,  //   Usage (Pointer)
-    0xA1, 0x00,  //   Collection (Physical)
-    0x05, 0x09,  //     Usage Page (Button)
-    0x19, 0x01,  //     Usage Minimum (0x01)
-    0x29, 0x03,  //     Usage Maximum (0x03)
-    0x15, 0x00,  //     Logical Minimum (0)
-    0x25, 0x01,  //     Logical Maximum (1)
-    0x95, 0x03,  //     Report Count (3)
-    0x75, 0x01,  //     Report Size (1)
-    0x81, 0x02,  //     Input (Data,Var,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0x95, 0x01,  //     Report Count (1)
-    0x75, 0x05,  //     Report Size (5)
-    0x81, 0x01,  //     Input (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0x05, 0x01,  //     Usage Page (Generic Desktop Ctrls)
-    0x09, 0x30,  //     Usage (X)
-    0x09, 0x31,  //     Usage (Y)
-    0x09, 0x38,  //     Usage (Wheel)
-    0x15, 0x81,  //     Logical Minimum (-127)
-    0x25, 0x7F,  //     Logical Maximum (127)
-    0x75, 0x08,  //     Report Size (8)
-    0x95, 0x03,  //     Report Count (3)
-    0x81, 0x06,  //     Input (Data,Var,Rel,No Wrap,Linear,Preferred
-                 //     State,No Null Position)
-    0x05, 0x08,  //     Usage Page (LEDs)
-    0x19, 0x01,  //     Usage Minimum (Num Lock)
-    0x29, 0x03,  //     Usage Maximum (Scroll Lock)
-    0x15, 0x00,  //     Logical Minimum (0)
-    0x25, 0x01,  //     Logical Maximum (1)
-    0x35, 0x00,  //     Physical Minimum (0)
-    0x45, 0x01,  //     Physical Maximum (1)
-    0x75, 0x01,  //     Report Size (1)
-    0x95, 0x03,  //     Report Count (3)
-    0x91, 0x02,  //     Output (Data,Var,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position,Non-volatile)
-    0x75, 0x05,  //     Report Size (5)
-    0x95, 0x01,  //     Report Count (1)
-    0x91, 0x01,  //     Output (Const,Array,Abs,No Wrap,Linear,Preferred
-                 //     State,No Null Position,Non-volatile)
-    0xC0,        //   End Collection
-    0xC0,        // End Collection
-};
-const size_t kBelkinNostromoMouseAndExtraSize =
-    base::size(kBelkinNostromoMouseAndExtra);
-
 }  // namespace device
diff --git a/services/device/hid/test_report_descriptors.h b/services/device/hid/test_report_descriptors.h
index b116b64..1985ce6 100644
--- a/services/device/hid/test_report_descriptors.h
+++ b/services/device/hid/test_report_descriptors.h
@@ -54,28 +54,6 @@
 extern const uint8_t kMicrosoftXboxAdaptiveController[];
 extern const size_t kMicrosoftXboxAdaptiveControllerSize;
 
-// Nexus Player Controller descriptor
-extern const uint8_t kNexusPlayerController[];
-extern const size_t kNexusPlayerControllerSize;
-
-// Steam Controller descriptors
-extern const uint8_t kSteamControllerKeyboard[];
-extern const size_t kSteamControllerKeyboardSize;
-extern const uint8_t kSteamControllerMouse[];
-extern const size_t kSteamControllerMouseSize;
-extern const uint8_t kSteamControllerVendor[];
-extern const size_t kSteamControllerVendorSize;
-
-// XSkills Gamecube USB controller adapter descriptor
-extern const uint8_t kXSkillsUsbAdapter[];
-extern const size_t kXSkillsUsbAdapterSize;
-
-// Belkin Nostromo SpeedPad descriptors
-extern const uint8_t kBelkinNostromoKeyboard[];
-extern const size_t kBelkinNostromoKeyboardSize;
-extern const uint8_t kBelkinNostromoMouseAndExtra[];
-extern const size_t kBelkinNostromoMouseAndExtraSize;
-
 }  // namespace device
 
 #endif  // SERVICES_DEVICE_HID_TEST_REPORT_DESCRIPTORS_H_
diff --git a/services/device/public/cpp/hid/BUILD.gn b/services/device/public/cpp/hid/BUILD.gn
index da35bf9..6ec1c2c 100644
--- a/services/device/public/cpp/hid/BUILD.gn
+++ b/services/device/public/cpp/hid/BUILD.gn
@@ -12,18 +12,12 @@
   sources = [
     "fake_input_service_linux.cc",
     "fake_input_service_linux.h",
-    "hid_collection.cc",
-    "hid_collection.h",
     "hid_device_filter.cc",
     "hid_device_filter.h",
-    "hid_item_state_table.cc",
-    "hid_item_state_table.h",
     "hid_report_descriptor.cc",
     "hid_report_descriptor.h",
     "hid_report_descriptor_item.cc",
     "hid_report_descriptor_item.h",
-    "hid_report_item.cc",
-    "hid_report_item.h",
     "hid_usage_and_page.cc",
     "hid_usage_and_page.h",
   ]
diff --git a/services/device/public/cpp/hid/fake_input_service_linux.h b/services/device/public/cpp/hid/fake_input_service_linux.h
index 391cf7cf..0cfb825 100644
--- a/services/device/public/cpp/hid/fake_input_service_linux.h
+++ b/services/device/public/cpp/hid/fake_input_service_linux.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_DEVICE_PUBLIC_CPP_HID_FAKE_INPUT_SERVICE_LINUX_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_FAKE_INPUT_SERVICE_LINUX_H_
+#ifndef DEVICE_HID_FAKE_INPUT_SERVICE_LINUX_H_
+#define DEVICE_HID_FAKE_INPUT_SERVICE_LINUX_H_
 
 #include <map>
 #include <string>
@@ -42,4 +42,4 @@
 
 }  // namespace device
 
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_FAKE_INPUT_SERVICE_LINUX_H_
+#endif  // DEVICE_HID_FAKE_INPUT_SERVICE_LINUX_H_
diff --git a/services/device/public/cpp/hid/hid_collection.cc b/services/device/public/cpp/hid/hid_collection.cc
deleted file mode 100644
index 473c5cf65..0000000
--- a/services/device/public/cpp/hid/hid_collection.cc
+++ /dev/null
@@ -1,215 +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 "services/device/public/cpp/hid/hid_collection.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
-#include "services/device/public/cpp/hid/hid_item_state_table.h"
-
-namespace device {
-
-HidCollection::HidCollection(HidCollection* parent,
-                             uint32_t usage_page,
-                             uint32_t usage,
-                             uint32_t type)
-    : parent_(parent), usage_(usage, usage_page), collection_type_(type) {}
-
-HidCollection::~HidCollection() = default;
-
-// static
-std::vector<std::unique_ptr<HidCollection>> HidCollection::BuildCollections(
-    const std::vector<std::unique_ptr<HidReportDescriptorItem>>& items) {
-  std::vector<std::unique_ptr<HidCollection>> collections;
-  // This HID report descriptor parser implements a state machine described
-  // in the HID specification. See section 6.2.2 Report Descriptor.
-  HidItemStateTable state;
-  for (const auto& current_item : items) {
-    switch (current_item->tag()) {
-      case HidReportDescriptorItem::kTagCollection:
-        // Add a new collection. Collections at the top-most level describe
-        // separate components of the device and are often treated as separate
-        // devices. Nested components represent logical collections of fields
-        // within a report.
-        AddCollection(*current_item, collections, state);
-        state.local.Reset();
-        break;
-      case HidReportDescriptorItem::kTagEndCollection:
-        // Mark the end of the current collection. Subsequent items describe
-        // reports associated with the parent collection.
-        if (state.collection)
-          state.collection = state.collection->parent_;
-        state.local.Reset();
-        break;
-      case HidReportDescriptorItem::kTagInput:
-      case HidReportDescriptorItem::kTagOutput:
-      case HidReportDescriptorItem::kTagFeature:
-        // Add a report item to an input, output, or feature report within the
-        // current collection. The properties of the report item are determined
-        // by the current descriptor item and the current item state table.
-        // Changes to input, output, and feature reports are propagated to all
-        // ancestor collections.
-        if (state.collection) {
-          auto* collection = state.collection;
-          while (collection) {
-            collection->AddReportItem(current_item->tag(),
-                                      current_item->GetShortData(), state);
-            collection = collection->parent_;
-          }
-        }
-        state.local.Reset();
-        break;
-      case HidReportDescriptorItem::kTagPush:
-        // Push a copy of the current global state onto the stack. If there is
-        // no global state, the push has no effect and is ignored.
-        if (!state.global_stack.empty())
-          state.global_stack.push_back(state.global_stack.back());
-        break;
-      case HidReportDescriptorItem::kTagPop:
-        // Pop the top item of the global state stack, returning to the
-        // previously pushed state. If there is no such item, the pop has no
-        // effect and is ignored.
-        if (!state.global_stack.empty())
-          state.global_stack.pop_back();
-        break;
-      case HidReportDescriptorItem::kTagReportId:
-        // Update the current report ID. The report ID is global, but is not
-        // affected by push and pop. Changes to the report ID are propagated to
-        // all ancestor collections.
-        if (state.collection) {
-          state.report_id = current_item->GetShortData();
-          auto* collection = state.collection;
-          while (collection) {
-            collection->report_ids_.push_back(state.report_id);
-            collection = collection->parent_;
-          }
-        }
-        break;
-      case HidReportDescriptorItem::kTagUsagePage:
-      case HidReportDescriptorItem::kTagLogicalMinimum:
-      case HidReportDescriptorItem::kTagLogicalMaximum:
-      case HidReportDescriptorItem::kTagPhysicalMinimum:
-      case HidReportDescriptorItem::kTagPhysicalMaximum:
-      case HidReportDescriptorItem::kTagUnitExponent:
-      case HidReportDescriptorItem::kTagUnit:
-      case HidReportDescriptorItem::kTagReportSize:
-      case HidReportDescriptorItem::kTagReportCount:
-      case HidReportDescriptorItem::kTagUsage:
-      case HidReportDescriptorItem::kTagUsageMinimum:
-      case HidReportDescriptorItem::kTagUsageMaximum:
-      case HidReportDescriptorItem::kTagDesignatorIndex:
-      case HidReportDescriptorItem::kTagDesignatorMinimum:
-      case HidReportDescriptorItem::kTagDesignatorMaximum:
-      case HidReportDescriptorItem::kTagStringIndex:
-      case HidReportDescriptorItem::kTagStringMinimum:
-      case HidReportDescriptorItem::kTagStringMaximum:
-      case HidReportDescriptorItem::kTagDelimiter:
-        // Update the value associated with a local or global item in the item
-        // state table.
-        state.SetItemValue(current_item->tag(), current_item->GetShortData());
-        break;
-      default:
-        break;
-    }
-  }
-  return collections;
-}
-
-// static
-void HidCollection::AddCollection(
-    const HidReportDescriptorItem& item,
-    std::vector<std::unique_ptr<HidCollection>>& collections,
-    HidItemStateTable& state) {
-  // Extract |usage| and |usage_page| from the current state. The usage page may
-  // be set either by a global usage page, or in the high-order bytes of a local
-  // usage value. When both are provided, the local usage value takes
-  // precedence.
-  uint32_t usage = state.local.usages.empty() ? 0 : state.local.usages.front();
-  uint32_t usage_page = (usage >> 16) & 0xffff;
-  if (usage_page == 0 && !state.global_stack.empty())
-    usage_page = state.global_stack.back().usage_page;
-  // Create the new collection. If it is a child of another collection, append
-  // it to that collection's list of children. Otherwise, append it to the list
-  // of top-level collections in |collections|.
-  uint32_t collection_type = item.GetShortData();
-  auto collection = std::make_unique<HidCollection>(
-      state.collection, usage_page, usage, collection_type);
-  if (state.collection) {
-    state.collection->children_.push_back(std::move(collection));
-    state.collection = state.collection->children_.back().get();
-  } else {
-    collections.push_back(std::move(collection));
-    state.collection = collections.back().get();
-  }
-}
-
-void HidCollection::AddChildForTesting(
-    std::unique_ptr<HidCollection> collection) {
-  children_.push_back(std::move(collection));
-}
-
-void HidCollection::AddReportItem(HidReportDescriptorItem::Tag tag,
-                                  uint32_t report_info,
-                                  const HidItemStateTable& state) {
-  // Get the correct report map for the current report item (input, output,
-  // or feature). The new item will be appended to a report in this report map.
-  std::unordered_map<uint8_t, HidReport>* reports = nullptr;
-  if (tag == HidReportDescriptorItem::kTagInput)
-    reports = &input_reports_;
-  else if (tag == HidReportDescriptorItem::kTagOutput)
-    reports = &output_reports_;
-  else if (tag == HidReportDescriptorItem::kTagFeature)
-    reports = &feature_reports_;
-  else
-    return;
-  // Fetch the report with the |report_id| matching this item, or insert a new
-  // report into the map if it does not yet exist.
-  HidReport* report = nullptr;
-  auto find_it = reports->find(state.report_id);
-  if (find_it == reports->end()) {
-    auto emplace_result = reports->emplace(state.report_id, HidReport());
-    report = &emplace_result.first->second;
-  } else {
-    report = &find_it->second;
-  }
-  // Create the report item and append it to the report.
-  report->push_back(HidReportItem::Create(tag, report_info, state));
-}
-
-mojom::HidCollectionInfoPtr HidCollection::GetDetails(
-    size_t* max_input_report_bits,
-    size_t* max_output_report_bits,
-    size_t* max_feature_report_bits) {
-  DCHECK(max_input_report_bits);
-  DCHECK(max_output_report_bits);
-  DCHECK(max_feature_report_bits);
-  struct {
-    const std::unordered_map<uint8_t, HidReport>& reports;
-    size_t& max_report_bits;
-  } report_lists[]{
-      {input_reports_, *max_input_report_bits},
-      {output_reports_, *max_output_report_bits},
-      {feature_reports_, *max_feature_report_bits},
-  };
-  auto collection_info = mojom::HidCollectionInfo::New();
-  collection_info->usage =
-      mojom::HidUsageAndPage::New(usage_.usage, usage_.usage_page);
-  collection_info->report_ids.insert(collection_info->report_ids.end(),
-                                     report_ids_.begin(), report_ids_.end());
-  for (const auto& entry : report_lists) {
-    entry.max_report_bits = 0;
-    for (const auto& report : entry.reports) {
-      size_t report_bits = 0;
-      for (const auto& item : report.second)
-        report_bits += item->GetReportSize() * item->GetReportCount();
-      entry.max_report_bits = std::max(entry.max_report_bits, report_bits);
-    }
-  }
-  return collection_info;
-}
-
-}  // namespace device
diff --git a/services/device/public/cpp/hid/hid_collection.h b/services/device/public/cpp/hid/hid_collection.h
deleted file mode 100644
index 4f964a0..0000000
--- a/services/device/public/cpp/hid/hid_collection.h
+++ /dev/null
@@ -1,109 +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 SERVICES_DEVICE_PUBLIC_CPP_HID_HID_COLLECTION_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_COLLECTION_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
-#include "services/device/public/cpp/hid/hid_report_item.h"
-#include "services/device/public/mojom/hid.mojom.h"
-
-namespace device {
-
-class HidItemStateTable;
-
-// Information about a single HID collection.
-class HidCollection {
- public:
-  using HidReport = std::vector<std::unique_ptr<HidReportItem>>;
-
-  HidCollection(HidCollection* parent,
-                uint32_t usage_page,
-                uint32_t usage,
-                uint32_t collection_type);
-  ~HidCollection();
-
-  static std::vector<std::unique_ptr<HidCollection>> BuildCollections(
-      const std::vector<std::unique_ptr<HidReportDescriptorItem>>& items);
-
-  uint16_t GetUsagePage() const { return usage_.usage_page; }
-
-  uint16_t GetUsage() const { return usage_.usage; }
-
-  uint32_t GetCollectionType() const { return collection_type_; }
-
-  // Returns true if there are one or more report IDs associated with this
-  // collection.
-  bool HasReportId() const { return !report_ids_.empty(); }
-
-  // Returns information about the collection.
-  mojom::HidCollectionInfoPtr GetDetails(size_t* max_input_report_bits,
-                                         size_t* max_output_report_bits,
-                                         size_t* max_feature_report_bits);
-
-  const HidCollection* GetParent() const { return parent_; }
-
-  const std::vector<std::unique_ptr<HidCollection>>& GetChildren() const {
-    return children_;
-  }
-
-  const std::unordered_map<uint8_t, HidReport>& GetInputReports() const {
-    return input_reports_;
-  }
-
-  const std::unordered_map<uint8_t, HidReport>& GetOutputReports() const {
-    return output_reports_;
-  }
-
-  const std::unordered_map<uint8_t, HidReport>& GetFeatureReports() const {
-    return feature_reports_;
-  }
-
-  // Exposed for testing.
-  void AddChildForTesting(std::unique_ptr<HidCollection> child);
-  void AddReportItem(const HidReportDescriptorItem::Tag tag,
-                     uint32_t report_info,
-                     const HidItemStateTable& state);
-
- private:
-  static void AddCollection(
-      const HidReportDescriptorItem& item,
-      std::vector<std::unique_ptr<HidCollection>>& collections,
-      HidItemStateTable& state);
-
-  // The parent collection, or nullptr if this is a top level collection.
-  HidCollection* const parent_;
-
-  // The children of this collection in the order they were encountered in the
-  // report descriptor.
-  std::vector<std::unique_ptr<HidCollection>> children_;
-
-  // The usage page and usage ID associated with this collection.
-  const mojom::HidUsageAndPage usage_;
-
-  // The type of this collection. Stored as an integer type rather than an enum
-  // to preserve reserved and vendor-defined values.
-  const uint32_t collection_type_;
-
-  // The sequence of report IDs associated with this collection in the order
-  // they were encountered in the report descriptor.
-  std::vector<uint8_t> report_ids_;
-
-  // Maps from report IDs to sequences of report items. Reports are divided by
-  // type (input, output, or feature).
-  std::unordered_map<uint8_t, HidReport> input_reports_;
-  std::unordered_map<uint8_t, HidReport> output_reports_;
-  std::unordered_map<uint8_t, HidReport> feature_reports_;
-};
-
-}  // namespace device
-
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_COLLECTION_H_
diff --git a/services/device/public/cpp/hid/hid_device_filter.h b/services/device/public/cpp/hid/hid_device_filter.h
index bdb9c2e..431d8a47 100644
--- a/services/device/public/cpp/hid/hid_device_filter.h
+++ b/services/device/public/cpp/hid/hid_device_filter.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_DEVICE_PUBLIC_CPP_HID_HID_DEVICE_FILTER_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_DEVICE_FILTER_H_
+#ifndef DEVICE_HID_HID_DEVICE_FILTER_H_
+#define DEVICE_HID_HID_DEVICE_FILTER_H_
 
 #include <stdint.h>
 #include <vector>
@@ -41,4 +41,4 @@
 
 }  // namespace device
 
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_DEVICE_FILTER_H_
+#endif  // DEVICE_HID_HID_DEVICE_FILTER_H_
diff --git a/services/device/public/cpp/hid/hid_item_state_table.cc b/services/device/public/cpp/hid/hid_item_state_table.cc
deleted file mode 100644
index 6acb2cb..0000000
--- a/services/device/public/cpp/hid/hid_item_state_table.cc
+++ /dev/null
@@ -1,153 +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 "services/device/public/cpp/hid/hid_item_state_table.h"
-
-#include <limits>
-
-namespace device {
-
-namespace {
-
-bool IsGlobalItem(HidReportDescriptorItem::Tag tag) {
-  switch (tag) {
-    case HidReportDescriptorItem::kTagUsagePage:
-    case HidReportDescriptorItem::kTagLogicalMinimum:
-    case HidReportDescriptorItem::kTagLogicalMaximum:
-    case HidReportDescriptorItem::kTagPhysicalMinimum:
-    case HidReportDescriptorItem::kTagPhysicalMaximum:
-    case HidReportDescriptorItem::kTagUnitExponent:
-    case HidReportDescriptorItem::kTagUnit:
-    case HidReportDescriptorItem::kTagReportSize:
-    case HidReportDescriptorItem::kTagReportId:
-    case HidReportDescriptorItem::kTagReportCount:
-      return true;
-    default:
-      break;
-  }
-  return false;
-}
-
-uint32_t MaybeCombineUsageAndUsagePage(
-    uint32_t usage,
-    const std::vector<HidItemStateTable::HidGlobalItemState>& global_stack) {
-  // Check if the usage value already has a usage page in the upper bytes.
-  if (usage > std::numeric_limits<uint16_t>::max())
-    return usage;
-  // No global state, just return the usage value.
-  if (global_stack.empty())
-    return usage;
-  // Combine the global usage page with the usage value.
-  return (global_stack.back().usage_page << (sizeof(uint16_t) * 8)) | usage;
-}
-
-}  // namespace
-
-HidItemStateTable::HidItemStateTable() = default;
-HidItemStateTable::~HidItemStateTable() = default;
-
-void HidItemStateTable::SetItemValue(HidReportDescriptorItem::Tag tag,
-                                     uint32_t value) {
-  if (IsGlobalItem(tag)) {
-    if (global_stack.empty())
-      global_stack.emplace_back();
-    auto& global = global_stack.back();
-    switch (tag) {
-      case HidReportDescriptorItem::kTagUsagePage:
-        global.usage_page = value;
-        break;
-      case HidReportDescriptorItem::kTagLogicalMinimum:
-        global.logical_minimum = int32_t{value};
-        break;
-      case HidReportDescriptorItem::kTagLogicalMaximum:
-        global.logical_maximum = int32_t{value};
-        break;
-      case HidReportDescriptorItem::kTagPhysicalMinimum:
-        global.physical_minimum = int32_t{value};
-        break;
-      case HidReportDescriptorItem::kTagPhysicalMaximum:
-        global.physical_maximum = int32_t{value};
-        break;
-      case HidReportDescriptorItem::kTagUnitExponent:
-        global.unit_exponent = value;
-        break;
-      case HidReportDescriptorItem::kTagUnit:
-        global.unit = value;
-        break;
-      case HidReportDescriptorItem::kTagReportSize:
-        global.report_size = value;
-        break;
-      case HidReportDescriptorItem::kTagReportCount:
-        global.report_count = value;
-        break;
-      default:
-        NOTREACHED() << "Unexpected global item in HID report descriptor";
-        break;
-    }
-  } else {
-    switch (tag) {
-      case HidReportDescriptorItem::kTagUsage:
-        local.usages.push_back(
-            MaybeCombineUsageAndUsagePage(value, global_stack));
-        break;
-      case HidReportDescriptorItem::kTagUsageMinimum:
-        local.usage_minimum =
-            MaybeCombineUsageAndUsagePage(value, global_stack);
-        break;
-      case HidReportDescriptorItem::kTagUsageMaximum:
-        local.usage_maximum =
-            MaybeCombineUsageAndUsagePage(value, global_stack);
-        break;
-      case HidReportDescriptorItem::kTagDesignatorIndex:
-        local.designator_index = value;
-        break;
-      case HidReportDescriptorItem::kTagDesignatorMinimum:
-        local.designator_minimum = value;
-        break;
-      case HidReportDescriptorItem::kTagDesignatorMaximum:
-        local.designator_maximum = value;
-        break;
-      case HidReportDescriptorItem::kTagStringIndex:
-        local.string_index = value;
-        break;
-      case HidReportDescriptorItem::kTagStringMinimum:
-        local.string_minimum = value;
-        break;
-      case HidReportDescriptorItem::kTagStringMaximum:
-        local.string_maximum = value;
-        break;
-      case HidReportDescriptorItem::kTagDelimiter:
-        local.delimiter = value;
-        break;
-      default:
-        NOTREACHED() << "Unexpected local item in HID report descriptor";
-        break;
-    }
-  }
-}
-
-HidItemStateTable::HidGlobalItemState::HidGlobalItemState() = default;
-HidItemStateTable::HidGlobalItemState::HidGlobalItemState(
-    const HidGlobalItemState&) = default;
-HidItemStateTable::HidGlobalItemState::~HidGlobalItemState() = default;
-
-HidItemStateTable::HidLocalItemState::HidLocalItemState() = default;
-HidItemStateTable::HidLocalItemState::HidLocalItemState(
-    const HidLocalItemState&) = default;
-HidItemStateTable::HidLocalItemState::~HidLocalItemState() = default;
-
-void HidItemStateTable::HidLocalItemState::Reset() {
-  usages.clear();
-  usage_minimum = 0;
-  usage_maximum = 0;
-  designator_index = 0;
-  designator_minimum = 0;
-  designator_maximum = 0;
-  string_index = 0;
-  string_minimum = 0;
-  string_maximum = 0;
-  delimiter = 0;
-}
-
-}  // namespace device
diff --git a/services/device/public/cpp/hid/hid_item_state_table.h b/services/device/public/cpp/hid/hid_item_state_table.h
deleted file mode 100644
index 2f6ff56..0000000
--- a/services/device/public/cpp/hid/hid_item_state_table.h
+++ /dev/null
@@ -1,85 +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 SERVICES_DEVICE_PUBLIC_CPP_HID_HID_ITEM_STATE_TABLE_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_ITEM_STATE_TABLE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
-#include "services/device/public/mojom/hid.mojom.h"
-
-namespace device {
-
-class HidCollection;
-
-// The item state table, used when parsing the HID report descriptor.
-class HidItemStateTable {
- public:
-  class HidGlobalItemState {
-   public:
-    HidGlobalItemState();
-    HidGlobalItemState(const HidGlobalItemState&);
-    ~HidGlobalItemState();
-
-    // Global items. See section 6.2.2.7 of the HID specifications.
-    uint32_t usage_page = mojom::kPageUndefined;
-    int32_t logical_minimum = 0;
-    int32_t logical_maximum = 0;
-    int32_t physical_minimum = 0;
-    int32_t physical_maximum = 0;
-    uint32_t unit_exponent = 0;
-    uint32_t unit = 0;
-    uint32_t report_size = 0;
-    uint32_t report_count = 0;
-  };
-
-  class HidLocalItemState {
-   public:
-    HidLocalItemState();
-    HidLocalItemState(const HidLocalItemState&);
-    ~HidLocalItemState();
-
-    void Reset();
-
-    // Local items. See section 6.2.2.6 of the HID specifications.
-    std::vector<uint32_t> usages;
-    uint32_t usage_minimum = 0;
-    uint32_t usage_maximum = 0;
-    uint32_t designator_index = 0;
-    uint32_t designator_minimum = 0;
-    uint32_t designator_maximum = 0;
-    uint32_t string_index = 0;
-    uint32_t string_minimum = 0;
-    uint32_t string_maximum = 0;
-    uint32_t delimiter = 0;
-  };
-
-  HidItemStateTable();
-  ~HidItemStateTable();
-
-  // Set the value of a local or global item.
-  void SetItemValue(HidReportDescriptorItem::Tag tag, uint32_t value);
-
-  // The collection that will be modified when main items are encountered.
-  HidCollection* collection = nullptr;
-
-  // The report ID is part of the global item state but is not affected by push
-  // or pop items.
-  uint32_t report_id = 0;
-
-  // The global item state. The global state is represented as a stack in order
-  // to handle push and pop items. The last element holds the current state.
-  std::vector<HidGlobalItemState> global_stack;
-
-  // The local item state.
-  HidLocalItemState local;
-};
-
-}  // namespace device
-
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_ITEM_STATE_TABLE_H_
diff --git a/services/device/public/cpp/hid/hid_report_descriptor.cc b/services/device/public/cpp/hid/hid_report_descriptor.cc
index 2726928..ca71cdbe 100644
--- a/services/device/public/cpp/hid/hid_report_descriptor.cc
+++ b/services/device/public/cpp/hid/hid_report_descriptor.cc
@@ -4,10 +4,7 @@
 
 #include "services/device/public/cpp/hid/hid_report_descriptor.h"
 
-#include <algorithm>
-#include <limits>
-#include <utility>
-
+#include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 
 namespace device {
@@ -22,11 +19,11 @@
   size_t header_index = 0;
   HidReportDescriptorItem* item = nullptr;
   while (header_index < bytes.size()) {
-    items_.push_back(HidReportDescriptorItem::Create(
-        &bytes[header_index], bytes.size() - header_index, item));
-    header_index += items_.back()->GetSize();
+    item = new HidReportDescriptorItem(&bytes[header_index],
+                                       bytes.size() - header_index, item);
+    items_.push_back(base::WrapUnique(item));
+    header_index += item->GetSize();
   }
-  collections_ = HidCollection::BuildCollections(items_);
 }
 
 HidReportDescriptor::~HidReportDescriptor() {}
@@ -34,36 +31,126 @@
 void HidReportDescriptor::GetDetails(
     std::vector<mojom::HidCollectionInfoPtr>* top_level_collections,
     bool* has_report_id,
-    size_t* max_input_report_bytes,
-    size_t* max_output_report_bytes,
-    size_t* max_feature_report_bytes) const {
+    size_t* max_input_report_size,
+    size_t* max_output_report_size,
+    size_t* max_feature_report_size) {
   DCHECK(top_level_collections);
-  DCHECK(has_report_id);
-  DCHECK(max_input_report_bytes);
-  DCHECK(max_output_report_bytes);
-  DCHECK(max_feature_report_bytes);
+  DCHECK(max_input_report_size);
+  DCHECK(max_output_report_size);
+  DCHECK(max_feature_report_size);
   base::STLClearObject(top_level_collections);
 
-  size_t max_input_report_bits = 0;
-  size_t max_output_report_bits = 0;
-  size_t max_feature_report_bits = 0;
-  for (const auto& collection : collections_) {
-    size_t input_bits;
-    size_t output_bits;
-    size_t feature_bits;
-    top_level_collections->push_back(
-        collection->GetDetails(&input_bits, &output_bits, &feature_bits));
-    if (collection->HasReportId())
-      *has_report_id = true;
-    max_input_report_bits = std::max(max_input_report_bits, input_bits);
-    max_output_report_bits = std::max(max_output_report_bits, output_bits);
-    max_feature_report_bits = std::max(max_feature_report_bits, feature_bits);
+  *has_report_id = false;
+  *max_input_report_size = 0;
+  *max_output_report_size = 0;
+  *max_feature_report_size = 0;
+
+  // Global tags data:
+  auto current_usage_page = mojom::kPageUndefined;
+  size_t current_report_count = 0;
+  size_t cached_report_count = 0;
+  size_t current_report_size = 0;
+  size_t cached_report_size = 0;
+  size_t current_input_report_size = 0;
+  size_t current_output_report_size = 0;
+  size_t current_feature_report_size = 0;
+
+  // Local tags data:
+  uint32_t current_usage = 0;
+
+  for (const auto& current_item : items()) {
+    switch (current_item->tag()) {
+      // Main tags:
+      case HidReportDescriptorItem::kTagCollection:
+        if (!current_item->parent() &&
+            (current_usage <= std::numeric_limits<uint16_t>::max())) {
+          // This is a top-level collection.
+          auto collection = mojom::HidCollectionInfo::New();
+          collection->usage = mojom::HidUsageAndPage::New(
+              static_cast<uint16_t>(current_usage),
+              static_cast<uint16_t>(current_usage_page));
+          top_level_collections->push_back(std::move(collection));
+        }
+        break;
+      case HidReportDescriptorItem::kTagInput:
+        current_input_report_size += current_report_count * current_report_size;
+        break;
+      case HidReportDescriptorItem::kTagOutput:
+        current_output_report_size +=
+            current_report_count * current_report_size;
+        break;
+      case HidReportDescriptorItem::kTagFeature:
+        current_feature_report_size +=
+            current_report_count * current_report_size;
+        break;
+
+      // Global tags:
+      case HidReportDescriptorItem::kTagUsagePage:
+        current_usage_page = current_item->GetShortData();
+        break;
+      case HidReportDescriptorItem::kTagReportId:
+        if (top_level_collections->size() > 0) {
+          // Store report ID.
+          top_level_collections->back()->report_ids.push_back(
+              current_item->GetShortData());
+          *has_report_id = true;
+
+          // Update max report sizes.
+          *max_input_report_size =
+              std::max(*max_input_report_size, current_input_report_size);
+          *max_output_report_size =
+              std::max(*max_output_report_size, current_output_report_size);
+          *max_feature_report_size =
+              std::max(*max_feature_report_size, current_feature_report_size);
+
+          // Reset the report sizes for the next report ID.
+          current_input_report_size = 0;
+          current_output_report_size = 0;
+          current_feature_report_size = 0;
+        }
+        break;
+      case HidReportDescriptorItem::kTagReportCount:
+        current_report_count = current_item->GetShortData();
+        break;
+      case HidReportDescriptorItem::kTagReportSize:
+        current_report_size = current_item->GetShortData();
+        break;
+      case HidReportDescriptorItem::kTagPush:
+        // Cache report count and size.
+        cached_report_count = current_report_count;
+        cached_report_size = current_report_size;
+        break;
+      case HidReportDescriptorItem::kTagPop:
+        // Restore cache.
+        current_report_count = cached_report_count;
+        current_report_size = cached_report_size;
+        // Reset cache.
+        cached_report_count = 0;
+        cached_report_size = 0;
+        break;
+
+      // Local tags:
+      case HidReportDescriptorItem::kTagUsage:
+        current_usage = current_item->GetShortData();
+        break;
+
+      default:
+        break;
+    }
   }
 
-  // Convert bits into bytes.
-  *max_input_report_bytes = max_input_report_bits / kBitsPerByte;
-  *max_output_report_bytes = max_output_report_bits / kBitsPerByte;
-  *max_feature_report_bytes = max_feature_report_bits / kBitsPerByte;
+  // Update max report sizes
+  *max_input_report_size =
+      std::max(*max_input_report_size, current_input_report_size);
+  *max_output_report_size =
+      std::max(*max_output_report_size, current_output_report_size);
+  *max_feature_report_size =
+      std::max(*max_feature_report_size, current_feature_report_size);
+
+  // Convert bits into bytes
+  *max_input_report_size /= kBitsPerByte;
+  *max_output_report_size /= kBitsPerByte;
+  *max_feature_report_size /= kBitsPerByte;
 }
 
 }  // namespace device
diff --git a/services/device/public/cpp/hid/hid_report_descriptor.h b/services/device/public/cpp/hid/hid_report_descriptor.h
index 650558d5..337ea6a 100644
--- a/services/device/public/cpp/hid/hid_report_descriptor.h
+++ b/services/device/public/cpp/hid/hid_report_descriptor.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_H_
+#ifndef DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
+#define DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -11,7 +11,6 @@
 #include <memory>
 #include <vector>
 
-#include "services/device/public/cpp/hid/hid_collection.h"
 #include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
 #include "services/device/public/mojom/hid.mojom.h"
 
@@ -28,29 +27,19 @@
     return items_;
   }
 
-  const std::vector<std::unique_ptr<HidCollection>>& collections() const {
-    return collections_;
-  }
-
-  // Return the top-level collections present in the descriptor,
-  // together with max report sizes.
+  // Returns top-level collections present in the descriptor,
+  // together with max report sizes
   void GetDetails(
       std::vector<mojom::HidCollectionInfoPtr>* top_level_collections,
       bool* has_report_id,
-      size_t* max_input_report_bytes,
-      size_t* max_output_report_bytes,
-      size_t* max_feature_report_bytes) const;
+      size_t* max_input_report_size,
+      size_t* max_output_report_size,
+      size_t* max_feature_report_size);
 
  private:
-  // An ordered sequence of HidReportDescriptorItem objects representing the
-  // items that make up a HID report descriptor.
   std::vector<std::unique_ptr<HidReportDescriptorItem>> items_;
-
-  // A hierarchichal representation of the collections and reports described by
-  // the HID report descriptor.
-  std::vector<std::unique_ptr<HidCollection>> collections_;
 };
 
 }  // namespace device
 
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_H_
+#endif  // DEVICE_HID_HID_REPORT_DESCRIPTOR_H_
diff --git a/services/device/public/cpp/hid/hid_report_descriptor_item.h b/services/device/public/cpp/hid/hid_report_descriptor_item.h
index 8b1a64c7e..7f7601fae 100644
--- a/services/device/public/cpp/hid/hid_report_descriptor_item.h
+++ b/services/device/public/cpp/hid/hid_report_descriptor_item.h
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
+#ifndef DEVICE_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
+#define DEVICE_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
 
 #include <stddef.h>
 #include <stdint.h>
 
-#include <memory>
-
 namespace device {
 
 // An element of a HID report descriptor.
 class HidReportDescriptorItem {
  private:
+  friend class HidReportDescriptor;
+
   enum Type {
     kTypeMain = 0,
     kTypeGlobal = 1,
@@ -100,11 +100,7 @@
   // Can be retrieved from GetShortData()
   // when item.tag() == HidReportDescriptorItem::kTagInput
   // or HidReportDescriptorItem::kTagOutput
-  // or HidReportDescriptorItem::kTagFeature.
-  // The ReportInfo struct matches the layout of the bitfield defined in section
-  // 6.2.2.5 of the Device Class Definition for HID v1.11. Pad to 32-bits so it
-  // can be safely cast to and from uint32_t.
-#pragma pack(push, 1)
+  // or HidReportDescriptorItem::kTagFeature
   struct ReportInfo {
     uint8_t data_or_constant : 1;
     uint8_t array_or_variable : 1;
@@ -113,14 +109,10 @@
     uint8_t linear : 1;
     uint8_t preferred : 1;
     uint8_t null : 1;
-    uint8_t is_volatile : 1;
+    uint8_t reserved_1 : 1;
     uint8_t bit_field_or_buffer : 1;
-    uint8_t reserved : 7;
-    uint8_t reserved2[2];
+    uint8_t reserved_2 : 1;
   };
-#pragma pack(pop)
-  static_assert(sizeof(ReportInfo) == sizeof(uint32_t),
-                "incorrect report info size");
 
   // HID collection type.
   // Can be retrieved from GetShortData()
@@ -145,12 +137,6 @@
  public:
   ~HidReportDescriptorItem() {}
 
-  static std::unique_ptr<HidReportDescriptorItem>
-  Create(const uint8_t* bytes, size_t size, HidReportDescriptorItem* previous) {
-    return std::unique_ptr<HidReportDescriptorItem>(
-        new HidReportDescriptorItem(bytes, size, previous));
-  }
-
   // Previous element in report descriptor.
   // Owned by descriptor instance.
   HidReportDescriptorItem* previous() const { return previous_; };
@@ -172,14 +158,13 @@
   // Raw data of a short item.
   // Not valid for a long item.
   uint32_t GetShortData() const;
-  // Size of this item in bytes, including the header.
-  size_t GetSize() const;
 
   static CollectionType GetCollectionTypeFromValue(uint32_t value);
 
  private:
   size_t GetHeaderSize() const;
   size_t payload_size() const { return payload_size_; }
+  size_t GetSize() const;
 
   HidReportDescriptorItem* previous_;
   HidReportDescriptorItem* next_;
@@ -191,4 +176,4 @@
 
 }  // namespace device
 
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
+#endif  // DEVICE_HID_HID_REPORT_DESCRIPTOR_ITEM_H_
diff --git a/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc b/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
index 3f63b6a..9fa56aa 100644
--- a/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
+++ b/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
@@ -5,330 +5,43 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include <limits>
 #include <sstream>
-#include <unordered_map>
-#include <utility>
 
 #include "base/macros.h"
 #include "services/device/hid/test_report_descriptors.h"
 #include "services/device/public/cpp/hid/hid_report_descriptor.h"
-#include "services/device/public/cpp/hid/hid_usage_and_page.h"
 #include "services/device/public/mojom/hid.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
 
-namespace {
-using HidReport = std::vector<std::unique_ptr<HidReportItem>>;
-using HidReportMap = std::unordered_map<uint8_t, HidReport>;
-using HidCollectionVector = std::vector<std::unique_ptr<HidCollection>>;
-
-// HID unit values.
-const uint32_t kUnitCandela = 0x010000e1;
-const uint32_t kUnitDegrees = 0x14;
-const uint32_t kUnitInch = 0x13;
-const uint32_t kUnitNewton = 0xe111;
-const uint32_t kUnitSecond = 0x1001;
-
-// Report info bitfield values. The bits are:
-//   bit 0: Data (0) | Constant (1)
-//   bit 1: Array (0) | Variable (1)
-//   bit 2: Absolute (0) | Relative (1)
-//   bit 3: No Wrap (0) | Wrap (1)
-//   bit 4: Linear (0) | Non-Linear (1)
-//   bit 5: Preferred State (0) | No Preferred State (1)
-//   bit 6: No Null Value (0) | Has Null Value (1)
-//   bit 7: Non-Volatile (0) | Volatile (1)
-//   bit 8: Bit Field (0) | Buffered Bytes (1)
-const uint16_t kNonNullableArray = 0x0000;
-const uint16_t kConstantArray = 0x0001;
-const uint16_t kAbsoluteVariable = 0x0002;
-const uint16_t kConstant = 0x0003;
-const uint16_t kRelativeVariable = 0x0006;
-const uint16_t kNonLinearVariable = 0x0012;
-const uint16_t kNullableArray = 0x0040;
-const uint16_t kNullableAbsoluteVariable = 0x0042;
-const uint16_t kVolatileConstant = 0x0083;
-const uint16_t kBufferedBytes = 0x0102;
-
-// Vendor usage pages.
-const uint16_t kPageVendor02 = mojom::kPageVendor + 0x02;
-const uint16_t kPageVendor05 = mojom::kPageVendor + 0x05;
-const uint16_t kPageVendor80 = mojom::kPageVendor + 0x80;
-
-// Bit-width and mask for the usage ID field in a 32-bit usage value.
-const size_t kUsageIdSizeBits = sizeof(uint16_t) * 8;
-const uint32_t kUsageIdMask = std::numeric_limits<uint16_t>::max();
-
-// Combined usage page and usage ID values. The usage page occupies the high 16
-// bits, the usage ID occupies the low 16 bits.
-const uint32_t kUsageButton = (mojom::kPageButton << kUsageIdSizeBits);
-const uint32_t kUsageConsumer = (mojom::kPageConsumer << kUsageIdSizeBits);
-const uint32_t kUsageConsumerACBack = kUsageConsumer | 0x0224;
-const uint32_t kUsageConsumerACHome = kUsageConsumer | 0x0223;
-const uint32_t kUsageConsumerControl = kUsageConsumer | 0x01;
-const uint32_t kUsageConsumerModeStep = kUsageConsumer | 0x82;
-const uint32_t kUsageDigitizer = (mojom::kPageDigitizer << kUsageIdSizeBits);
-const uint32_t kUsageDigitizerDigitizer = kUsageDigitizer | 0x01;
-const uint32_t kUsageDigitizerBarrelSwitch = kUsageDigitizer | 0x44;
-const uint32_t kUsageDigitizerInRange = kUsageDigitizer | 0x32;
-const uint32_t kUsageDigitizerPuck = kUsageDigitizer | 0x21;
-const uint32_t kUsageDigitizerStylus = kUsageDigitizer | 0x20;
-const uint32_t kUsageDigitizerTipPressure = kUsageDigitizer | 0x30;
-const uint32_t kUsageDigitizerTipSwitch = kUsageDigitizer | 0x42;
-const uint32_t kUsageGenericDesktop =
-    (mojom::kPageGenericDesktop << kUsageIdSizeBits);
-const uint32_t kUsageGenericDesktopDial =
-    kUsageGenericDesktop | mojom::kGenericDesktopDial;
-const uint32_t kUsageGenericDesktopGamePad =
-    kUsageGenericDesktop | mojom::kGenericDesktopGamePad;
-const uint32_t kUsageGenericDesktopHatSwitch =
-    kUsageGenericDesktop | mojom::kGenericDesktopHatSwitch;
-const uint32_t kUsageGenericDesktopJoystick =
-    kUsageGenericDesktop | mojom::kGenericDesktopJoystick;
-const uint32_t kUsageGenericDesktopKeyboard =
-    kUsageGenericDesktop | mojom::kGenericDesktopKeyboard;
-const uint32_t kUsageGenericDesktopMouse =
-    kUsageGenericDesktop | mojom::kGenericDesktopMouse;
-const uint32_t kUsageGenericDesktopPointer =
-    kUsageGenericDesktop | mojom::kGenericDesktopPointer;
-const uint32_t kUsageGenericDesktopRx =
-    kUsageGenericDesktop | mojom::kGenericDesktopRx;
-const uint32_t kUsageGenericDesktopRy =
-    kUsageGenericDesktop | mojom::kGenericDesktopRy;
-const uint32_t kUsageGenericDesktopRz =
-    kUsageGenericDesktop | mojom::kGenericDesktopRz;
-const uint32_t kUsageGenericDesktopSystemControl =
-    kUsageGenericDesktop | mojom::kGenericDesktopSystemControl;
-const uint32_t kUsageGenericDesktopSystemMainMenu =
-    kUsageGenericDesktop | mojom::kGenericDesktopSystemMainMenu;
-const uint32_t kUsageGenericDesktopVbrx =
-    kUsageGenericDesktop | mojom::kGenericDesktopVbrx;
-const uint32_t kUsageGenericDesktopVbry =
-    kUsageGenericDesktop | mojom::kGenericDesktopVbry;
-const uint32_t kUsageGenericDesktopVbrz =
-    kUsageGenericDesktop | mojom::kGenericDesktopVbrz;
-const uint32_t kUsageGenericDesktopVx =
-    kUsageGenericDesktop | mojom::kGenericDesktopVx;
-const uint32_t kUsageGenericDesktopVy =
-    kUsageGenericDesktop | mojom::kGenericDesktopVy;
-const uint32_t kUsageGenericDesktopVz =
-    kUsageGenericDesktop | mojom::kGenericDesktopVz;
-const uint32_t kUsageGenericDesktopWheel =
-    kUsageGenericDesktop | mojom::kGenericDesktopWheel;
-const uint32_t kUsageGenericDesktopX =
-    kUsageGenericDesktop | mojom::kGenericDesktopX;
-const uint32_t kUsageGenericDesktopY =
-    kUsageGenericDesktop | mojom::kGenericDesktopY;
-const uint32_t kUsageGenericDesktopZ =
-    kUsageGenericDesktop | mojom::kGenericDesktopZ;
-const uint32_t kUsageGenericDeviceBatteryStrength =
-    (mojom::kPageGenericDevice << kUsageIdSizeBits) | 0x20;
-const uint32_t kUsageKeyboard = (mojom::kPageKeyboard << kUsageIdSizeBits);
-const uint32_t kUsageKeyboardApplication = kUsageKeyboard | 0x65;
-const uint32_t kUsageKeyboardLeftControl = kUsageKeyboard | 0xe0;
-const uint32_t kUsageKeyboardRightGui = kUsageKeyboard | 0xe7;
-const uint32_t kUsageLedNumLock = (mojom::kPageLed << kUsageIdSizeBits) | 0x01;
-const uint32_t kUsageLedCapsLock = (mojom::kPageLed << kUsageIdSizeBits) | 0x02;
-const uint32_t kUsageLedScrollLock =
-    (mojom::kPageLed << kUsageIdSizeBits) | 0x03;
-const uint32_t kUsageLedCompose = (mojom::kPageLed << kUsageIdSizeBits) | 0x04;
-const uint32_t kUsageLedKana = (mojom::kPageLed << kUsageIdSizeBits) | 0x05;
-const uint32_t kUsageMonitorControl =
-    (mojom::kPageMonitor0 << kUsageIdSizeBits) | 0x01;
-const uint32_t kUsageMonitorEdidInfo =
-    (mojom::kPageMonitor0 << kUsageIdSizeBits) | 0x02;
-const uint32_t kUsageMonitorVdifInfo =
-    (mojom::kPageMonitor0 << kUsageIdSizeBits) | 0x03;
-const uint32_t kUsageMonitorBrightness =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x10;
-const uint32_t kUsageMonitorContrast =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x12;
-const uint32_t kUsageMonitorRedVideoGain =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x16;
-const uint32_t kUsageMonitorGreenVideoGain =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x18;
-const uint32_t kUsageMonitorBlueVideoGain =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x1a;
-const uint32_t kUsageMonitorHorizontalPosition =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x20;
-const uint32_t kUsageMonitorHorizontalSize =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x22;
-const uint32_t kUsageMonitorVerticalPosition =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x30;
-const uint32_t kUsageMonitorVerticalSize =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x32;
-const uint32_t kUsageMonitorTrapezoidalDistortion =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x42;
-const uint32_t kUsageMonitorTilt =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x44;
-const uint32_t kUsageMonitorRedVideoBlackLevel =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x6c;
-const uint32_t kUsageMonitorGreenVideoBlackLevel =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x6e;
-const uint32_t kUsageMonitorBlueVideoBlackLevel =
-    (mojom::kPageMonitor2 << kUsageIdSizeBits) | 0x70;
-const uint32_t kUsagePidSetEffectReport =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0x21;
-const uint32_t kUsagePidDuration =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0x50;
-const uint32_t kUsagePidMagnitude =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0x70;
-const uint32_t kUsagePidLoopCount =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0x7c;
-const uint32_t kUsagePidDCEnableActuators =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0x97;
-const uint32_t kUsagePidStartDelay =
-    (mojom::kPagePidPage << kUsageIdSizeBits) | 0xa7;
-const uint32_t kUsageSimulationAccelerator =
-    (mojom::kPageSimulation << kUsageIdSizeBits) | 0xc4;
-const uint32_t kUsageSimulationBrake =
-    (mojom::kPageSimulation << kUsageIdSizeBits) | 0xc5;
-const uint32_t kUsageVendor = mojom::kPageVendor << kUsageIdSizeBits;
-const uint32_t kUsageVendor02 = kPageVendor02 << kUsageIdSizeBits;
-const uint32_t kUsageVendor05 = kPageVendor05 << kUsageIdSizeBits;
-const uint32_t kUsageVendor80 = kPageVendor80 << kUsageIdSizeBits;
-
-// Report item tags.
-const HidReportDescriptorItem::Tag kInput = HidReportDescriptorItem::kTagInput;
-const HidReportDescriptorItem::Tag kOutput =
-    HidReportDescriptorItem::kTagOutput;
-const HidReportDescriptorItem::Tag kFeature =
-    HidReportDescriptorItem::kTagFeature;
-const HidReportDescriptorItem::CollectionType kCollectionTypeApplication =
-    HidReportDescriptorItem::kCollectionTypeApplication;
-const HidReportDescriptorItem::CollectionType kCollectionTypeLogical =
-    HidReportDescriptorItem::kCollectionTypeLogical;
-const HidReportDescriptorItem::CollectionType kCollectionTypePhysical =
-    kCollectionTypePhysical;
-
-}  // namespace
-
 class HidReportDescriptorTest : public testing::Test {
  protected:
   using HidUsageAndPage = mojom::HidUsageAndPage;
   using HidCollectionInfo = mojom::HidCollectionInfo;
   using HidCollectionInfoPtr = mojom::HidCollectionInfoPtr;
 
+  void SetUp() override { descriptor_ = nullptr; }
+
   void TearDown() override {
-    descriptor_ = nullptr;
-    expected_collection_infos_.clear();
-    expected_collections_.clear();
-    report_id_ = 0;
-    globals_ = HidItemStateTable::HidGlobalItemState();
+    if (descriptor_) {
+      delete descriptor_;
+    }
   }
 
  public:
-  // Add a top-level collection to |expected_collection_infos_|.
-  void AddTopCollectionInfo(HidCollectionInfoPtr collection_info) {
-    expected_collection_infos_.push_back(std::move(collection_info));
-  }
-
-  // Create a new collection and append it to |expected_collections_|.
-  HidCollection* AddTopCollection(
-      uint32_t usage,
-      HidReportDescriptorItem::CollectionType collection_type) {
-    uint16_t usage_page = (usage >> kUsageIdSizeBits) & kUsageIdMask;
-    usage = usage & kUsageIdMask;
-    expected_collections_.push_back(std::make_unique<HidCollection>(
-        nullptr, usage_page, usage, static_cast<uint32_t>(collection_type)));
-    return expected_collections_.back().get();
-  }
-
-  // Create a new collection as a child of |parent|.
-  HidCollection* AddChild(
-      HidCollection* parent,
-      uint32_t usage,
-      HidReportDescriptorItem::CollectionType collection_type) {
-    uint16_t usage_page = (usage >> kUsageIdSizeBits) & kUsageIdMask;
-    usage = usage & kUsageIdMask;
-    parent->AddChildForTesting(std::make_unique<HidCollection>(
-        parent, usage_page, usage, static_cast<uint32_t>(collection_type)));
-    return parent->GetChildren().back().get();
-  }
-
-  // Set the |report_id|. Subsequent report items will be appended to the report
-  // with this ID.
-  void SetReportId(uint8_t report_id) { report_id_ = report_id; }
-
-  // Set the |unit| and |unit_exponent|. Subsequent report items will inherit
-  // these values.
-  void SetUnitAndUnitExponent(uint32_t unit, uint32_t unit_exponent) {
-    globals_.unit = unit;
-    globals_.unit_exponent = unit_exponent;
-  }
-
-  // Set the logical and physical minimums and maximums. Subsequent report items
-  // will inherit these values.
-  void SetLogicalAndPhysicalBounds(uint32_t logical_minimum,
-                                   uint32_t logical_maximum,
-                                   uint32_t physical_minimum,
-                                   uint32_t physical_maximum) {
-    globals_.logical_minimum = int32_t{logical_minimum};
-    globals_.logical_maximum = int32_t{logical_maximum};
-    globals_.physical_minimum = int32_t{physical_minimum};
-    globals_.physical_maximum = int32_t{physical_maximum};
-  }
-
-  // Set the |report_size| in bits, and the |report_count|. Subsequent report
-  // items will inherit these values.
-  void SetReportSizeAndCount(uint32_t report_size, uint32_t report_count) {
-    globals_.report_size = report_size;
-    globals_.report_count = report_count;
-  }
-
-  // Add a report item with a size and count but no usage value.
-  void AddReportConstant(HidCollection* collection,
-                         HidReportDescriptorItem::Tag tag,
-                         uint32_t report_info) {
-    HidItemStateTable state;
-    state.global_stack.push_back(globals_);
-    state.report_id = report_id_;
-    for (const HidCollection* c = collection; c; c = c->GetParent())
-      const_cast<HidCollection*>(c)->AddReportItem(tag, report_info, state);
-  }
-
-  // Add a report item for one or more usages with the same size. The size of
-  // |usage_ids| is not required to be the same as the report count.
-  void AddReportItem(HidCollection* collection,
-                     HidReportDescriptorItem::Tag tag,
-                     uint32_t report_info,
-                     const std::vector<uint32_t>& usage_ids) {
-    HidItemStateTable state;
-    state.global_stack.push_back(globals_);
-    state.report_id = report_id_;
-    state.local.usages = usage_ids;
-    for (const HidCollection* c = collection; c; c = c->GetParent())
-      const_cast<HidCollection*>(c)->AddReportItem(tag, report_info, state);
-  }
-
-  // Add a report item for a range of usages. The item may be a variable or an
-  // array.
-  void AddReportItemRange(HidCollection* collection,
-                          HidReportDescriptorItem::Tag tag,
-                          uint32_t report_info,
-                          uint32_t usage_minimum,
-                          uint32_t usage_maximum) {
-    HidItemStateTable state;
-    state.global_stack.push_back(globals_);
-    state.report_id = report_id_;
-    state.local.usage_minimum = usage_minimum;
-    state.local.usage_maximum = usage_maximum;
-    for (const HidCollection* c = collection; c; c = c->GetParent())
-      const_cast<HidCollection*>(c)->AddReportItem(tag, report_info, state);
-  }
-
   void ValidateDetails(
+      const std::vector<HidCollectionInfoPtr>& expected_collection_infos,
       const bool expected_has_report_id,
       const size_t expected_max_input_report_size,
       const size_t expected_max_output_report_size,
       const size_t expected_max_feature_report_size,
       const uint8_t* bytes,
       size_t size) {
-    descriptor_ = std::make_unique<HidReportDescriptor>(
-        std::vector<uint8_t>(bytes, bytes + size));
+    descriptor_ =
+        new HidReportDescriptor(std::vector<uint8_t>(bytes, bytes + size));
+
     std::vector<HidCollectionInfoPtr> actual_collection_infos;
     bool actual_has_report_id;
     size_t actual_max_input_report_size;
@@ -339,1261 +52,199 @@
                             &actual_max_output_report_size,
                             &actual_max_feature_report_size);
 
-    ASSERT_EQ(expected_collection_infos_.size(),
-              actual_collection_infos.size());
+    ASSERT_EQ(expected_collection_infos.size(), actual_collection_infos.size());
+
     auto actual_info_iter = actual_collection_infos.begin();
-    auto expected_info_iter = expected_collection_infos_.begin();
-    while (expected_info_iter != expected_collection_infos_.end() &&
+    auto expected_info_iter = expected_collection_infos.begin();
+
+    while (expected_info_iter != expected_collection_infos.end() &&
            actual_info_iter != actual_collection_infos.end()) {
       const HidCollectionInfoPtr& expected_info = *expected_info_iter;
       const HidCollectionInfoPtr& actual_info = *actual_info_iter;
+
       ASSERT_EQ(expected_info->usage->usage_page,
                 actual_info->usage->usage_page);
       ASSERT_EQ(expected_info->usage->usage, actual_info->usage->usage);
       ASSERT_THAT(actual_info->report_ids,
                   testing::ContainerEq(expected_info->report_ids));
+
       ++expected_info_iter;
       ++actual_info_iter;
     }
+
     ASSERT_EQ(expected_has_report_id, actual_has_report_id);
     ASSERT_EQ(expected_max_input_report_size, actual_max_input_report_size);
     ASSERT_EQ(expected_max_output_report_size, actual_max_output_report_size);
     ASSERT_EQ(expected_max_feature_report_size, actual_max_feature_report_size);
   }
 
-  static void ValidateReportItem(const HidReportItem& expected,
-                                 const HidReportItem& actual) {
-    uint32_t expected_report_info =
-        *reinterpret_cast<const uint32_t*>(&expected.GetReportInfo());
-    uint32_t actual_report_info =
-        *reinterpret_cast<const uint32_t*>(&actual.GetReportInfo());
-    ASSERT_EQ(expected.GetTag(), actual.GetTag());
-    ASSERT_EQ(expected_report_info, actual_report_info);
-    ASSERT_EQ(expected.GetReportId(), actual.GetReportId());
-    ASSERT_THAT(actual.GetUsages(), testing::ContainerEq(expected.GetUsages()));
-    ASSERT_EQ(expected.GetUsageMinimum(), actual.GetUsageMinimum());
-    ASSERT_EQ(expected.GetUsageMaximum(), actual.GetUsageMaximum());
-    ASSERT_EQ(expected.GetDesignatorMinimum(), actual.GetDesignatorMinimum());
-    ASSERT_EQ(expected.GetDesignatorMaximum(), actual.GetDesignatorMaximum());
-    ASSERT_EQ(expected.GetStringMinimum(), actual.GetStringMinimum());
-    ASSERT_EQ(expected.GetStringMaximum(), actual.GetStringMaximum());
-    ASSERT_EQ(expected.GetLogicalMinimum(), actual.GetLogicalMinimum());
-    ASSERT_EQ(expected.GetLogicalMaximum(), actual.GetLogicalMaximum());
-    ASSERT_EQ(expected.GetPhysicalMinimum(), actual.GetPhysicalMinimum());
-    ASSERT_EQ(expected.GetPhysicalMaximum(), actual.GetPhysicalMaximum());
-    ASSERT_EQ(expected.GetUnitExponent(), actual.GetUnitExponent());
-    ASSERT_EQ(expected.GetUnit(), actual.GetUnit());
-    ASSERT_EQ(expected.GetReportSize(), actual.GetReportSize());
-    ASSERT_EQ(expected.GetReportCount(), actual.GetReportCount());
-  }
-
-  static void ValidateReportMap(const HidReportMap& expected_reports,
-                                const HidReportMap& actual_reports) {
-    for (const auto& expected_entry : expected_reports) {
-      auto find_it = actual_reports.find(expected_entry.first);
-      ASSERT_NE(find_it, actual_reports.end());
-      const auto& expected_report = expected_entry.second;
-      const auto& actual_report = find_it->second;
-      ASSERT_EQ(expected_report.size(), actual_report.size());
-      auto expected_item_iter = expected_report.begin();
-      auto actual_item_iter = actual_report.begin();
-      while (expected_item_iter != expected_report.end() &&
-             actual_item_iter != actual_report.end()) {
-        ValidateReportItem(**expected_item_iter, **actual_item_iter);
-        ++expected_item_iter;
-        ++actual_item_iter;
-      }
-    }
-    ASSERT_EQ(expected_reports.size(), actual_reports.size());
-  }
-
-  static void ValidateLinkCollection(const HidCollection* expected_collection,
-                                     const HidCollection* actual_collection) {
-    ASSERT_EQ(expected_collection->GetUsagePage(),
-              actual_collection->GetUsagePage());
-    ASSERT_EQ(expected_collection->GetUsage(), actual_collection->GetUsage());
-    ASSERT_EQ(expected_collection->GetCollectionType(),
-              actual_collection->GetCollectionType());
-    ValidateReportMap(expected_collection->GetInputReports(),
-                      actual_collection->GetInputReports());
-    ValidateReportMap(expected_collection->GetOutputReports(),
-                      actual_collection->GetOutputReports());
-    ValidateReportMap(expected_collection->GetFeatureReports(),
-                      actual_collection->GetFeatureReports());
-    const auto& expected_children = expected_collection->GetChildren();
-    const auto& actual_children = actual_collection->GetChildren();
-    auto expected_child_iter = expected_children.begin();
-    auto actual_child_iter = actual_children.begin();
-    while (expected_child_iter != expected_children.end() &&
-           actual_child_iter != actual_children.end()) {
-      const HidCollection* expected_child = expected_child_iter->get();
-      const HidCollection* actual_child = actual_child_iter->get();
-      ASSERT_EQ(actual_child->GetParent(), actual_collection);
-      ValidateLinkCollection(expected_child, actual_child);
-      ++expected_child_iter;
-      ++actual_child_iter;
-    }
-    ASSERT_EQ(expected_children.size(), actual_children.size());
-  }
-
-  void ValidateCollections(const uint8_t* bytes, size_t size) {
-    descriptor_ = std::make_unique<HidReportDescriptor>(
-        std::vector<uint8_t>(bytes, bytes + size));
-    const auto& actual_collections = descriptor_->collections();
-    auto actual_collection_iter = actual_collections.begin();
-    auto expected_collection_iter = expected_collections_.begin();
-    while (expected_collection_iter != expected_collections_.end() &&
-           actual_collection_iter != actual_collections.end()) {
-      ValidateLinkCollection(expected_collection_iter->get(),
-                             actual_collection_iter->get());
-      ++expected_collection_iter;
-      ++actual_collection_iter;
-    }
-    ASSERT_EQ(expected_collections_.size(), actual_collections.size());
-  }
-
  private:
-  std::unique_ptr<HidReportDescriptor> descriptor_;
-  std::vector<HidCollectionInfoPtr> expected_collection_infos_;
-  HidCollectionVector expected_collections_;
-  uint8_t report_id_ = 0;
-  HidItemStateTable::HidGlobalItemState globals_;
+  HidReportDescriptor* descriptor_;
 };
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_Digitizer) {
-  auto digitizer = HidCollectionInfo::New();
-  digitizer->usage = HidUsageAndPage::New(0x01, mojom::kPageDigitizer);
-  ASSERT_EQ(IsProtected(*digitizer->usage), false);
-  digitizer->report_ids = {0x01, 0x02, 0x03};
-  AddTopCollectionInfo(std::move(digitizer));
-  ValidateDetails(true, 6, 0, 0, kDigitizer, kDigitizerSize);
-}
+  const uint16_t usage_page = mojom::kPageDigitizer;
+  const uint16_t usage = 0x01;  // Digitizer
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_Digitizer) {
-  auto* top =
-      AddTopCollection(kUsageDigitizerDigitizer, kCollectionTypeApplication);
-  auto* puck = AddChild(top, kUsageDigitizerPuck, kCollectionTypePhysical);
-  SetReportId(0x01);
-  SetLogicalAndPhysicalBounds(0, 12000, 0, 12);
-  SetUnitAndUnitExponent(kUnitInch, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(puck, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetUnitAndUnitExponent(0, 0);
-  SetReportSizeAndCount(1, 3);
-  AddReportItem(puck, kInput, kAbsoluteVariable,
-                {kUsageDigitizerInRange, kUsageDigitizerBarrelSwitch,
-                 kUsageDigitizerTipSwitch});
-  SetReportSizeAndCount(5, 1);
-  AddReportConstant(puck, kInput, kConstant);
-  SetReportId(0x02);
-  auto* stylus_up =
-      AddChild(top, kUsageDigitizerStylus, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 12000, 0, 12);
-  SetUnitAndUnitExponent(kUnitInch, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(stylus_up, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetUnitAndUnitExponent(0, 0);
-  SetReportSizeAndCount(1, 2);
-  AddReportItem(stylus_up, kInput, kAbsoluteVariable, {kUsageDigitizerInRange});
-  SetLogicalAndPhysicalBounds(0, 16, 0, 1);
-  SetReportSizeAndCount(5, 2);
-  AddReportItemRange(stylus_up, kInput, kNullableArray, kUsageButton,
-                     kUsageButton + 16);
-  SetReportSizeAndCount(2, 2);
-  AddReportConstant(stylus_up, kInput, kConstantArray);
-  SetReportId(0x03);
-  auto* stylus_down =
-      AddChild(top, kUsageDigitizerStylus, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 12000, 0, 12);
-  SetUnitAndUnitExponent(kUnitInch, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(stylus_down, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetUnitAndUnitExponent(0, 0);
-  SetReportSizeAndCount(1, 2);
-  AddReportItem(stylus_down, kInput, kAbsoluteVariable,
-                {kUsageDigitizerInRange, kUsageDigitizerBarrelSwitch});
-  SetReportSizeAndCount(1, 6);
-  AddReportConstant(stylus_down, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 127, 0, 45);
-  SetUnitAndUnitExponent(kUnitNewton, 4);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(stylus_down, kInput, kNonLinearVariable,
-                {kUsageDigitizerTipPressure});
-  ValidateCollections(kDigitizer, kDigitizerSize);
+  auto digitizer = HidCollectionInfo::New();
+  digitizer->usage = HidUsageAndPage::New(usage, usage_page);
+  digitizer->report_ids = {0x01, 0x02, 0x03};
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(digitizer));
+  ValidateDetails(expected_infos, true, 6, 0, 0, kDigitizer, kDigitizerSize);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_Keyboard) {
-  auto keyboard = HidCollectionInfo::New();
-  keyboard->usage = HidUsageAndPage::New(mojom::kGenericDesktopKeyboard,
-                                         mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*keyboard->usage), true);
-  AddTopCollectionInfo(std::move(keyboard));
-  ValidateDetails(false, 8, 1, 0, kKeyboard, kKeyboardSize);
-}
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopKeyboard;
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_Keyboard) {
-  auto* top = AddTopCollection(kUsageGenericDesktopKeyboard,
-                               kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 8);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageKeyboardLeftControl,
-                     kUsageKeyboardRightGui);
-  SetReportSizeAndCount(8, 1);
-  AddReportConstant(top, kInput, kConstant);
-  SetReportSizeAndCount(1, 5);
-  AddReportItemRange(top, kOutput, kAbsoluteVariable, kUsageLedNumLock,
-                     kUsageLedKana);
-  SetReportSizeAndCount(3, 1);
-  AddReportConstant(top, kOutput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 101, 0, 0);
-  SetReportSizeAndCount(8, 6);
-  AddReportItemRange(top, kInput, kNonNullableArray, kUsageKeyboard,
-                     kUsageKeyboardApplication);
-  ValidateCollections(kKeyboard, kKeyboardSize);
+  auto keyboard = HidCollectionInfo::New();
+  keyboard->usage = HidUsageAndPage::New(usage, usage_page);
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(keyboard));
+  ValidateDetails(expected_infos, false, 8, 1, 0, kKeyboard, kKeyboardSize);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_Monitor) {
-  auto monitor = HidCollectionInfo::New();
-  monitor->usage = HidUsageAndPage::New(0x01, mojom::kPageMonitor0);
-  ASSERT_EQ(IsProtected(*monitor->usage), false);
-  monitor->report_ids = {0x01, 0x02, 0x03, 0x04, 0x05};
-  AddTopCollectionInfo(std::move(monitor));
-  ValidateDetails(true, 0, 0, 243, kMonitor, kMonitorSize);
-}
+  const uint16_t usage_page = mojom::kPageMonitor0;  // USB monitor
+  const uint16_t usage = 0x01;                       // Monitor control
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_Monitor) {
-  auto* top =
-      AddTopCollection(kUsageMonitorControl, kCollectionTypeApplication);
-  SetReportId(0x01);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 128);
-  AddReportItem(top, kFeature, kBufferedBytes, {kUsageMonitorEdidInfo});
-  SetReportId(0x02);
-  SetReportSizeAndCount(8, 243);
-  AddReportItem(top, kFeature, kBufferedBytes, {kUsageMonitorVdifInfo});
-  SetReportId(0x03);
-  SetUnitAndUnitExponent(kUnitCandela, 0x0e);
-  SetReportSizeAndCount(16, 1);
-  SetLogicalAndPhysicalBounds(0, 200, 0, 0);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageMonitorBrightness});
-  SetReportId(0x04);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageMonitorContrast});
-  SetReportSizeAndCount(16, 6);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  AddReportItem(
-      top, kFeature, kAbsoluteVariable,
-      {kUsageMonitorRedVideoGain, kUsageMonitorGreenVideoGain,
-       kUsageMonitorBlueVideoGain, kUsageMonitorRedVideoBlackLevel,
-       kUsageMonitorGreenVideoBlackLevel, kUsageMonitorBlueVideoBlackLevel});
-  SetReportId(0x05);
-  SetLogicalAndPhysicalBounds(0, 127, 0, 0);
-  AddReportItem(top, kFeature, kAbsoluteVariable,
-                {kUsageMonitorHorizontalPosition, kUsageMonitorHorizontalSize,
-                 kUsageMonitorVerticalPosition, kUsageMonitorVerticalSize,
-                 kUsageMonitorTrapezoidalDistortion, kUsageMonitorTilt});
-  ValidateCollections(kMonitor, kMonitorSize);
+  auto monitor = HidCollectionInfo::New();
+  monitor->usage = HidUsageAndPage::New(usage, usage_page);
+  monitor->report_ids = {1, 2, 3, 4, 5};
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(monitor));
+  ValidateDetails(expected_infos, true, 0, 0, 243, kMonitor, kMonitorSize);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_Mouse) {
-  auto mouse = HidCollectionInfo::New();
-  mouse->usage = HidUsageAndPage::New(mojom::kGenericDesktopMouse,
-                                      mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*mouse->usage), true);
-  AddTopCollectionInfo(std::move(mouse));
-  ValidateDetails(false, 3, 0, 0, kMouse, kMouseSize);
-}
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopMouse;
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_Mouse) {
-  auto* top =
-      AddTopCollection(kUsageGenericDesktopMouse, kCollectionTypeApplication);
-  auto* physical =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 3);
-  AddReportItemRange(physical, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 3);
-  SetReportSizeAndCount(5, 1);
-  AddReportConstant(physical, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0x81, 0x7f, 0, 0);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(physical, kInput, kRelativeVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  ValidateCollections(kMouse, kMouseSize);
+  auto mouse = HidCollectionInfo::New();
+  mouse->usage = HidUsageAndPage::New(usage, usage_page);
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(mouse));
+  ValidateDetails(expected_infos, false, 3, 0, 0, kMouse, kMouseSize);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_LogitechUnifyingReceiver) {
+  const uint16_t usage_page = mojom::kPageVendor;
+  const uint16_t usage_hidpp_short = 0x01;  // Vendor-defined
+  const uint16_t usage_hidpp_long = 0x02;   // Vendor-defined
+  const uint16_t usage_hidpp_dj = 0x04;     // Vendor-defined
+
   auto hidpp_short = HidCollectionInfo::New();
-  hidpp_short->usage = HidUsageAndPage::New(0x01, mojom::kPageVendor);
-  ASSERT_EQ(IsProtected(*hidpp_short->usage), false);
+  hidpp_short->usage = HidUsageAndPage::New(usage_hidpp_short, usage_page);
   hidpp_short->report_ids = {0x10};
   auto hidpp_long = HidCollectionInfo::New();
-  hidpp_long->usage = HidUsageAndPage::New(0x02, mojom::kPageVendor);
-  ASSERT_EQ(IsProtected(*hidpp_long->usage), false);
+  hidpp_long->usage = HidUsageAndPage::New(usage_hidpp_long, usage_page);
   hidpp_long->report_ids = {0x11};
   auto hidpp_dj = HidCollectionInfo::New();
-  hidpp_dj->usage = HidUsageAndPage::New(0x04, mojom::kPageVendor);
-  ASSERT_EQ(IsProtected(*hidpp_dj->usage), false);
+  hidpp_dj->usage = HidUsageAndPage::New(usage_hidpp_dj, usage_page);
   hidpp_dj->report_ids = {0x20, 0x21};
-  AddTopCollectionInfo(std::move(hidpp_short));
-  AddTopCollectionInfo(std::move(hidpp_long));
-  AddTopCollectionInfo(std::move(hidpp_dj));
-  ValidateDetails(true, 31, 31, 0, kLogitechUnifyingReceiver,
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(hidpp_short));
+  expected_infos.push_back(std::move(hidpp_long));
+  expected_infos.push_back(std::move(hidpp_dj));
+  ValidateDetails(expected_infos, true, 31, 31, 0, kLogitechUnifyingReceiver,
                   kLogitechUnifyingReceiverSize);
 }
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_LogitechUnifyingReceiver) {
-  auto* short_collection =
-      AddTopCollection(kUsageVendor + 0x01, kCollectionTypeApplication);
-  SetReportId(0x10);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(short_collection, kInput, kNonNullableArray,
-                {kUsageVendor + 0x01});
-  AddReportItem(short_collection, kOutput, kNonNullableArray,
-                {kUsageVendor + 0x01});
-  auto* long_collection =
-      AddTopCollection(kUsageVendor + 0x02, kCollectionTypeApplication);
-  SetReportId(0x11);
-  SetReportSizeAndCount(8, 19);
-  AddReportItem(long_collection, kInput, kNonNullableArray,
-                {kUsageVendor + 0x02});
-  AddReportItem(long_collection, kOutput, kNonNullableArray,
-                {kUsageVendor + 0x02});
-  auto* dj_collection =
-      AddTopCollection(kUsageVendor + 0x04, kCollectionTypeApplication);
-  SetReportId(0x20);
-  SetReportSizeAndCount(8, 14);
-  AddReportItem(dj_collection, kInput, kNonNullableArray,
-                {kUsageVendor + 0x41});
-  AddReportItem(dj_collection, kOutput, kNonNullableArray,
-                {kUsageVendor + 0x41});
-  SetReportId(0x21);
-  SetReportSizeAndCount(8, 31);
-  AddReportItem(dj_collection, kInput, kNonNullableArray,
-                {kUsageVendor + 0x42});
-  AddReportItem(dj_collection, kOutput, kNonNullableArray,
-                {kUsageVendor + 0x42});
-  ValidateCollections(kLogitechUnifyingReceiver, kLogitechUnifyingReceiverSize);
-}
-
 TEST_F(HidReportDescriptorTest, ValidateDetails_SonyDualshock3) {
-  auto top_info = HidCollectionInfo::New();
-  top_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopJoystick,
-                                         mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*top_info->usage), false);
-  top_info->report_ids = {0x01, 0x02, 0xee, 0xef};
-  AddTopCollectionInfo(std::move(top_info));
-  ValidateDetails(true, 48, 48, 48, kSonyDualshock3, kSonyDualshock3Size);
-}
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopJoystick;
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_SonyDualshock3) {
-  auto* top = AddTopCollection(kUsageGenericDesktopJoystick,
-                               kCollectionTypeApplication);
-  auto* joystick = AddChild(top, kUsageGenericDesktop, kCollectionTypeLogical);
-  SetReportId(0x01);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 1);
-  AddReportConstant(joystick, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetReportSizeAndCount(1, 19);
-  AddReportItemRange(joystick, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 19);
-  SetReportSizeAndCount(1, 13);
-  AddReportConstant(joystick, kInput, kConstant);
-  auto* stick_axes =
-      AddChild(joystick, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 255);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(stick_axes, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopZ, kUsageGenericDesktopRz});
-  SetReportSizeAndCount(8, 39);
-  AddReportItem(joystick, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  SetReportSizeAndCount(8, 48);
-  AddReportItem(joystick, kOutput, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  AddReportItem(joystick, kFeature, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  auto* report_02_collection =
-      AddChild(top, kUsageGenericDesktop, kCollectionTypeLogical);
-  SetReportId(0x02);
-  AddReportItem(report_02_collection, kFeature, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  auto* report_ee_collection =
-      AddChild(top, kUsageGenericDesktop, kCollectionTypeLogical);
-  SetReportId(0xee);
-  AddReportItem(report_ee_collection, kFeature, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  auto* report_ef_collection =
-      AddChild(top, kUsageGenericDesktop, kCollectionTypeLogical);
-  SetReportId(0xef);
-  AddReportItem(report_ef_collection, kFeature, kAbsoluteVariable,
-                {kUsageGenericDesktopPointer});
-  ValidateCollections(kSonyDualshock3, kSonyDualshock3Size);
+  auto top_info = HidCollectionInfo::New();
+  top_info->usage = HidUsageAndPage::New(usage, usage_page);
+  top_info->report_ids = {0x01, 0x02, 0xee, 0xef};
+
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(top_info));
+  ValidateDetails(expected_infos, true, 48, 48, 48, kSonyDualshock3,
+                  kSonyDualshock3Size);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_SonyDualshock4) {
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopGamePad;
+
   auto top_info = HidCollectionInfo::New();
-  top_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopGamePad,
-                                         mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*top_info->usage), false);
+  top_info->usage = HidUsageAndPage::New(usage, usage_page);
   top_info->report_ids = {0x01, 0x05, 0x04, 0x02, 0x08, 0x10, 0x11, 0x12, 0x13,
                           0x14, 0x15, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
                           0x87, 0x88, 0x89, 0x90, 0x91, 0x92, 0x93, 0xa0, 0xa1,
                           0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xf0, 0xf1, 0xf2, 0xa7,
                           0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0};
-  AddTopCollectionInfo(std::move(top_info));
-  ValidateDetails(true, 63, 31, 63, kSonyDualshock4, kSonyDualshock4Size);
-}
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_SonyDualshock4) {
-  auto* top =
-      AddTopCollection(kUsageGenericDesktopGamePad, kCollectionTypeApplication);
-  SetReportId(0x01);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopZ, kUsageGenericDesktopRz});
-  SetLogicalAndPhysicalBounds(0, 7, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(top, kInput, kNullableAbsoluteVariable,
-                {kUsageGenericDesktopHatSwitch});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 315);
-  SetUnitAndUnitExponent(0, 0);
-  SetReportSizeAndCount(1, 14);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 14);
-  SetLogicalAndPhysicalBounds(0, 127, 0, 315);
-  SetReportSizeAndCount(6, 1);
-  AddReportItem(top, kInput, kAbsoluteVariable, {kUsageVendor + 0x20});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 315);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopRx, kUsageGenericDesktopRy});
-  SetReportSizeAndCount(8, 54);
-  AddReportItem(top, kInput, kAbsoluteVariable, {kUsageVendor + 0x21});
-  SetReportId(0x05);
-  SetReportSizeAndCount(8, 31);
-  AddReportItem(top, kOutput, kAbsoluteVariable, {kUsageVendor + 0x22});
-  SetReportId(0x04);
-  SetReportSizeAndCount(8, 36);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x23});
-  SetReportId(0x02);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x24});
-  SetReportId(0x08);
-  SetReportSizeAndCount(8, 3);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x25});
-  SetReportId(0x10);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x26});
-  SetReportId(0x11);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x27});
-  SetReportId(0x12);
-  SetReportSizeAndCount(8, 15);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor02 + 0x21});
-  SetReportId(0x13);
-  SetReportSizeAndCount(8, 22);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor02 + 0x22});
-  SetReportId(0x14);
-  SetReportSizeAndCount(8, 16);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor05 + 0x20});
-  SetReportId(0x15);
-  SetReportSizeAndCount(8, 44);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor05 + 0x21});
-  SetReportId(0x80);
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x20});
-  SetReportId(0x81);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x21});
-  SetReportId(0x82);
-  SetReportSizeAndCount(8, 5);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x22});
-  SetReportId(0x83);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x23});
-  SetReportId(0x84);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x24});
-  SetReportId(0x85);
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x25});
-  SetReportId(0x86);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x26});
-  SetReportId(0x87);
-  SetReportSizeAndCount(8, 35);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x27});
-  SetReportId(0x88);
-  SetReportSizeAndCount(8, 34);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x28});
-  SetReportId(0x89);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x29});
-  SetReportId(0x90);
-  SetReportSizeAndCount(8, 5);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x30});
-  SetReportId(0x91);
-  SetReportSizeAndCount(8, 3);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x31});
-  SetReportId(0x92);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x32});
-  SetReportId(0x93);
-  SetReportSizeAndCount(8, 12);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x33});
-  SetReportId(0xa0);
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x40});
-  SetReportId(0xa1);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x41});
-  SetReportId(0xa2);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x42});
-  SetReportId(0xa3);
-  SetReportSizeAndCount(8, 48);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x43});
-  SetReportId(0xa4);
-  SetReportSizeAndCount(8, 13);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x44});
-  SetReportId(0xa5);
-  SetReportSizeAndCount(8, 21);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x45});
-  SetReportId(0xa6);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x46});
-  SetReportId(0xf0);
-  SetReportSizeAndCount(8, 63);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x47});
-  SetReportId(0xf1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x48});
-  SetReportId(0xf2);
-  SetReportSizeAndCount(8, 15);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x49});
-  SetReportId(0xa7);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x4a});
-  SetReportId(0xa8);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x4b});
-  SetReportId(0xa9);
-  SetReportSizeAndCount(8, 8);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x4c});
-  SetReportId(0xaa);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x4e});
-  SetReportId(0xab);
-  SetReportSizeAndCount(8, 57);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x4f});
-  SetReportId(0xac);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x50});
-  SetReportId(0xad);
-  SetReportSizeAndCount(8, 11);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x51});
-  SetReportId(0xae);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x52});
-  SetReportId(0xaf);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x53});
-  SetReportId(0xb0);
-  SetReportSizeAndCount(8, 63);
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor80 + 0x54});
-  ValidateCollections(kSonyDualshock4, kSonyDualshock4Size);
+  std::vector<HidCollectionInfoPtr> expected_infos;
+  expected_infos.push_back(std::move(top_info));
+  ValidateDetails(expected_infos, true, 63, 31, 63, kSonyDualshock4,
+                  kSonyDualshock4Size);
 }
 
 TEST_F(HidReportDescriptorTest, ValidateDetails_XboxWirelessController) {
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopGamePad;
+
   auto top_info = HidCollectionInfo::New();
-  top_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopGamePad,
-                                         mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*top_info->usage), false);
+  top_info->usage = HidUsageAndPage::New(usage, usage_page);
   top_info->report_ids = {0x01, 0x02, 0x03, 0x04};
-  AddTopCollectionInfo(std::move(top_info));
-  ValidateDetails(true, 15, 8, 0, kMicrosoftXboxWirelessController,
+
+  std::vector<HidCollectionInfoPtr> expected_info;
+  expected_info.push_back(std::move(top_info));
+  ValidateDetails(expected_info, true, 15, 8, 0,
+                  kMicrosoftXboxWirelessController,
                   kMicrosoftXboxWirelessControllerSize);
 }
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_XboxWirelessController) {
-  auto* top =
-      AddTopCollection(kUsageGenericDesktopGamePad, kCollectionTypeApplication);
-  SetReportId(0x01);
-  auto* left_stick =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(left_stick, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  auto* right_stick =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  AddReportItem(right_stick, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopRx, kUsageGenericDesktopRy});
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(top, kInput, kAbsoluteVariable, {kUsageGenericDesktopZ});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(top, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(top, kInput, kAbsoluteVariable, {kUsageGenericDesktopRz});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(top, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(1, 8, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(top, kInput, kNullableAbsoluteVariable,
-                {kUsageGenericDesktopHatSwitch});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetUnitAndUnitExponent(0, 0);
-  AddReportConstant(top, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 10);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 10);
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(top, kInput, kConstant);
-  SetReportId(0x02);
-  auto* mode_collection =
-      AddChild(top, kUsageGenericDesktopSystemControl, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 1);
-  AddReportItem(mode_collection, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopSystemMainMenu});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(7, 1);
-  AddReportConstant(mode_collection, kInput, kConstant);
-  SetReportId(0x03);
-  auto* pid_collection =
-      AddChild(top, kUsagePidSetEffectReport, kCollectionTypeLogical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidDCEnableActuators});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  AddReportConstant(pid_collection, kOutput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidMagnitude});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetUnitAndUnitExponent(kUnitSecond, 0x0e);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidDuration});
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidStartDelay});
-  SetUnitAndUnitExponent(0, 0);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidLoopCount});
-  SetReportId(0x04);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDeviceBatteryStrength});
-  ValidateCollections(kMicrosoftXboxWirelessController,
-                      kMicrosoftXboxWirelessControllerSize);
-}
-
 TEST_F(HidReportDescriptorTest, ValidateDetails_NintendoSwitchProController) {
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage = mojom::kGenericDesktopJoystick;
+
   auto top_info = HidCollectionInfo::New();
-  top_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopJoystick,
-                                         mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*top_info->usage), false);
+  top_info->usage = HidUsageAndPage::New(usage, usage_page);
   top_info->report_ids = {0x30, 0x21, 0x81, 0x01, 0x10, 0x80, 0x82};
-  AddTopCollectionInfo(std::move(top_info));
-  ValidateDetails(true, 63, 63, 0, kNintendoSwitchProController,
+
+  std::vector<HidCollectionInfoPtr> expected_info;
+  expected_info.push_back(std::move(top_info));
+  ValidateDetails(expected_info, true, 63, 63, 0, kNintendoSwitchProController,
                   kNintendoSwitchProControllerSize);
 }
 
-TEST_F(HidReportDescriptorTest,
-       ValidateCollections_NintendoSwitchProController) {
-  auto* top = AddTopCollection(kUsageGenericDesktopJoystick,
-                               kCollectionTypeApplication);
-  SetReportId(0x30);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetUnitAndUnitExponent(0, 0);
-  SetReportSizeAndCount(1, 10);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 10);
-  SetReportSizeAndCount(1, 4);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 11,
-                     kUsageButton + 14);
-  SetReportSizeAndCount(1, 2);
-  AddReportConstant(top, kInput, kConstant);
-  auto* stick_axes =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  SetReportSizeAndCount(16, 4);
-  AddReportItem(stick_axes, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopZ, kUsageGenericDesktopRz});
-  SetLogicalAndPhysicalBounds(0, 7, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopHatSwitch});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 315);
-  SetReportSizeAndCount(1, 4);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 15,
-                     kUsageButton + 18);
-  SetReportSizeAndCount(8, 52);
-  AddReportConstant(top, kInput, kConstant);
-  SetReportId(0x21);
-  SetReportSizeAndCount(8, 63);
-  AddReportItem(top, kInput, kConstant, {kUsageVendor + 0x01});
-  SetReportId(0x81);
-  AddReportItem(top, kInput, kConstant, {kUsageVendor + 0x02});
-  SetReportId(0x01);
-  AddReportItem(top, kOutput, kVolatileConstant, {kUsageVendor + 0x03});
-  SetReportId(0x10);
-  AddReportItem(top, kOutput, kVolatileConstant, {kUsageVendor + 0x04});
-  SetReportId(0x80);
-  AddReportItem(top, kOutput, kVolatileConstant, {kUsageVendor + 0x05});
-  SetReportId(0x82);
-  AddReportItem(top, kOutput, kVolatileConstant, {kUsageVendor + 0x06});
-  ValidateCollections(kNintendoSwitchProController,
-                      kNintendoSwitchProControllerSize);
-}
-
 TEST_F(HidReportDescriptorTest, ValidateDetails_XboxAdaptiveController) {
+  const uint16_t usage_page = mojom::kPageGenericDesktop;
+  const uint16_t usage_gamepad = mojom::kGenericDesktopGamePad;
+  const uint16_t usage_keyboard = mojom::kGenericDesktopKeyboard;
+  const uint8_t report_ids_gamepad[] = {0x01, 0x02, 0x03, 0x04, 0x06,
+                                        0x07, 0x08, 0x09, 0x0a, 0x0b};
+  const size_t report_ids_gamepad_size = base::size(report_ids_gamepad);
+  const uint8_t report_ids_keyboard[] = {0x05};
+  const size_t report_ids_keyboard_size = base::size(report_ids_keyboard);
+
   auto gamepad_info = HidCollectionInfo::New();
-  gamepad_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopGamePad,
-                                             mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*gamepad_info->usage), false);
-  gamepad_info->report_ids = {0x01, 0x02, 0x03, 0x04, 0x06,
-                              0x07, 0x08, 0x09, 0x0a, 0x0b};
+  gamepad_info->usage = HidUsageAndPage::New(usage_gamepad, usage_page);
+  gamepad_info->report_ids.insert(gamepad_info->report_ids.begin(),
+                                  report_ids_gamepad,
+                                  report_ids_gamepad + report_ids_gamepad_size);
+
   auto keyboard_info = HidCollectionInfo::New();
-  keyboard_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopKeyboard,
-                                              mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*keyboard_info->usage), true);
-  keyboard_info->report_ids = {0x05};
-  AddTopCollectionInfo(std::move(gamepad_info));
-  AddTopCollectionInfo(std::move(keyboard_info));
-  ValidateDetails(true, 54, 8, 64, kMicrosoftXboxAdaptiveController,
+  keyboard_info->usage = HidUsageAndPage::New(usage_keyboard, usage_page);
+  keyboard_info->report_ids.insert(
+      keyboard_info->report_ids.begin(), report_ids_keyboard,
+      report_ids_keyboard + report_ids_keyboard_size);
+
+  std::vector<HidCollectionInfoPtr> expected_info;
+  expected_info.push_back(std::move(gamepad_info));
+  expected_info.push_back(std::move(keyboard_info));
+  ValidateDetails(expected_info, true, 54, 8, 64,
+                  kMicrosoftXboxAdaptiveController,
                   kMicrosoftXboxAdaptiveControllerSize);
 }
 
-TEST_F(HidReportDescriptorTest, ValidateCollections_XboxAdaptiveController) {
-  auto* gamepad =
-      AddTopCollection(kUsageGenericDesktopGamePad, kCollectionTypeApplication);
-  SetReportId(0x01);
-  auto* left_stick =
-      AddChild(gamepad, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(left_stick, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY});
-  auto* right_stick =
-      AddChild(gamepad, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  AddReportItem(right_stick, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopZ, kUsageGenericDesktopRz});
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable, {kUsageSimulationBrake});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable,
-                {kUsageSimulationAccelerator});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(1, 8, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(gamepad, kInput, kNullableAbsoluteVariable,
-                {kUsageGenericDesktopHatSwitch});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetUnitAndUnitExponent(0, 0);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 15);
-  AddReportItemRange(gamepad, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 15);
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(1, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable, {kUsageConsumerACBack});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(7, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  auto* left_stick2 =
-      AddChild(gamepad, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  SetReportSizeAndCount(16, 2);
-  AddReportItem(left_stick2, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopVx, kUsageGenericDesktopVy});
-  auto* right_stick2 =
-      AddChild(gamepad, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 0xffff, 0, 0);
-  AddReportItem(right_stick2, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopVbrx, kUsageGenericDesktopVbry});
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable, {kUsageGenericDesktopVz});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1023, 0, 0);
-  SetReportSizeAndCount(10, 1);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable, {kUsageGenericDesktopVbrz});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(6, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(1, 8, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(gamepad, kInput, kNullableAbsoluteVariable,
-                {kUsageGenericDesktopDial});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetUnitAndUnitExponent(0, 0);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 15);
-  AddReportItemRange(gamepad, kInput, kAbsoluteVariable, kUsageButton + 16,
-                     kUsageButton + 30);
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(1, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable, {kUsageConsumerModeStep});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(7, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  auto* consumer_collection =
-      AddChild(gamepad, kUsageConsumerControl, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0x81});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  AddReportConstant(consumer_collection, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0x84});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  AddReportConstant(consumer_collection, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0x85});
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0x99});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  AddReportConstant(consumer_collection, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0x9e});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xa1});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xa2});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xa3});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xa4});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xb9});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xba});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xbb});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xbe});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc0});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc1});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc2});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc3});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc4});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc5});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc6});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc7});
-  AddReportItem(consumer_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumer + 0xc8});
-  SetReportId(0x02);
-  auto* mode_collection =
-      AddChild(gamepad, kUsageConsumerControl, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 1);
-  AddReportItem(mode_collection, kInput, kAbsoluteVariable,
-                {kUsageConsumerACHome});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  SetReportSizeAndCount(7, 1);
-  AddReportConstant(mode_collection, kInput, kConstant);
-  SetReportId(0x03);
-  auto* pid_collection =
-      AddChild(gamepad, kUsagePidSetEffectReport, kCollectionTypeLogical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidDCEnableActuators});
-  SetLogicalAndPhysicalBounds(0, 0, 0, 0);
-  AddReportConstant(pid_collection, kOutput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidMagnitude});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetUnitAndUnitExponent(kUnitSecond, 0x0e);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidDuration});
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidStartDelay});
-  SetUnitAndUnitExponent(0, 0);
-  AddReportItem(pid_collection, kOutput, kAbsoluteVariable,
-                {kUsagePidLoopCount});
-  SetReportId(0x04);
-  AddReportItem(gamepad, kInput, kAbsoluteVariable,
-                {kUsageGenericDeviceBatteryStrength});
-  SetReportId(0x06);
-  auto* report_06_collection =
-      AddChild(gamepad, kUsageVendor + 0x01, kCollectionTypeLogical);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  AddReportItem(report_06_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x01});
-  AddReportItem(report_06_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x02});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  AddReportItem(report_06_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x03});
-  SetReportSizeAndCount(8, 60);
-  AddReportItem(report_06_collection, kFeature, kBufferedBytes,
-                {kUsageVendor + 0x04});
-  SetReportId(0x07);
-  auto* report_07_collection =
-      AddChild(gamepad, kUsageVendor + 0x02, kCollectionTypeLogical);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(report_07_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x05});
-  AddReportItem(report_07_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x06});
-  AddReportItem(report_07_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x07});
-  SetReportId(0x08);
-  auto* report_08_collection =
-      AddChild(gamepad, kUsageVendor + 0x03, kCollectionTypeLogical);
-  AddReportItem(report_08_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x08});
-  AddReportItem(report_08_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x09});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  AddReportItem(report_08_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x0a});
-  SetReportId(0x09);
-  auto* report_09_collection =
-      AddChild(gamepad, kUsageVendor + 0x04, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-  AddReportItem(report_09_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x0b});
-  AddReportItem(report_09_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x0c});
-  AddReportItem(report_09_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x0d});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  AddReportItem(report_09_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x0e});
-  SetReportSizeAndCount(8, 60);
-  AddReportItem(report_09_collection, kFeature, kBufferedBytes,
-                {kUsageVendor + 0x0f});
-  SetReportId(0x0a);
-  auto* report_0a_collection =
-      AddChild(gamepad, kUsageVendor + 0x05, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 0x7fffffff, 0, 0);
-  SetReportSizeAndCount(32, 1);
-  AddReportItem(report_0a_collection, kInput, kAbsoluteVariable,
-                {kUsageVendor + 0x10});
-  AddReportItem(report_0a_collection, kInput, kAbsoluteVariable,
-                {kUsageVendor + 0x11});
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 2);
-  AddReportItem(report_0a_collection, kInput, kAbsoluteVariable,
-                {kUsageVendor + 0x12});
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(report_0a_collection, kInput, kAbsoluteVariable,
-                {kUsageVendor + 0x13});
-  SetReportId(0x0b);
-  auto* report_0b_collection =
-      AddChild(gamepad, kUsageVendor + 0x06, kCollectionTypeLogical);
-  SetLogicalAndPhysicalBounds(0, 100, 0, 0);
-
-  AddReportItem(report_0b_collection, kFeature, kAbsoluteVariable,
-                {kUsageVendor + 0x14});
-  SetReportId(0x05);
-  auto* keyboard = AddTopCollection(kUsageGenericDesktopKeyboard,
-                                    kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 8);
-  AddReportItemRange(keyboard, kInput, kAbsoluteVariable,
-                     kUsageKeyboardLeftControl, kUsageKeyboardRightGui);
-  SetReportSizeAndCount(8, 1);
-  AddReportConstant(keyboard, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 101, 0, 0);
-  SetReportSizeAndCount(8, 6);
-  AddReportItemRange(keyboard, kInput, kNonNullableArray, kUsageKeyboard,
-                     kUsageKeyboardApplication);
-  ValidateCollections(kMicrosoftXboxAdaptiveController,
-                      kMicrosoftXboxAdaptiveControllerSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_NexusPlayerController) {
-  auto gamepad_info = HidCollectionInfo::New();
-  gamepad_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopGamePad,
-                                             mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*gamepad_info->usage), false);
-  gamepad_info->report_ids = {0x01, 0x02};
-  auto status_info = HidCollectionInfo::New();
-  status_info->usage = HidUsageAndPage::New(mojom::kGenericDesktopGamePad,
-                                            mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*status_info->usage), false);
-  status_info->report_ids = {0x03};
-  AddTopCollectionInfo(std::move(gamepad_info));
-  AddTopCollectionInfo(std::move(status_info));
-  ValidateDetails(true, 8, 1, 0, kNexusPlayerController,
-                  kNexusPlayerControllerSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_NexusPlayerController) {
-  auto* gamepad =
-      AddTopCollection(kUsageGenericDesktopGamePad, kCollectionTypeApplication);
-  SetReportId(0x01);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 11);
-  AddReportItem(
-      gamepad, kInput, kAbsoluteVariable,
-      {kUsageButton + 1, kUsageButton + 2, kUsageButton + 4, kUsageButton + 5,
-       kUsageButton + 7, kUsageButton + 8, kUsageButton + 14, kUsageButton + 15,
-       kUsageButton + 13, kUsageConsumerACBack, kUsageConsumerACHome});
-  SetReportSizeAndCount(1, 1);
-  AddReportConstant(gamepad, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 7, 0, 315);
-  SetUnitAndUnitExponent(kUnitDegrees, 0);
-  SetReportSizeAndCount(4, 1);
-  AddReportItem(gamepad, kInput, kNullableAbsoluteVariable,
-                {kUsageGenericDesktopHatSwitch});
-  SetUnitAndUnitExponent(0, 0);
-  auto* axes_collection =
-      AddChild(gamepad, kUsageGenericDesktop, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 255);
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(axes_collection, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopZ, kUsageGenericDesktopRz,
-                 kUsageSimulationBrake, kUsageSimulationAccelerator});
-  SetReportId(0x02);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 255);
-  SetReportSizeAndCount(1, 4);
-  AddReportItem(gamepad, kOutput, kAbsoluteVariable,
-                {kUsageLedNumLock, kUsageLedCapsLock, kUsageLedScrollLock,
-                 kUsageLedCompose});
-  SetReportSizeAndCount(4, 1);
-  AddReportConstant(gamepad, kOutput, kConstant);
-  SetReportId(0x03);
-  auto* status =
-      AddTopCollection(kUsageGenericDesktopGamePad, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 255);
-  SetReportSizeAndCount(8, 1);
-  AddReportItem(status, kInput, kAbsoluteVariable,
-                {kUsageGenericDeviceBatteryStrength});
-  SetReportSizeAndCount(8, 6);
-  AddReportItem(status, kInput, kAbsoluteVariable, {0xffbcbdad});
-  ValidateCollections(kNexusPlayerController, kNexusPlayerControllerSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_SteamControllerKeyboard) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(mojom::kGenericDesktopKeyboard,
-                                     mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*info->usage), true);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 8, 1, 0, kSteamControllerKeyboard,
-                  kSteamControllerKeyboardSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_SteamControllerKeyboard) {
-  auto* top = AddTopCollection(kUsageGenericDesktopKeyboard,
-                               kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 8);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageKeyboardLeftControl,
-                     kUsageKeyboardRightGui);
-  SetReportSizeAndCount(8, 1);
-  AddReportConstant(top, kInput, kConstantArray);
-  SetReportSizeAndCount(1, 5);
-  AddReportItemRange(top, kOutput, kAbsoluteVariable, kUsageLedNumLock,
-                     kUsageLedKana);
-  SetReportSizeAndCount(3, 1);
-  AddReportConstant(top, kOutput, kConstantArray);
-  SetReportSizeAndCount(8, 6);
-  SetLogicalAndPhysicalBounds(0, 101, 0, 0);
-  AddReportItemRange(top, kInput, kNonNullableArray, kUsageKeyboard,
-                     kUsageKeyboardApplication);
-  ValidateCollections(kSteamControllerKeyboard, kSteamControllerKeyboardSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_SteamControllerMouse) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(mojom::kGenericDesktopMouse,
-                                     mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*info->usage), true);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 4, 0, 0, kSteamControllerMouse,
-                  kSteamControllerMouseSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_SteamControllerMouse) {
-  auto* top =
-      AddTopCollection(kUsageGenericDesktopMouse, kCollectionTypeApplication);
-  auto* pointer =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 5);
-  AddReportItemRange(pointer, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 5);
-  SetReportSizeAndCount(3, 1);
-  AddReportConstant(pointer, kInput, kConstantArray);
-  SetLogicalAndPhysicalBounds(0x81, 0x7f, 0, 0);
-  SetReportSizeAndCount(8, 3);
-  AddReportItem(pointer, kInput, kRelativeVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopWheel});
-  ValidateCollections(kSteamControllerMouse, kSteamControllerMouseSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_SteamControllerVendor) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(0x01, mojom::kPageVendor);
-  ASSERT_EQ(IsProtected(*info->usage), false);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 64, 64, 64, kSteamControllerVendor,
-                  kSteamControllerVendorSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_SteamControllerVendor) {
-  auto* top = AddTopCollection(kUsageVendor + 0x01, kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 0);
-  SetReportSizeAndCount(8, 64);
-  AddReportItem(top, kInput, kAbsoluteVariable, {kUsageVendor + 0x01});
-  AddReportItem(top, kOutput, kAbsoluteVariable, {kUsageVendor + 0x01});
-  AddReportItem(top, kFeature, kAbsoluteVariable, {kUsageVendor + 0x01});
-  ValidateCollections(kSteamControllerVendor, kSteamControllerVendorSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_XSkillsUsbAdapter) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(mojom::kGenericDesktopJoystick,
-                                     mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*info->usage), false);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 7, 4, 0, kXSkillsUsbAdapter, kXSkillsUsbAdapterSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_XSkillsUsbAdapter) {
-  auto* top = AddTopCollection(kUsageGenericDesktopJoystick,
-                               kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetReportSizeAndCount(1, 12);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 12);
-  SetReportSizeAndCount(1, 4);
-  AddReportConstant(top, kInput, kConstant);
-  SetLogicalAndPhysicalBounds(0, 255, 0, 255);
-  SetReportSizeAndCount(8, 4);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopRz, kUsageGenericDesktopZ});
-  SetLogicalAndPhysicalBounds(0, 15, 0, 15);
-  SetReportSizeAndCount(4, 2);
-  AddReportItem(top, kInput, kAbsoluteVariable,
-                {kUsageGenericDesktopRx, kUsageGenericDesktopRy});
-  SetReportSizeAndCount(8, 4);
-  AddReportItemRange(top, kOutput, kAbsoluteVariable, kUsageVendor + 0x01,
-                     kUsageVendor + 0x04);
-  ValidateCollections(kXSkillsUsbAdapter, kXSkillsUsbAdapterSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_BelkinNostromoKeyboard) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(mojom::kGenericDesktopKeyboard,
-                                     mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*info->usage), true);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 8, 0, 0, kBelkinNostromoKeyboard,
-                  kBelkinNostromoKeyboardSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateCollections_BelkinNostromoKeyboard) {
-  auto* top = AddTopCollection(kUsageGenericDesktopKeyboard,
-                               kCollectionTypeApplication);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 8);
-  AddReportItemRange(top, kInput, kAbsoluteVariable, kUsageKeyboardLeftControl,
-                     kUsageKeyboardRightGui);
-  SetReportSizeAndCount(8, 1);
-  AddReportConstant(top, kInput, kConstantArray);
-  SetLogicalAndPhysicalBounds(0, 101, 0, 0);
-  SetReportSizeAndCount(8, 6);
-  AddReportItemRange(top, kInput, kNonNullableArray, kUsageKeyboard,
-                     kUsageKeyboardApplication);
-  ValidateCollections(kBelkinNostromoKeyboard, kBelkinNostromoKeyboardSize);
-}
-
-TEST_F(HidReportDescriptorTest, ValidateDetails_BelkinNostromoMouseAndExtra) {
-  auto info = HidCollectionInfo::New();
-  info->usage = HidUsageAndPage::New(mojom::kGenericDesktopMouse,
-                                     mojom::kPageGenericDesktop);
-  ASSERT_EQ(IsProtected(*info->usage), true);
-  AddTopCollectionInfo(std::move(info));
-  ValidateDetails(false, 4, 1, 0, kBelkinNostromoMouseAndExtra,
-                  kBelkinNostromoMouseAndExtraSize);
-}
-
-TEST_F(HidReportDescriptorTest,
-       ValidateCollections_BelkinNostromoMouseAndExtra) {
-  auto* top =
-      AddTopCollection(kUsageGenericDesktopMouse, kCollectionTypeApplication);
-  auto* pointer =
-      AddChild(top, kUsageGenericDesktopPointer, kCollectionTypePhysical);
-  SetLogicalAndPhysicalBounds(0, 1, 0, 0);
-  SetReportSizeAndCount(1, 3);
-  AddReportItemRange(pointer, kInput, kAbsoluteVariable, kUsageButton + 1,
-                     kUsageButton + 3);
-  SetReportSizeAndCount(5, 1);
-  AddReportConstant(pointer, kInput, kConstantArray);
-  SetLogicalAndPhysicalBounds(0x81, 0x7f, 0, 0);
-  SetReportSizeAndCount(8, 3);
-  AddReportItem(pointer, kInput, kRelativeVariable,
-                {kUsageGenericDesktopX, kUsageGenericDesktopY,
-                 kUsageGenericDesktopWheel});
-  SetLogicalAndPhysicalBounds(0, 1, 0, 1);
-  SetReportSizeAndCount(1, 3);
-  AddReportItemRange(pointer, kOutput, kAbsoluteVariable, kUsageLedNumLock,
-                     kUsageLedScrollLock);
-  SetReportSizeAndCount(5, 1);
-  AddReportConstant(pointer, kOutput, kConstantArray);
-  ValidateCollections(kBelkinNostromoMouseAndExtra,
-                      kBelkinNostromoMouseAndExtraSize);
-}
-
 }  // namespace device
diff --git a/services/device/public/cpp/hid/hid_report_item.cc b/services/device/public/cpp/hid/hid_report_item.cc
deleted file mode 100644
index eeab22a..0000000
--- a/services/device/public/cpp/hid/hid_report_item.cc
+++ /dev/null
@@ -1,41 +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 "services/device/public/cpp/hid/hid_report_item.h"
-
-#include "services/device/public/mojom/hid.mojom.h"
-
-namespace device {
-
-HidReportItem::HidReportItem(HidReportDescriptorItem::Tag tag,
-                             uint32_t short_data,
-                             const HidItemStateTable& state)
-    : tag_(tag),
-      report_info_(
-          *reinterpret_cast<HidReportDescriptorItem::ReportInfo*>(&short_data)),
-      report_id_(state.report_id),
-      local_(state.local),
-      global_(state.global_stack.empty()
-                  ? HidItemStateTable::HidGlobalItemState()
-                  : state.global_stack.back()),
-      is_range_(state.local.usage_minimum != state.local.usage_maximum),
-      has_strings_(state.local.string_index ||
-                   (state.local.string_minimum != state.local.string_maximum)),
-      has_designators_(
-          state.local.designator_index ||
-          (state.local.designator_minimum != state.local.designator_maximum)) {
-  global_.usage_page = mojom::kPageUndefined;
-  if (state.local.string_index) {
-    local_.string_minimum = state.local.string_index;
-    local_.string_maximum = state.local.string_index;
-  }
-  if (state.local.designator_index) {
-    local_.designator_minimum = state.local.designator_index;
-    local_.designator_maximum = state.local.designator_index;
-  }
-}
-
-HidReportItem::~HidReportItem() = default;
-
-}  // namespace device
diff --git a/services/device/public/cpp/hid/hid_report_item.h b/services/device/public/cpp/hid/hid_report_item.h
deleted file mode 100644
index eae86f8..0000000
--- a/services/device/public/cpp/hid/hid_report_item.h
+++ /dev/null
@@ -1,135 +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 SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_ITEM_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_ITEM_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "services/device/public/cpp/hid/hid_item_state_table.h"
-#include "services/device/public/cpp/hid/hid_report_descriptor_item.h"
-
-namespace device {
-
-class HidReportItem {
- public:
-  HidReportItem(HidReportDescriptorItem::Tag,
-                uint32_t,
-                const HidItemStateTable&);
-  ~HidReportItem();
-
-  static std::unique_ptr<HidReportItem> Create(HidReportDescriptorItem::Tag tag,
-                                               uint32_t short_data,
-                                               const HidItemStateTable& state) {
-    return std::make_unique<HidReportItem>(tag, short_data, state);
-  }
-
-  HidReportDescriptorItem::Tag GetTag() const { return tag_; }
-
-  const HidReportDescriptorItem::ReportInfo& GetReportInfo() const {
-    return report_info_;
-  }
-
-  // Returns the report ID of the report this item is part of.
-  uint8_t GetReportId() const { return report_id_; }
-
-  // Returns true if this item defines a usage range (minimum and maximum), or
-  // false if it defines a list of usages.
-  bool IsRange() const { return is_range_; }
-
-  // Returns true if the usage or usage range has one or more strings.
-  bool HasStrings() const { return has_strings_; }
-
-  // Returns true if the usage or usage range has one or more designators.
-  bool HasDesignators() const { return has_designators_; }
-
-  // Returns true if the report item is an absolute type, or false if it is a
-  // relative type.
-  bool IsAbsolute() const { return !report_info_.absolute_or_relative; }
-
-  // Returns true if the report item is an array type. (e.g., keyboard scan
-  // codes)
-  bool IsArray() const { return !report_info_.array_or_variable; }
-
-  // If |is_range| is false, Usages returns the list of usages associated with
-  // this item.
-  const std::vector<uint32_t>& GetUsages() const { return local_.usages; }
-
-  // If |is_range| is true, UsageMinimum and UsageMaximum return the minimum and
-  // maximum for the range of usages associated with this item.
-  uint16_t GetUsageMinimum() const { return local_.usage_minimum; }
-  uint16_t GetUsageMaximum() const { return local_.usage_maximum; }
-
-  // If |has_strings| is true, StringMinimum and StringMaximum return the
-  // minimum and maximum string indices associated with this item.
-  uint16_t GetStringMinimum() const { return local_.string_minimum; }
-  uint16_t GetStringMaximum() const { return local_.string_maximum; }
-
-  // If |has_designators| is true, DesignatorMinimum and DesignatorMaximum
-  // return the minimum and maximum designator indices associated with this
-  // item.
-  uint16_t GetDesignatorMinimum() const { return local_.designator_minimum; }
-  uint16_t GetDesignatorMaximum() const { return local_.designator_maximum; }
-
-  // Returns true if the item supports reporting a value outside the logical
-  // range as a null value.
-  bool HasNull() const { return report_info_.null; }
-
-  // Returns the width of each field defined by this item, in bits.
-  uint16_t GetReportSize() const { return global_.report_size; }
-
-  // Returns the number of fields defined by this item.
-  uint16_t GetReportCount() const { return global_.report_count; }
-
-  // Returns a 32-bit value representing a unit definition for the current item,
-  // or 0 if the item is not assigned a unit.
-  uint32_t GetUnit() const { return global_.unit; }
-
-  // Returns a value representing the exponent applied to the assigned unit.
-  uint32_t GetUnitExponent() const { return global_.unit_exponent; }
-
-  // Returns signed values representing the minimum and maximum values for this
-  // item.
-  int32_t GetLogicalMinimum() const { return global_.logical_minimum; }
-  int32_t GetLogicalMaximum() const { return global_.logical_maximum; }
-
-  // Returns signed values representing the minimum and maximum values for this
-  // item in the declared units, for scaling purposes.
-  int32_t GetPhysicalMinimum() const { return global_.physical_minimum; }
-  int32_t GetPhysicalMaximum() const { return global_.physical_maximum; }
-
- private:
-  // The tag of the main item that generated this report item. Must be
-  // kItemInput, kItemOutput, or kItemFeature.
-  HidReportDescriptorItem::Tag tag_;
-
-  // Data associated with the main item that generated this report item.
-  HidReportDescriptorItem::ReportInfo report_info_;
-
-  // The report ID associated with this report, or 0 if none.
-  uint8_t report_id_;
-
-  // A copy of the local and global item state when this report item was
-  // encountered.
-  HidItemStateTable::HidLocalItemState local_;
-  HidItemStateTable::HidGlobalItemState global_;
-
-  // If true, the usages for this item are defined by |local.usage_minimum| and
-  // |local.usage_maximum|. If false, the usages are defomed by |local.usages|.
-  bool is_range_;
-
-  // If true, one or more strings are associated with this item.
-  bool has_strings_;
-
-  // If true, one or more designators are associated with this item.
-  bool has_designators_;
-};
-
-}  // namespace device
-
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_REPORT_ITEM_H_
diff --git a/services/device/public/cpp/hid/hid_usage_and_page.h b/services/device/public/cpp/hid/hid_usage_and_page.h
index b080797..4c82d88 100644
--- a/services/device/public/cpp/hid/hid_usage_and_page.h
+++ b/services/device/public/cpp/hid/hid_usage_and_page.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_DEVICE_PUBLIC_CPP_HID_HID_USAGE_AND_PAGE_H_
-#define SERVICES_DEVICE_PUBLIC_CPP_HID_HID_USAGE_AND_PAGE_H_
+#ifndef DEVICE_HID_PUBLIC_CPP_HID_USAGE_AND_PAGE_H_
+#define DEVICE_HID_PUBLIC_CPP_HID_USAGE_AND_PAGE_H_
 
 #include "services/device/public/mojom/hid.mojom.h"
 
@@ -14,4 +14,4 @@
 
 }  // namespace device
 
-#endif  // SERVICES_DEVICE_PUBLIC_CPP_HID_HID_USAGE_AND_PAGE_H_
+#endif  // DEVICE_HID_PUBLIC_CPP_HID_USAGE_AND_PAGE_H_
diff --git a/services/device/public/mojom/hid.mojom b/services/device/public/mojom/hid.mojom
index 208a511..1de8f6f2 100644
--- a/services/device/public/mojom/hid.mojom
+++ b/services/device/public/mojom/hid.mojom
@@ -16,7 +16,6 @@
 const uint16 kPageVirtualReality = 0x03;
 const uint16 kPageSport = 0x04;
 const uint16 kPageGame = 0x05;
-const uint16 kPageGenericDevice = 0x06;
 const uint16 kPageKeyboard = 0x07;
 const uint16 kPageLed = 0x08;
 const uint16 kPageButton = 0x09;
diff --git a/services/device/serial/serial_port_manager_impl_unittest.cc b/services/device/serial/serial_port_manager_impl_unittest.cc
index 4a8d274..c41ebc9 100644
--- a/services/device/serial/serial_port_manager_impl_unittest.cc
+++ b/services/device/serial/serial_port_manager_impl_unittest.cc
@@ -87,24 +87,19 @@
 
 class SerialPortManagerImplTest : public DeviceServiceTestBase {
  public:
-  SerialPortManagerImplTest() {
-    blockable_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
-  }
+  SerialPortManagerImplTest() = default;
   ~SerialPortManagerImplTest() override = default;
 
  protected:
   void SetUp() override { DeviceServiceTestBase::SetUp(); }
 
   void BindSerialPortManager(mojom::SerialPortManagerRequest request) {
-    blockable_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&CreateAndBindOnBlockableRunner,
-                                  std::move(request), io_thread_.task_runner(),
-                                  base::ThreadTaskRunnerHandle::Get()));
+    file_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&CreateAndBindOnBlockableRunner, std::move(request),
+                       io_task_runner_, base::ThreadTaskRunnerHandle::Get()));
   }
 
-  scoped_refptr<base::SequencedTaskRunner> blockable_runner_;
-
   DISALLOW_COPY_AND_ASSIGN(SerialPortManagerImplTest);
 };
 
diff --git a/services/network/cors/cors_url_loader.h b/services/network/cors/cors_url_loader.h
index cc28bf3..84ca043d 100644
--- a/services/network/cors/cors_url_loader.h
+++ b/services/network/cors/cors_url_loader.h
@@ -13,6 +13,7 @@
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/cpp/cors/preflight_timing_info.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc
index b2c0f0bd..af0e3d37 100644
--- a/services/network/cors/preflight_controller.cc
+++ b/services/network/cors/preflight_controller.cc
@@ -18,6 +18,7 @@
 #include "services/network/public/cpp/cors/cors_error_status.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "url/gurl.h"
 
 namespace network {
diff --git a/services/network/public/cpp/cross_thread_shared_url_loader_factory_info.cc b/services/network/public/cpp/cross_thread_shared_url_loader_factory_info.cc
index 6210048..0da8c691 100644
--- a/services/network/public/cpp/cross_thread_shared_url_loader_factory_info.cc
+++ b/services/network/public/cpp/cross_thread_shared_url_loader_factory_info.cc
@@ -12,6 +12,7 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace network {
diff --git a/services/network/public/cpp/wrapper_shared_url_loader_factory.h b/services/network/public/cpp/wrapper_shared_url_loader_factory.h
index fe0ebdc5..e0969c4 100644
--- a/services/network/public/cpp/wrapper_shared_url_loader_factory.h
+++ b/services/network/public/cpp/wrapper_shared_url_loader_factory.h
@@ -7,6 +7,7 @@
 
 #include "base/component_export.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace network {
diff --git a/services/network/test/test_url_loader_factory.cc b/services/network/test/test_url_loader_factory.cc
index 60e83d5..f2195dfc 100644
--- a/services/network/test/test_url_loader_factory.cc
+++ b/services/network/test/test_url_loader_factory.cc
@@ -11,6 +11,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/test/test_utils.h"
 
 namespace network {
diff --git a/services/network/test/test_url_loader_factory.h b/services/network/test/test_url_loader_factory.h
index 609f402d..d5d15a13 100644
--- a/services/network/test/test_url_loader_factory.h
+++ b/services/network/test/test_url_loader_factory.h
@@ -14,6 +14,7 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "net/http/http_status_code.h"
 #include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace network {
diff --git a/services/network/tls_socket_factory.cc b/services/network/tls_socket_factory.cc
index 4934404..a401acb 100644
--- a/services/network/tls_socket_factory.cc
+++ b/services/network/tls_socket_factory.cc
@@ -53,7 +53,8 @@
           url_request_context->transport_security_state(),
           url_request_context->cert_transparency_verifier(),
           url_request_context->ct_policy_enforcer(),
-          std::string() /* TODO(rsleevi): Ensure a proper unique shard. */),
+          nullptr /* Disables SSL session caching */,
+          std::string()),
       client_socket_factory_(nullptr),
       ssl_config_service_(url_request_context->ssl_config_service()) {
   if (http_context) {
diff --git a/services/shape_detection/face_detection_provider_impl.cc b/services/shape_detection/face_detection_provider_impl.cc
index e552ed06..7fb8d76 100644
--- a/services/shape_detection/face_detection_provider_impl.cc
+++ b/services/shape_detection/face_detection_provider_impl.cc
@@ -4,6 +4,8 @@
 
 #include "services/shape_detection/face_detection_provider_impl.h"
 
+#include "services/shape_detection/public/mojom/facedetection.mojom.h"
+
 namespace shape_detection {
 
 void FaceDetectionProviderImpl::CreateFaceDetection(
diff --git a/services/ws/test_change_tracker.cc b/services/ws/test_change_tracker.cc
index 76f100c..178cfc9 100644
--- a/services/ws/test_change_tracker.cc
+++ b/services/ws/test_change_tracker.cc
@@ -13,6 +13,7 @@
 #include "mojo/public/cpp/bindings/map.h"
 #include "services/ws/common/util.h"
 #include "services/ws/ids.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/gfx/geometry/point_conversions.h"
 
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
index db27a87..7a92bf5 100644
--- a/storage/browser/blob/blob_registry_impl.cc
+++ b/storage/browser/blob/blob_registry_impl.cc
@@ -17,6 +17,8 @@
 #include "storage/browser/blob/blob_storage_context.h"
 #include "storage/browser/blob/blob_transport_strategy.h"
 #include "storage/browser/blob/blob_url_store_impl.h"
+#include "third_party/blink/public/mojom/blob/data_element.mojom.h"
+#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
 
 namespace storage {
 
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc
index 9c4b14d..ea98f0e3 100644
--- a/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -28,6 +28,8 @@
 #include "storage/browser/test/mock_bytes_provider.h"
 #include "storage/browser/test/mock_special_storage_policy.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/blob/data_element.mojom.h"
+#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
 
 namespace storage {
 
diff --git a/storage/browser/blob/blob_transport_strategy.cc b/storage/browser/blob/blob_transport_strategy.cc
index ea44138b..8dbaa33 100644
--- a/storage/browser/blob/blob_transport_strategy.cc
+++ b/storage/browser/blob/blob_transport_strategy.cc
@@ -10,6 +10,7 @@
 #include "base/containers/circular_deque.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "storage/browser/blob/blob_data_builder.h"
+#include "third_party/blink/public/mojom/blob/data_element.mojom.h"
 
 namespace storage {
 
diff --git a/storage/browser/blob/blob_transport_strategy_unittest.cc b/storage/browser/blob/blob_transport_strategy_unittest.cc
index c0570e6..63e67f5 100644
--- a/storage/browser/blob/blob_transport_strategy_unittest.cc
+++ b/storage/browser/blob/blob_transport_strategy_unittest.cc
@@ -20,6 +20,7 @@
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/test/mock_bytes_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/blob/data_element.mojom.h"
 
 namespace storage {
 
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
index 5a6fed4c..5fbd785 100644
--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/blob/blob_impl.h"
 #include "storage/browser/blob/blob_storage_context.h"
diff --git a/storage/browser/test/mock_bytes_provider.h b/storage/browser/test/mock_bytes_provider.h
index 41a634a..0dbf4981 100644
--- a/storage/browser/test/mock_bytes_provider.h
+++ b/storage/browser/test/mock_bytes_provider.h
@@ -6,6 +6,7 @@
 #define STORAGE_BROWSER_TEST_MOCK_BYTES_PROVIDER_H_
 
 #include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"
+#include "third_party/blink/public/mojom/blob/data_element.mojom.h"
 
 namespace storage {
 
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html
index 3227676..82d92ee 100644
--- a/styleguide/c++/c++11.html
+++ b/styleguide/c++/c++11.html
@@ -319,6 +319,14 @@
 </tr>
 
 <tr>
+<td>thread_local storage class</td>
+<td><code>thread_local int foo = 1;</code></td>
+<td>Puts variables into thread local storage.</td>
+<td><a href="http://en.cppreference.com/w/cpp/language/storage_duration">Storage duration</a></td>
+<td>Allowed only for POD data. (<a href="https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/2msN8k3Xzgs">discussion</a>, <a href="https://groups.google.com/a/chromium.org/forum/#!topic/cxx/h7O5BdtWCZw">fork</a>). Use <a href="https://cs.chromium.org/chromium/src/base/threading/sequence_local_storage_slot.h">SequenceLocalStorageSlot</a> for sequence support, and <a href="https://cs.chromium.org/chromium/src/base/threading/thread_local.h">ThreadLocal</a>/<a href="https://cs.chromium.org/chromium/src/base/threading/thread_local_storage.h">ThreadLocalStorage</a> for other cases.</td>
+</tr>
+
+<tr>
 <td>Type Aliases ("using" instead of "typedef")</td>
 <td><code>using <i>new_alias</i> = <i>typename</i></code></td>
 <td>Allows parameterized typedefs</td>
@@ -776,14 +784,6 @@
 <td>Banned in the <a href="https://google.github.io/styleguide/cppguide.html#Operator_Overloading">Google Style Guide</a>.</td>
 </tr>
 
-<tr>
-<td>thread_local storage class</td>
-<td><code>thread_local int foo = 1;</code></td>
-<td>Puts variables into thread local storage.</td>
-<td><a href="http://en.cppreference.com/w/cpp/language/storage_duration">Storage duration</a></td>
-<td>Some surprising effects on Mac (<a href="https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/2msN8k3Xzgs">discussion</a>, <a href="https://groups.google.com/a/chromium.org/forum/#!topic/cxx/h7O5BdtWCZw">fork</a>). Use <a href="https://cs.chromium.org/chromium/src/base/threading/sequence_local_storage_slot.h">SequenceLocalStorageSlot</a> for sequence support, and <a href="https://cs.chromium.org/chromium/src/base/threading/thread_local.h">ThreadLocal</a>/<a href="https://cs.chromium.org/chromium/src/base/threading/thread_local_storage.h">ThreadLocalStorage</a> otherwise.</td>
-</tr>
-
 </tbody>
 </table>
 
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 1c0307de..869dfd7 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -539,6 +539,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -805,6 +806,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -1233,6 +1235,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -1499,6 +1502,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 9334f2f..69b7bec0 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -90,6 +90,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -352,6 +353,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -762,6 +764,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -1270,6 +1273,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -1936,6 +1940,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -2444,6 +2449,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -3098,6 +3104,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -3606,6 +3613,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -9464,6 +9472,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -9708,6 +9717,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -10104,6 +10114,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -10430,6 +10441,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -10904,6 +10916,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -11148,6 +11161,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -11472,6 +11486,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -11694,6 +11709,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -12041,6 +12057,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -12285,6 +12302,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -12633,6 +12651,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -12877,6 +12896,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -13220,6 +13240,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -13458,6 +13479,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -13906,6 +13928,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -14186,6 +14209,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -14592,6 +14616,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -14889,6 +14914,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -15262,6 +15288,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -15559,6 +15586,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -15932,6 +15960,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -16229,6 +16258,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -16602,6 +16632,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -16899,6 +16930,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -17272,6 +17304,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -17569,6 +17602,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -17942,6 +17976,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -18239,6 +18274,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -18612,6 +18648,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -18909,6 +18946,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -19282,6 +19320,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -19579,6 +19618,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -19952,6 +19992,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -20249,6 +20290,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -20622,6 +20664,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -20919,6 +20962,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -21292,6 +21336,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -21536,6 +21581,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -21934,6 +21980,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -22431,6 +22478,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 0974db2..4b6b4e0c 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -415,6 +415,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -653,6 +654,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -2617,6 +2619,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -2904,6 +2907,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -6077,6 +6081,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -6321,6 +6326,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -6829,6 +6835,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "isolate_coverage_data": true,
@@ -7108,6 +7115,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "isolate_coverage_data": true,
@@ -10231,6 +10239,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -10475,6 +10484,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -11207,6 +11217,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -11753,6 +11764,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -12542,6 +12554,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2,ViewsBrowserWindows",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -12865,6 +12878,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2,ViewsBrowserWindows",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 249c697..23309e82 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1123,6 +1123,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -1367,6 +1368,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -1885,6 +1887,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -2129,6 +2132,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -2587,6 +2591,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -2831,6 +2836,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -3346,6 +3352,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -3765,6 +3772,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 88d47af..b5c62a65 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -153,6 +153,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -529,6 +530,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -1297,6 +1299,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -1673,6 +1676,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -2458,6 +2462,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -2900,6 +2905,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -3668,6 +3674,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -4044,6 +4051,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -4805,6 +4813,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -5181,6 +5190,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 39a6b42..8b3d577 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -2759,6 +2759,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -3069,6 +3070,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -3583,6 +3585,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -3863,6 +3866,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -4302,6 +4306,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -4653,6 +4658,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -5374,6 +5380,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -5941,6 +5948,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -6842,6 +6850,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -7402,6 +7411,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -8123,6 +8133,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -8440,6 +8451,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -8912,6 +8924,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -9192,6 +9205,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter",
           "--test-launcher-print-test-stdio=always"
         ],
@@ -9762,6 +9776,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -10270,6 +10285,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index f93abd10..594b693 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -117,6 +117,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -414,6 +415,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -995,6 +997,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -1549,6 +1552,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -2739,6 +2743,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "experiment_percentage": 100,
@@ -3568,6 +3573,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -3823,6 +3829,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
@@ -4335,6 +4342,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "name": "webui_polymer2_browser_tests",
@@ -4632,6 +4640,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "name": "webui_polymer2_interactive_ui_tests",
diff --git a/testing/buildbot/filters/webui_polymer2_browser_tests.filter b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
index e4cf8f2..bead418 100644
--- a/testing/buildbot/filters/webui_polymer2_browser_tests.filter
+++ b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
@@ -8,8 +8,9 @@
 # in this file.
 #
 # NOTE: Please do not add new exclusions to this file. Instead fix the test in
-# question such that it passes with --enable-features=WebUIPolymer2 (and with
-# GN optimize_webui=true and false).
+# question such that it passes with --enable-features=WebUIPolymer2 and, on
+# Chrome OS, --disable-features=WebUIPolymer2Exceptions (and with GN
+# optimize_webui=true and false).
 #
 # Note that some of these tests only fail inconsistently (like with
 # --gtest_repeat=5, but might pass on a single invocation).
diff --git a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter
index 61cf9be3..308818cbb 100644
--- a/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter
+++ b/testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter
@@ -7,8 +7,9 @@
 # be fixed and moved to the "Passing tests" section further down in this file.
 #
 # NOTE: Please do not add new exclusions to this file. Instead fix the test in
-# question such that it passes with --enable-features=WebUIPolymer2 (and with
-# GN optimize_webui=true and false).
+# question such that it passes with --enable-features=WebUIPolymer2 and, on
+# Chrome OS, --disable-features=WebUIPolymer2Exceptions (and with GN
+# optimize_webui=true and false).
 
 # Failing on Chrome OS only:
 -LoginUITest.OobeCatchException
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index f4f24f9..f43c84e 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -4036,6 +4036,7 @@
       'webui_polymer2_browser_tests': {
         'args': [
           '--enable-features=WebUIPolymer2',
+          '--disable-features=WebUIPolymer2Exceptions',
           '--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter',
         ],
         'swarming': {
@@ -4046,6 +4047,7 @@
       'webui_polymer2_interactive_ui_tests': {
         'args': [
           '--enable-features=WebUIPolymer2',
+          '--disable-features=WebUIPolymer2Exceptions',
           '--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter',
         ],
         'test': 'interactive_ui_tests',
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index b7e5c8e4..7b007528 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -103,6 +103,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
         ],
         "isolate_coverage_data": true,
@@ -382,6 +383,7 @@
       {
         "args": [
           "--enable-features=WebUIPolymer2",
+          "--disable-features=WebUIPolymer2Exceptions",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_interactive_ui_tests.filter"
         ],
         "isolate_coverage_data": true,
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 96e1319..1f3e44b42 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -77,7 +77,7 @@
 
 // Onion souping for all DOMStorage. https://crbug.com/781870
 const base::Feature kOnionSoupDOMStorage{"OnionSoupDOMStorage",
-                                         base::FEATURE_ENABLED_BY_DEFAULT};
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enable browser-initiated dedicated worker script loading
 // (PlzDedicatedWorker). https://crbug.com/906991
diff --git a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
index 487d39654..07a1609 100644
--- a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
+++ b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
@@ -119,6 +119,8 @@
       return blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN;
     case blink::MediaStreamRequestResult::MEDIA_DEVICE_KILL_SWITCH_ON:
       return blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON;
+    case blink::MediaStreamRequestResult::MEDIA_DEVICE_SYSTEM_PERMISSION_DENIED:
+      return blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED;
     default:
       break;
   }
@@ -183,6 +185,10 @@
     case blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON:
       *out = blink::MediaStreamRequestResult::MEDIA_DEVICE_KILL_SWITCH_ON;
       return true;
+    case blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED:
+      *out = blink::MediaStreamRequestResult::
+          MEDIA_DEVICE_SYSTEM_PERMISSION_DENIED;
+      return true;
   }
   NOTREACHED();
   return false;
diff --git a/third_party/blink/public/common/mediastream/media_stream_request.h b/third_party/blink/public/common/mediastream/media_stream_request.h
index 8e0e2ba..c00f038 100644
--- a/third_party/blink/public/common/mediastream/media_stream_request.h
+++ b/third_party/blink/public/common/mediastream/media_stream_request.h
@@ -75,6 +75,7 @@
   MEDIA_DEVICE_NOT_SUPPORTED = 12,
   MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN = 13,
   MEDIA_DEVICE_KILL_SWITCH_ON = 14,
+  MEDIA_DEVICE_SYSTEM_PERMISSION_DENIED = 15,
   NUM_MEDIA_REQUEST_RESULTS
 };
 
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom
index 24a6bed4..8e617511 100644
--- a/third_party/blink/public/mojom/mediastream/media_stream.mojom
+++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -38,7 +38,8 @@
   TRACK_START_FAILURE_VIDEO,
   NOT_SUPPORTED,
   FAILED_DUE_TO_SHUTDOWN,
-  KILL_SWITCH_ON
+  KILL_SWITCH_ON,
+  SYSTEM_PERMISSION_DENIED
 };
 
 // See public/common/media_stream_request.h.
diff --git a/third_party/blink/public/web/web_user_media_request.h b/third_party/blink/public/web/web_user_media_request.h
index 0196f53f..a5fd121 100644
--- a/third_party/blink/public/web/web_user_media_request.h
+++ b/third_party/blink/public/web/web_user_media_request.h
@@ -57,7 +57,8 @@
     kCapture,
     kTrackStart,
     kFailedDueToShutdown,
-    kKillSwitchOn
+    kKillSwitchOn,
+    kSystemPermissionDenied
   };
 
   enum class MediaType {
diff --git a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
index 202786f4..22578f37 100644
--- a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
+++ b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -11,9 +11,7 @@
 {%- endif %}) {
   {% filter format_remove_duplicates(['ExceptionState exception_state']) %}
   {% set define_exception_state -%}
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "{{interface_name}}", "{{attribute.name}}");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "{{interface_name}}", "{{attribute.name}}");
   {%- endset %}
 
   {% if attribute.is_lenient_this %}
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc
index 3d3dad8..ccfffa44 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_attributes.cc
@@ -81,9 +81,7 @@
   // This attribute returns a Promise.
   // Per https://heycam.github.io/webidl/#dfn-attribute-getter, all exceptions
   // must be turned into a Promise rejection.
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestAttributes", "stringPromiseAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestAttributes", "stringPromiseAttribute");
   ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
 
   // Returning a Promise type requires us to disable some of V8's type checks,
@@ -118,9 +116,7 @@
   // This attribute returns a Promise.
   // Per https://heycam.github.io/webidl/#dfn-attribute-getter, all exceptions
   // must be turned into a Promise rejection.
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestAttributes", "raisesExceptionShortPromiseAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestAttributes", "raisesExceptionShortPromiseAttribute");
   ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
 
   // Returning a Promise type requires us to disable some of V8's type checks,
@@ -135,9 +131,6 @@
 
   TestAttributes* impl = V8TestAttributes::ToImpl(holder);
 
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestAttributes", "raisesExceptionShortPromiseAttribute");
-
   ScriptPromise cpp_value(impl->raisesExceptionShortPromiseAttribute(exception_state));
 
   if (UNLIKELY(exception_state.HadException()))
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
index 29ee0e6..3725cbd 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
@@ -919,9 +919,7 @@
   // This attribute returns a Promise.
   // Per https://heycam.github.io/webidl/#dfn-attribute-getter, all exceptions
   // must be turned into a Promise rejection.
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "promiseAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "promiseAttribute");
   ExceptionToRejectPromiseScope reject_promise_scope(info, exception_state);
 
   // Returning a Promise type requires us to disable some of V8's type checks,
@@ -2231,9 +2229,7 @@
   TestObject* impl = V8TestObject::ToImpl(holder);
 
   // Perform a security check for the returned object.
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "checkSecurityForNodeReadonlyDocumentAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "checkSecurityForNodeReadonlyDocumentAttribute");
   if (!BindingSecurity::ShouldAllowAccessTo(CurrentDOMWindow(info.GetIsolate()), WTF::GetPtr(impl->checkSecurityForNodeReadonlyDocumentAttribute()), BindingSecurity::ErrorReportOption::kDoNotReport)) {
     UseCounter::Count(CurrentExecutionContext(info.GetIsolate()),
                       WebFeature::kCrossOriginTestObjectCheckSecurityForNodeReadonlyDocumentAttribute);
@@ -3001,9 +2997,7 @@
 
   TestObject* impl = V8TestObject::ToImpl(holder);
 
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "raisesExceptionLongAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "raisesExceptionLongAttribute");
 
   int32_t cpp_value(impl->raisesExceptionLongAttribute(exception_state));
 
@@ -3038,9 +3032,7 @@
 
   TestObject* impl = V8TestObject::ToImpl(holder);
 
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "raisesExceptionGetterLongAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "raisesExceptionGetterLongAttribute");
 
   int32_t cpp_value(impl->raisesExceptionGetterLongAttribute(exception_state));
 
@@ -3103,9 +3095,7 @@
 
   TestObject* impl = V8TestObject::ToImpl(holder);
 
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "raisesExceptionTestInterfaceEmptyAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "raisesExceptionTestInterfaceEmptyAttribute");
 
   TestInterfaceEmpty* cpp_value(impl->raisesExceptionTestInterfaceEmptyAttribute(exception_state));
 
@@ -3156,9 +3146,7 @@
     }
   }
 
-  ExceptionState exception_state(
-      info.GetIsolate(), ExceptionState::kGetterContext,
-      "TestObject", "cachedAttributeRaisesExceptionGetterAnyAttribute");
+  ExceptionState exception_state(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", "cachedAttributeRaisesExceptionGetterAnyAttribute");
 
   ScriptValue cpp_value(impl->cachedAttributeRaisesExceptionGetterAnyAttribute(exception_state));
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 7aa570a33..35d24a77 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -91,6 +91,7 @@
   FinishUpdateResolver(kReject);
   FinishCommitResolver(kReject);
   FinishAcquireResolver(kReject);
+  CancelTimeoutTask();
   state_ = kUnlocked;
 }
 
@@ -394,6 +395,7 @@
   if (!element_ || !element_->isConnected()) {
     state_ = kUnlocked;
     update_budget_.reset();
+    CancelTimeoutTask();
     FinishUpdateResolver(kReject);
     // TODO(vmpstr): Should we resolve here? What's the path to unlocking an
     // element without connecting it (i.e. acquire the lock, then change your
@@ -407,6 +409,7 @@
   if (state_ == kPendingAcquire) {
     FinishAcquireResolver(kReject);
     FinishCommitResolver(kResolve);
+    CancelTimeoutTask();
     state_ = kUnlocked;
     return;
   }
@@ -561,6 +564,7 @@
   if (state_ == kPendingAcquire) {
     if (!ElementSupportsDisplayLocking()) {
       FinishAcquireResolver(kReject);
+      CancelTimeoutTask();
       state_ = kUnlocked;
       return;
     }
@@ -568,6 +572,10 @@
     FinishAcquireResolver(kResolve);
     state_ = kLocked;
     auto* layout_object = element_->GetLayoutObject();
+    // TODO(vmpstr): Note that we may be in a nested display lock, so it's
+    // unclear which frame rect to save here since we have not necessarily done
+    // a layout to acquire this lock. We need to figure out what to do here. For
+    // now, just stash whatever the current frame rect is. See crbug.com/926276.
     if (layout_object && layout_object->IsBox()) {
       locked_frame_rect_ = ToLayoutBox(layout_object)->FrameRect();
     } else {
@@ -595,6 +603,7 @@
 
     if (commit_resolver_) {
       FinishCommitResolver(kReject);
+      CancelTimeoutTask();
       state_ = kUnlocked;
     } else {
       state_ = kLocked;
@@ -638,6 +647,7 @@
 }
 
 void DisplayLockContext::ScheduleAnimation() {
+  DCHECK(element_);
   DCHECK(element_->isConnected());
 
   // Schedule an animation to perform the lifecycle phases.
@@ -670,12 +680,25 @@
 }
 
 void DisplayLockContext::TriggerTimeout() {
+  // We might have started to shut down while we're triggering a timeout. In
+  // that case, do nothing.
+  if (!element_ || !element_->GetDocument().Lifecycle().IsActive())
+    return;
   StartCommit();
   timeout_task_is_scheduled_ = false;
 }
 
 bool DisplayLockContext::ElementSupportsDisplayLocking() const {
-  DCHECK(element_ && !IsElementDirtyForStyleRecalc());
+  DCHECK(element_);
+  // The style can be dirty if we're in a nested lock.
+  // TODO(vmpstr): We need to figure out what to do here, since we don't know
+  // what the style is and whether this element has proper containment. However,
+  // forcing an update from the ancestor locks seems inefficient. For now, we
+  // just optimistically assume that we have all of the right containment in
+  // place. See crbug.com/926276 for more information.
+  if (IsElementDirtyForStyleRecalc())
+    return true;
+
   // If we have a layout object, check that since it's a more authoritative
   // source of containment information.
   if (auto* layout_object = element_->GetLayoutObject()) {
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory.cc b/third_party/blink/renderer/core/events/pointer_event_factory.cc
index 7a4dca7..371719dd 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory.cc
@@ -319,7 +319,7 @@
 
 void PointerEventFactory::SetLastPosition(int pointer_id,
                                           const WebPointerProperties& event) {
-  pointer_id_last_position_mapping_.Set(pointer_id, event.PositionInScreen());
+  pointer_id_last_position_mapping_[pointer_id] = event.PositionInScreen();
 }
 
 void PointerEventFactory::RemoveLastPosition(const int pointer_id) {
@@ -329,8 +329,10 @@
 FloatPoint PointerEventFactory::GetLastPointerPosition(
     int pointer_id,
     const WebPointerProperties& event) const {
-  if (pointer_id_last_position_mapping_.Contains(pointer_id))
-    return pointer_id_last_position_mapping_.at(pointer_id);
+  const auto& last_position_iterator =
+      pointer_id_last_position_mapping_.find(pointer_id);
+  if (last_position_iterator != pointer_id_last_position_mapping_.end())
+    return last_position_iterator->second;
   // If pointer_id is not in the map, returns the current position so the
   // movement will be zero.
   return event.PositionInScreen();
@@ -339,11 +341,9 @@
 PointerEvent* PointerEventFactory::CreatePointerCancelEvent(
     const int pointer_id,
     TimeTicks platfrom_time_stamp) {
-  DCHECK(pointer_id_mapping_.Contains(pointer_id));
-  pointer_id_mapping_.Set(
-      pointer_id,
-      PointerAttributes(pointer_id_mapping_.at(pointer_id).incoming_id, false,
-                        true));
+  DCHECK(pointer_id_mapping_.find(pointer_id) != pointer_id_mapping_.end());
+  pointer_id_mapping_[pointer_id] = PointerAttributes(
+      pointer_id_mapping_.at(pointer_id).incoming_id, false, true);
 
   PointerEventInit* pointer_event_init = PointerEventInit::Create();
 
@@ -452,10 +452,8 @@
   // No need to add it to m_pointerIncomingIdMapping as it is not going to be
   // used with the existing APIs
   primary_id_[ToInt(WebPointerProperties::PointerType::kMouse)] = kMouseId;
-  pointer_id_mapping_.insert(
-      kMouseId, PointerAttributes(
-                    IncomingId(WebPointerProperties::PointerType::kMouse, 0),
-                    false, true));
+  pointer_id_mapping_[kMouseId] = PointerAttributes(
+      IncomingId(WebPointerProperties::PointerType::kMouse, 0), false, true);
 
   current_id_ = PointerEventFactory::kMouseId + 1;
 }
@@ -465,15 +463,15 @@
                                                      bool hovering) {
   // Do not add extra mouse pointer as it was added in initialization
   if (p.GetPointerType() == WebPointerProperties::PointerType::kMouse) {
-    pointer_id_mapping_.Set(kMouseId,
-                            PointerAttributes(p, is_active_buttons, true));
+    pointer_id_mapping_[kMouseId] =
+        PointerAttributes(p, is_active_buttons, true);
     return kMouseId;
   }
 
   if (pointer_incoming_id_mapping_.Contains(p)) {
     PointerId mapped_id = pointer_incoming_id_mapping_.at(p);
-    pointer_id_mapping_.Set(mapped_id,
-                            PointerAttributes(p, is_active_buttons, hovering));
+    pointer_id_mapping_[mapped_id] =
+        PointerAttributes(p, is_active_buttons, hovering);
     return mapped_id;
   }
   int type_int = p.PointerTypeInt();
@@ -483,14 +481,15 @@
     primary_id_[type_int] = mapped_id;
   id_count_[type_int]++;
   pointer_incoming_id_mapping_.insert(p, mapped_id);
-  pointer_id_mapping_.insert(mapped_id,
-                             PointerAttributes(p, is_active_buttons, hovering));
+  pointer_id_mapping_[mapped_id] =
+      PointerAttributes(p, is_active_buttons, hovering);
   return mapped_id;
 }
 
 bool PointerEventFactory::Remove(const PointerId mapped_id) {
   // Do not remove mouse pointer id as it should always be there
-  if (mapped_id == kMouseId || !pointer_id_mapping_.Contains(mapped_id))
+  if (mapped_id == kMouseId ||
+      pointer_id_mapping_.find(mapped_id) == pointer_id_mapping_.end())
     return false;
 
   IncomingId p = pointer_id_mapping_.at(mapped_id).incoming_id;
@@ -510,8 +509,8 @@
 
   for (auto iter = pointer_id_mapping_.begin();
        iter != pointer_id_mapping_.end(); ++iter) {
-    PointerId mapped_id = iter->key;
-    if (!iter->value.hovering)
+    PointerId mapped_id = iter->first;
+    if (!iter->second.hovering)
       mapped_ids.push_back(mapped_id);
   }
 
@@ -521,15 +520,16 @@
 }
 
 bool PointerEventFactory::IsPrimary(PointerId mapped_id) const {
-  if (!pointer_id_mapping_.Contains(mapped_id))
+  const auto& pointer_iterator = pointer_id_mapping_.find(mapped_id);
+  if (pointer_iterator == pointer_id_mapping_.end())
     return false;
 
-  IncomingId p = pointer_id_mapping_.at(mapped_id).incoming_id;
+  IncomingId p = pointer_iterator->second.incoming_id;
   return primary_id_[p.PointerTypeInt()] == mapped_id;
 }
 
 bool PointerEventFactory::IsActive(const PointerId pointer_id) const {
-  return pointer_id_mapping_.Contains(pointer_id);
+  return pointer_id_mapping_.find(pointer_id) != pointer_id_mapping_.end();
 }
 
 bool PointerEventFactory::IsPrimary(
@@ -550,8 +550,9 @@
 
 bool PointerEventFactory::IsActiveButtonsState(
     const PointerId pointer_id) const {
-  return pointer_id_mapping_.Contains(pointer_id) &&
-         pointer_id_mapping_.at(pointer_id).is_active_buttons;
+  const auto& pointer_iterator = pointer_id_mapping_.find(pointer_id);
+  return pointer_iterator != pointer_id_mapping_.end() &&
+         pointer_iterator->second.is_active_buttons;
 }
 
 WebPointerProperties::PointerType PointerEventFactory::GetPointerType(
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory.h b/third_party/blink/renderer/core/events/pointer_event_factory.h
index 6592a2b..5584b60 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory.h
+++ b/third_party/blink/renderer/core/events/pointer_event_factory.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_POINTER_EVENT_FACTORY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_POINTER_EVENT_FACTORY_H_
 
+#include <unordered_map>
+
 #include "third_party/blink/public/platform/web_pointer_event.h"
 #include "third_party/blink/public/platform/web_pointer_properties.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -143,11 +145,10 @@
           WTF::PairHashTraits<WTF::UnsignedWithZeroKeyHashTraits<int>,
                               WTF::UnsignedWithZeroKeyHashTraits<int>>>
       pointer_incoming_id_mapping_;
-  HashMap<PointerId,
-          PointerAttributes,
-          WTF::IntHash<PointerId>,
-          WTF::UnsignedWithZeroKeyHashTraits<PointerId>>
-      pointer_id_mapping_;
+  // We are using unordered_map instead of WTF::HashMap to accommodate
+  // for all the possible keys in the given rage as WTF::HashTraits have at
+  // least one unsupported key like 0 or max value in their range.
+  std::unordered_map<PointerId, PointerAttributes> pointer_id_mapping_;
   int primary_id_[static_cast<int>(
                       WebPointerProperties::PointerType::kLastEntry) +
                   1];
@@ -155,11 +156,7 @@
                     WebPointerProperties::PointerType::kLastEntry) +
                 1];
 
-  HashMap<PointerId,
-          FloatPoint,
-          WTF::IntHash<PointerId>,
-          WTF::UnsignedWithZeroKeyHashTraits<PointerId>>
-      pointer_id_last_position_mapping_;
+  std::unordered_map<PointerId, FloatPoint> pointer_id_last_position_mapping_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory_test.cc b/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
index 362da5d..69e4239 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory_test.cc
@@ -6,7 +6,7 @@
 
 #include <gtest/gtest.h>
 
-#include <climits>
+#include <limits>
 
 #include "base/time/time.h"
 #include "third_party/blink/public/platform/web_pointer_properties.h"
@@ -537,8 +537,9 @@
                                 mapped_id_start_ + 4, false /* isprimary */,
                                 false /* hovering */);
   CreateAndCheckWebPointerEvent(WebPointerProperties::PointerType::kUnknown,
-                                INT_MAX, mapped_id_start_ + 5,
-                                false /* isprimary */, false /* hovering */);
+                                std::numeric_limits<int>::max(),
+                                mapped_id_start_ + 5, false /* isprimary */,
+                                false /* hovering */);
 
   pointer_event_factory_.Clear();
 
@@ -555,6 +556,12 @@
   }
   CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kMouse, 0,
                               expected_mouse_id_, true);
+
+  EXPECT_EQ(pointer_event_factory_.IsActive(0), false);
+  EXPECT_EQ(pointer_event_factory_.IsActive(-1), false);
+  EXPECT_EQ(
+      pointer_event_factory_.IsActive(std::numeric_limits<PointerId>::max()),
+      false);
 }
 
 TEST_F(PointerEventFactoryTest, LastPointerPosition) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index be33486..450ff91 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -21,6 +21,43 @@
 
 namespace blink {
 
+bool IsAnonymousContainer(const LayoutObject* layout_object) {
+  return layout_object->IsAnonymousBlock() && layout_object->IsRelPositioned();
+}
+
+// When containing block is a split inline, Legacy and NG use different
+// containers to place OOF descendant.
+// Legacy uses the anonymous block generated by inline.
+// NG uses the anonymous' parent block, that contains all the anonymous
+// continuations.
+// This function finds anonymous parent block.
+LayoutBoxModelObject* GetOOFContainingBlockFromAnonymous(
+    const LayoutObject* anonymous_block,
+    EPosition child_position) {
+  DCHECK(IsAnonymousContainer(anonymous_block));
+  DCHECK(anonymous_block->IsBox());
+
+  // Comments and code copied from
+  // LayoutBox::ContainingBlockLogicalWidthForPositioned.
+  // Ensure we compute our width based on the width of our rel-pos inline
+  // container rather than any anonymous block created to manage a block-flow
+  // ancestor of ours in the rel-pos inline's inline flow.
+  LayoutBoxModelObject* absolute_containing_block =
+      ToLayoutBox(anonymous_block)->Continuation();
+  // There may be nested parallel inline continuations. We have now found the
+  // innermost inline (which may not be relatively positioned). Locate the
+  // inline that serves as the containing block of this box.
+  while (!absolute_containing_block->CanContainOutOfFlowPositionedElement(
+      child_position)) {
+    absolute_containing_block =
+        ToLayoutBoxModelObject(absolute_containing_block->Container());
+  }
+  DCHECK(absolute_containing_block->IsLayoutInline());
+  // Make absolute_containing_block continuation root.
+  return ToLayoutBoxModelObject(
+      absolute_containing_block->GetNode()->GetLayoutObject());
+}
+
 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
     NGBoxFragmentBuilder* container_builder,
     bool contains_absolute,
@@ -69,39 +106,32 @@
       &descendant_candidates, current_container);
 
   // Special case: containing block is a split inline.
-  // Detailed explanation of what this means is inside
-  // NGOutOfFlowLayoutPart::LayoutDescendant.
-  // This code can be removed once we stop inline splitting.
-  // only_layout is only true when positioning blocks for Legacy.
-  // Cross-anonymous inline containers cannot be done in Legacy.
+  // If current container was generated by a split inline,
+  // do not position descendants inside this container. Let its
+  // non-anonymous parent handle it. Only parent has geometry information
+  // needed to compute containing block geometry.
+  // See "Special case: oof css container" comment for detailed description.
   if (descendant_candidates.size() > 0 && current_container && !only_layout &&
-      current_container->IsAnonymousBlock() &&
-      current_container->IsRelPositioned()) {
-    // Comments and code copied from
-    // LayoutBox::ContainingBlockLogicalWidthForPositioned.
-    // Ensure we compute our width based on the width of our rel-pos inline
-    // container rather than any anonymous block created to manage a block-flow
-    // ancestor of ours in the rel-pos inline's inline flow.
+      IsAnonymousContainer(current_container)) {
     LayoutBoxModelObject* absolute_containing_block =
-        ToLayoutBox(current_container)->Continuation();
-    // There may be nested parallel inline continuations. We have now found the
-    // innermost inline (which may not be relatively positioned). Locate the
-    // inline that serves as the containing block of this box.
-    while (!absolute_containing_block->CanContainOutOfFlowPositionedElement(
-        EPosition::kAbsolute)) {
-      absolute_containing_block =
-          ToLayoutBoxModelObject(absolute_containing_block->Container());
-    }
-    DCHECK(absolute_containing_block->IsLayoutInline());
-    // Make absolute_containing_block continuation root.
-    absolute_containing_block = ToLayoutBoxModelObject(
-        absolute_containing_block->GetNode()->GetLayoutObject());
+        contains_absolute_ ? GetOOFContainingBlockFromAnonymous(
+                                 current_container, EPosition::kAbsolute)
+                           : nullptr;
+    LayoutBoxModelObject* fixed_containing_block =
+        contains_fixed_ ? GetOOFContainingBlockFromAnonymous(current_container,
+                                                             EPosition::kFixed)
+                        : nullptr;
     for (auto& candidate : descendant_candidates) {
-      if (absolute_containing_block->CanContainOutOfFlowPositionedElement(
+      if (absolute_containing_block &&
+          absolute_containing_block->CanContainOutOfFlowPositionedElement(
               candidate.node.Style().GetPosition())) {
         candidate.inline_container = absolute_containing_block;
-        container_builder_->AddOutOfFlowDescendant(candidate);
+      } else if (fixed_containing_block &&
+                 fixed_containing_block->CanContainOutOfFlowPositionedElement(
+                     candidate.node.Style().GetPosition())) {
+        candidate.inline_container = fixed_containing_block;
       }
+      container_builder_->AddOutOfFlowDescendant(candidate);
     }
     return;
   }
diff --git a/third_party/blink/renderer/core/workers/experimental/task.cc b/third_party/blink/renderer/core/workers/experimental/task.cc
index d12a1696..6c3f55d 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.cc
+++ b/third_party/blink/renderer/core/workers/experimental/task.cc
@@ -4,6 +4,8 @@
 
 #include "third_party/blink/renderer/core/workers/experimental/task.h"
 
+#include <utility>
+
 #include "third_party/blink/renderer/bindings/core/v8/script_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -41,24 +43,40 @@
   const State state_;
 };
 
-TaskBase::TaskBase(TaskType task_type,
-                   ScriptState* script_state,
+TaskBase::TaskBase(v8::Isolate* isolate,
+                   TaskType task_type,
                    V8Function* function,
-                   const String& function_name)
+                   const String& function_name,
+                   ExceptionState& exception_state)
     : task_type_(task_type),
       self_keep_alive_(this),
       function_name_(function_name.IsolatedCopy()) {
   DCHECK(IsMainThread());
   DCHECK(task_type_ == TaskType::kUserInteraction ||
          task_type_ == TaskType::kIdleTask);
-  // TODO(japhet): Handle serialization failures
-  if (function) {
-    v8::Isolate* isolate = script_state->GetIsolate();
-    function_ = SerializedScriptValue::SerializeAndSwallowExceptions(
-        isolate, function->CallbackObject()
-                     ->ToString(isolate->GetCurrentContext())
-                     .ToLocalChecked());
+
+  if (!function)
+    return;  // Nothing to do.
+
+  v8::Local<v8::String> function_string;
+  {
+    v8::TryCatch try_catch(isolate);
+    if (!function->CallbackObject()
+             ->ToString(isolate->GetCurrentContext())
+             .ToLocal(&function_string)) {
+      exception_state.RethrowV8Exception(try_catch.Exception());
+      return;
+    }
   }
+
+  scoped_refptr<SerializedScriptValue> serialized =
+      SerializedScriptValue::Serialize(
+          isolate, function_string, SerializedScriptValue::SerializeOptions(),
+          exception_state);
+  if (exception_state.HadException())
+    return;
+
+  function_ = std::move(serialized);
 }
 
 void TaskBase::InitializeArgumentsOnMainThread(
@@ -383,11 +401,15 @@
       ToV8(task, isolate->GetCurrentContext()->Global(), isolate))});
 }
 
-ScriptPromise Task::result(ScriptState* script_state) {
+ScriptPromise Task::result(ScriptState* script_state,
+                           ExceptionState& exception_state) {
   DCHECK(IsMainThread());
   if (!resolve_task_) {
-    resolve_task_ =
-        MakeGarbageCollected<ResolveTask>(script_state, task_type_, this);
+    ResolveTask* resolve_task = MakeGarbageCollected<ResolveTask>(
+        script_state, task_type_, this, exception_state);
+    if (exception_state.HadException())
+      return ScriptPromise();
+    resolve_task_ = resolve_task;
   }
   return resolve_task_->GetPromise();
 }
@@ -422,10 +444,18 @@
 
 ResolveTask::ResolveTask(ScriptState* script_state,
                          TaskType task_type,
-                         Task* prerequisite)
-    : TaskBase(task_type, script_state, nullptr, String()),
+                         Task* prerequisite,
+                         ExceptionState& exception_state)
+    : TaskBase(script_state->GetIsolate(),
+               task_type,
+               nullptr,
+               String(),
+               exception_state),
       resolver_(ScriptPromiseResolver::Create(script_state)) {
   DCHECK(IsMainThread());
+  if (exception_state.HadException())
+    return;
+
   // It's safe to pass a nullptr ThreadPoolThreadProivder here because it
   // is only used to select a thread if there are no prerequisites, but a
   // ResolveTask always has exactly one prerequisite.
diff --git a/third_party/blink/renderer/core/workers/experimental/task.h b/third_party/blink/renderer/core/workers/experimental/task.h
index 762648bce..9b9e66e4 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.h
+++ b/third_party/blink/renderer/core/workers/experimental/task.h
@@ -34,10 +34,11 @@
 
   enum class State { kPending, kStarted, kCancelPending, kCompleted, kFailed };
 
-  TaskBase(TaskType,
-           ScriptState*,
+  TaskBase(v8::Isolate*,
+           TaskType,
            V8Function* function,
-           const String& function_name);
+           const String& function_name,
+           ExceptionState&);
 
   void InitializeArgumentsOnMainThread(ThreadPoolThreadProvider*,
                                        ScriptState*,
@@ -158,25 +159,39 @@
 
  public:
   // Called on main thread
-  Task(ThreadPoolThreadProvider* thread_provider,
-       ScriptState* script_state,
+  Task(ScriptState* script_state,
+       ThreadPoolThreadProvider* thread_provider,
        V8Function* function,
        const Vector<ScriptValue>& arguments,
-       TaskType task_type)
-      : TaskBase(task_type, script_state, function, String()) {
+       TaskType task_type,
+       ExceptionState& exception_state)
+      : TaskBase(script_state->GetIsolate(),
+                 task_type,
+                 function,
+                 String(),
+                 exception_state) {
+    if (exception_state.HadException())
+      return;
     InitializeArgumentsOnMainThread(thread_provider, script_state, arguments);
   }
-  Task(ThreadPoolThreadProvider* thread_provider,
-       ScriptState* script_state,
+  Task(ScriptState* script_state,
+       ThreadPoolThreadProvider* thread_provider,
        const String& function_name,
        const Vector<ScriptValue>& arguments,
-       TaskType task_type)
-      : TaskBase(task_type, script_state, nullptr, function_name) {
+       TaskType task_type,
+       ExceptionState& exception_state)
+      : TaskBase(script_state->GetIsolate(),
+                 task_type,
+                 nullptr,
+                 function_name,
+                 exception_state) {
+    if (exception_state.HadException())
+      return;
     InitializeArgumentsOnMainThread(thread_provider, script_state, arguments);
   }
 
   // Returns a promise that will be resolved with the result when it completes.
-  ScriptPromise result(ScriptState*);
+  ScriptPromise result(ScriptState*, ExceptionState&);
   void cancel() LOCKS_EXCLUDED(mutex_);
 
   void StartTaskOnWorkerThread() override LOCKS_EXCLUDED(mutex_);
@@ -199,7 +214,7 @@
   USING_GARBAGE_COLLECTED_MIXIN(ResolveTask);
 
  public:
-  ResolveTask(ScriptState*, TaskType, Task* prerequisite);
+  ResolveTask(ScriptState*, TaskType, Task* prerequisite, ExceptionState&);
   void StartTaskOnWorkerThread() override LOCKS_EXCLUDED(mutex_);
   bool IsTargetThreadForArguments() override { return IsMainThread(); }
   void TaskCompleted(bool was_successful) override;
diff --git a/third_party/blink/renderer/core/workers/experimental/task.idl b/third_party/blink/renderer/core/workers/experimental/task.idl
index b3a2bf74..f57bc98f 100644
--- a/third_party/blink/renderer/core/workers/experimental/task.idl
+++ b/third_party/blink/renderer/core/workers/experimental/task.idl
@@ -6,6 +6,6 @@
     Exposed=Window,
     RuntimeEnabled=WorkerTaskQueue
 ] interface Task {
-    [CallWith=ScriptState] readonly attribute Promise<any> result;
+    [CallWith=ScriptState, RaisesException] readonly attribute Promise<any> result;
     void cancel();
 };
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
index 3fbc9ac..43af57eff 100644
--- a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
+++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
@@ -50,19 +50,29 @@
 
 Task* TaskWorklet::postTask(ScriptState* script_state,
                             V8Function* function,
-                            const Vector<ScriptValue>& arguments) {
+                            const Vector<ScriptValue>& arguments,
+                            ExceptionState& exception_state) {
   // TODO(japhet): Here and below: it's unclear what task type should be used,
   // and whether the API should allow it to be configured. Using kIdleTask as a
   // placeholder for now.
-  return MakeGarbageCollected<Task>(this, script_state, function, arguments,
-                                    TaskType::kIdleTask);
+  Task* task =
+      MakeGarbageCollected<Task>(script_state, this, function, arguments,
+                                 TaskType::kIdleTask, exception_state);
+  if (exception_state.HadException())
+    return nullptr;
+  return task;
 }
 
 Task* TaskWorklet::postTask(ScriptState* script_state,
                             const String& function_name,
-                            const Vector<ScriptValue>& arguments) {
-  return MakeGarbageCollected<Task>(this, script_state, function_name,
-                                    arguments, TaskType::kIdleTask);
+                            const Vector<ScriptValue>& arguments,
+                            ExceptionState& exception_state) {
+  Task* task =
+      MakeGarbageCollected<Task>(script_state, this, function_name, arguments,
+                                 TaskType::kIdleTask, exception_state);
+  if (exception_state.HadException())
+    return nullptr;
+  return task;
 }
 
 ThreadPoolThread* TaskWorklet::GetLeastBusyThread() {
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.h b/third_party/blink/renderer/core/workers/experimental/task_worklet.h
index d1000b1..3515e6b 100644
--- a/third_party/blink/renderer/core/workers/experimental/task_worklet.h
+++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.h
@@ -27,11 +27,13 @@
 
   Task* postTask(ScriptState*,
                  V8Function* task,
-                 const Vector<ScriptValue>& arguments);
+                 const Vector<ScriptValue>& arguments,
+                 ExceptionState&);
 
   Task* postTask(ScriptState*,
                  const String& function_name,
-                 const Vector<ScriptValue>& arguments);
+                 const Vector<ScriptValue>& arguments,
+                 ExceptionState&);
 
   ThreadPoolThread* GetLeastBusyThread() override;
 
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.idl b/third_party/blink/renderer/core/workers/experimental/task_worklet.idl
index 27168e5..aaafe67 100644
--- a/third_party/blink/renderer/core/workers/experimental/task_worklet.idl
+++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.idl
@@ -6,6 +6,6 @@
     RuntimeEnabled=WorkerTaskQueue,
     SecureContext
 ] interface TaskWorklet : Worklet {
-    [CallWith=ScriptState] Task postTask(Function task, any... arguments);
-    [CallWith=ScriptState] Task postTask(USVString task, any... arguments);
+    [CallWith=ScriptState, RaisesException] Task postTask(Function task, any... arguments);
+    [CallWith=ScriptState, RaisesException] Task postTask(USVString task, any... arguments);
 };
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
index a9201df..d7b2697 100644
--- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
+++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
@@ -41,23 +41,32 @@
     ScriptState* script_state,
     V8Function* function,
     AbortSignal* signal,
-    const Vector<ScriptValue>& arguments) {
+    const Vector<ScriptValue>& arguments,
+    ExceptionState& exception_state) {
   DCHECK(document_->IsContextThread());
 
-  Task* task =
-      MakeGarbageCollected<Task>(ThreadPool::From(*document_), script_state,
-                                 function, arguments, task_type_);
+  Task* task = MakeGarbageCollected<Task>(
+      script_state, ThreadPool::From(*document_), function, arguments,
+      task_type_, exception_state);
+  if (exception_state.HadException())
+    return ScriptPromise();
+
   if (signal)
     signal->AddAlgorithm(WTF::Bind(&Task::cancel, WrapWeakPersistent(task)));
-  return task->result(script_state);
+  return task->result(script_state, exception_state);
 }
 
 Task* WorkerTaskQueue::postTask(ScriptState* script_state,
                                 V8Function* function,
-                                const Vector<ScriptValue>& arguments) {
+                                const Vector<ScriptValue>& arguments,
+                                ExceptionState& exception_state) {
   DCHECK(document_->IsContextThread());
-  return MakeGarbageCollected<Task>(ThreadPool::From(*document_), script_state,
-                                    function, arguments, task_type_);
+  Task* task = MakeGarbageCollected<Task>(
+      script_state, ThreadPool::From(*document_), function, arguments,
+      task_type_, exception_state);
+  if (exception_state.HadException())
+    return nullptr;
+  return task;
 }
 
 void WorkerTaskQueue::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h
index ad29ca1..364cf45 100644
--- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h
+++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h
@@ -35,11 +35,13 @@
   ScriptPromise postFunction(ScriptState*,
                              V8Function* function,
                              AbortSignal*,
-                             const Vector<ScriptValue>& arguments);
+                             const Vector<ScriptValue>& arguments,
+                             ExceptionState&);
 
   Task* postTask(ScriptState*,
                  V8Function* function,
-                 const Vector<ScriptValue>& arguments);
+                 const Vector<ScriptValue>& arguments,
+                 ExceptionState&);
 
   void Trace(blink::Visitor*) override;
 
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.idl b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.idl
index 0982425..90a4e289 100644
--- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.idl
+++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.idl
@@ -12,6 +12,6 @@
     RuntimeEnabled=WorkerTaskQueue,
     SecureContext
 ] interface WorkerTaskQueue {
-    [CallWith=ScriptState] Promise<any> postFunction(Function task, optional AbortSignal signal = null, any... arguments);
-    [CallWith=ScriptState] Task postTask(Function task, any... arguments);
+    [CallWith=ScriptState, RaisesException] Promise<any> postFunction(Function task, optional AbortSignal signal = null, any... arguments);
+    [CallWith=ScriptState, RaisesException] Task postTask(Function task, any... arguments);
 };
diff --git a/third_party/blink/renderer/core/workers/worker_reporting_proxy.h b/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
index 2faa0a9..84264654 100644
--- a/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
+++ b/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
@@ -61,6 +61,9 @@
                                     const String& message,
                                     SourceLocation*) {}
 
+  // Invoked at the beginning of WorkerThread::InitializeOnWorkerThread.
+  virtual void WillInitializeWorkerContext() {}
+
   // Invoked when the new WorkerGlobalScope is created on
   // WorkerThread::InitializeOnWorkerThread.
   virtual void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) {}
@@ -69,6 +72,10 @@
   // WorkerThread::InitializeOnWorkerThread.
   virtual void DidInitializeWorkerContext() {}
 
+  // Invoked when the WorkerGlobalScope initialization failed on
+  // WorkerThread::InitializeOnWorkerThread.
+  virtual void DidFailToInitializeWorkerContext() {}
+
   // Invoked when the worker's main script is loaded on
   // WorkerThread::InitializeOnWorkerThread(). Only invoked when the script was
   // loaded on the worker thread, i.e., via InstalledScriptsManager rather than
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index d4549ef..cf062fa 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -435,6 +435,7 @@
     const base::Optional<WorkerBackingThreadStartupData>& thread_startup_data,
     std::unique_ptr<WorkerDevToolsParams> devtools_params) {
   DCHECK(IsCurrentThread());
+  worker_reporting_proxy_.WillInitializeWorkerContext();
   {
     MutexLocker lock(mutex_);
     DCHECK_EQ(ThreadState::kNotStarted, thread_state_);
@@ -464,14 +465,18 @@
             WorkerThreadDebugger::From(GetIsolate()))
       debugger->WorkerThreadCreated(this);
 
-    // TODO(nhiroki): Handle a case where the script controller fails to
-    // initialize the context.
     if (GlobalScope()->ScriptController()->InitializeContextIfNeeded(
             String(), url_for_debugger)) {
       worker_reporting_proxy_.DidInitializeWorkerContext();
       v8::HandleScope handle_scope(GetIsolate());
       Platform::Current()->WorkerContextCreated(
           GlobalScope()->ScriptController()->GetContext());
+    } else {
+      // TODO(nhiroki): Handle a case where the script controller fails to
+      // initialize the context. Specifically, we need to terminate this worker
+      // thread from the the parent thread. Currently we only record trace
+      // event.
+      worker_reporting_proxy_.DidFailToInitializeWorkerContext();
     }
 
     inspector_task_runner_->InitIsolate(GetIsolate());
diff --git a/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css b/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
index 5a57737..2470d2d 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
@@ -90,6 +90,7 @@
     tab-size: 4;
     -webkit-user-select: none;
     color: #222;
+    background: white;
 }
 
 .platform-linux {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
index 8ba96e8..0043a225 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
@@ -58,9 +58,6 @@
     case kMediaSlider:
       return AccessibilityMediaTimeline::Create(layout_object, ax_object_cache);
 
-    case kMediaControlsPanel:
-      return AXMediaControlsContainer::Create(layout_object, ax_object_cache);
-
     case kMediaSliderThumb:
     case kMediaTimelineContainer:
     case kMediaOverflowButton:
@@ -109,7 +106,6 @@
       return QueryString(WebLocalizedString::kAXMediaOverflowButton);
     case kMediaSliderThumb:
     case kMediaTimelineContainer:
-    case kMediaControlsPanel:
     case kMediaOverflowList:
       return QueryString(WebLocalizedString::kAXMediaDefault);
     case kMediaSlider:
@@ -132,7 +128,6 @@
       return QueryString(WebLocalizedString::kAXMediaOverflowButtonHelp);
     case kMediaSliderThumb:
     case kMediaTimelineContainer:
-    case kMediaControlsPanel:
     case kMediaOverflowList:
       return QueryString(WebLocalizedString::kAXMediaDefault);
     case kMediaSlider:
@@ -165,7 +160,6 @@
     case kMediaOverflowList:
       return ax::mojom::Role::kGroup;
 
-    case kMediaControlsPanel:
     case kMediaSliderThumb:
       return ax::mojom::Role::kUnknown;
 
@@ -181,46 +175,6 @@
 }
 
 //
-// AXMediaControlsContainer
-
-AXMediaControlsContainer::AXMediaControlsContainer(
-    LayoutObject* layout_object,
-    AXObjectCacheImpl& ax_object_cache)
-    : AccessibilityMediaControl(layout_object, ax_object_cache) {}
-
-AXObject* AXMediaControlsContainer::Create(LayoutObject* layout_object,
-                                           AXObjectCacheImpl& ax_object_cache) {
-  return MakeGarbageCollected<AXMediaControlsContainer>(layout_object,
-                                                        ax_object_cache);
-}
-
-String AXMediaControlsContainer::TextAlternative(
-    bool recursive,
-    bool in_aria_labelled_by_traversal,
-    AXObjectSet& visited,
-    ax::mojom::NameFrom& name_from,
-    AXRelatedObjectVector* related_objects,
-    NameSources* name_sources) const {
-  return QueryString(IsControllingVideoElement()
-                         ? WebLocalizedString::kAXMediaVideoElement
-                         : WebLocalizedString::kAXMediaAudioElement);
-}
-
-String AXMediaControlsContainer::Description(
-    ax::mojom::NameFrom name_from,
-    ax::mojom::DescriptionFrom& description_from,
-    AXObjectVector* description_objects) const {
-  return QueryString(IsControllingVideoElement()
-                         ? WebLocalizedString::kAXMediaVideoElementHelp
-                         : WebLocalizedString::kAXMediaAudioElementHelp);
-}
-
-bool AXMediaControlsContainer::ComputeAccessibilityIsIgnored(
-    IgnoredReasons* ignored_reasons) const {
-  return AccessibilityIsIgnoredByDefault(ignored_reasons);
-}
-
-//
 // AccessibilityMediaTimeline
 
 AccessibilityMediaTimeline::AccessibilityMediaTimeline(
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.h b/third_party/blink/renderer/modules/accessibility/ax_media_controls.h
index ad984667..d69c8a0 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.h
@@ -81,33 +81,6 @@
   DISALLOW_COPY_AND_ASSIGN(AccessibilityMediaTimeline);
 };
 
-class AXMediaControlsContainer final : public AccessibilityMediaControl {
- public:
-  static AXObject* Create(LayoutObject*, AXObjectCacheImpl&);
-
-  AXMediaControlsContainer(LayoutObject*, AXObjectCacheImpl&);
-  ~AXMediaControlsContainer() override = default;
-
-  ax::mojom::Role RoleValue() const override {
-    return ax::mojom::Role::kToolbar;
-  }
-
-  String TextAlternative(bool recursive,
-                         bool in_aria_labelled_by_traversal,
-                         AXObjectSet& visited,
-                         ax::mojom::NameFrom&,
-                         AXRelatedObjectVector*,
-                         NameSources*) const override;
-  String Description(ax::mojom::NameFrom,
-                     ax::mojom::DescriptionFrom&,
-                     AXObjectVector* description_objects) const override;
-
- private:
-  bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(AXMediaControlsContainer);
-};
-
 class AccessibilityMediaTimeDisplay final : public AccessibilityMediaControl {
  public:
   static AXObject* Create(LayoutObject*, AXObjectCacheImpl&);
diff --git a/third_party/blink/renderer/modules/geolocation/OWNERS b/third_party/blink/renderer/modules/geolocation/OWNERS
index f00a5417..51b1f3e2 100644
--- a/third_party/blink/renderer/modules/geolocation/OWNERS
+++ b/third_party/blink/renderer/modules/geolocation/OWNERS
@@ -1,3 +1,4 @@
+mattreynolds@chromium.org
 mcasas@chromium.org
 
 # TEAM: device-dev@chromium.org
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc
index cdc7edc..99df8bd1 100644
--- a/third_party/blink/renderer/modules/geolocation/geolocation.cc
+++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -27,6 +27,7 @@
 
 #include "third_party/blink/renderer/modules/geolocation/geolocation.h"
 
+#include "services/device/public/mojom/geoposition.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_button_panel_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_button_panel_element.cc
index c58efc14..72d08db 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_button_panel_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_button_panel_element.cc
@@ -11,7 +11,7 @@
 
 MediaControlButtonPanelElement::MediaControlButtonPanelElement(
     MediaControlsImpl& media_controls)
-    : MediaControlDivElement(media_controls, kMediaControlsPanel) {
+    : MediaControlDivElement(media_controls, kMediaIgnore) {
   SetShadowPseudoId(AtomicString("-internal-media-controls-button-panel"));
 }
 
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
index 42ed8ca7..90d6bfa 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
@@ -12,7 +12,6 @@
   kMediaSlider,
   kMediaSliderThumb,
   kMediaTimelineContainer,
-  kMediaControlsPanel,
   kMediaOverflowButton,
   kMediaOverflowList,
   kMediaIgnore
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
index c8aa69e..9b06677 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
@@ -32,7 +32,7 @@
 
 MediaControlLoadingPanelElement::MediaControlLoadingPanelElement(
     MediaControlsImpl& media_controls)
-    : MediaControlDivElement(media_controls, kMediaControlsPanel) {
+    : MediaControlDivElement(media_controls, kMediaIgnore) {
   SetShadowPseudoId(AtomicString("-internal-media-controls-loading-panel"));
   CreateUserAgentShadowRoot();
 
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_enclosure_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_enclosure_element.cc
index f66633f4..19138c7 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_enclosure_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_enclosure_element.cc
@@ -11,7 +11,7 @@
 
 MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(
     MediaControlsImpl& media_controls)
-    : MediaControlDivElement(media_controls, kMediaControlsPanel) {
+    : MediaControlDivElement(media_controls, kMediaIgnore) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-overlay-enclosure"));
 }
 
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
index 23d48e46..248de8f 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_element.cc
@@ -78,7 +78,7 @@
 
 MediaControlPanelElement::MediaControlPanelElement(
     MediaControlsImpl& media_controls)
-    : MediaControlDivElement(media_controls, kMediaControlsPanel),
+    : MediaControlDivElement(media_controls, kMediaIgnore),
       event_listener_(nullptr) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-panel"));
 }
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_enclosure_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_enclosure_element.cc
index 13b165a..9e1e495 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_enclosure_element.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_panel_enclosure_element.cc
@@ -10,7 +10,7 @@
 
 MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(
     MediaControlsImpl& media_controls)
-    : MediaControlDivElement(media_controls, kMediaControlsPanel) {
+    : MediaControlDivElement(media_controls, kMediaIgnore) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-enclosure"));
 }
 
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
index 2189f8e..1e45d06 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
@@ -1870,8 +1870,9 @@
 }
 
 void MediaControlsImpl::OnFocusIn() {
-  // Touch focus shouldn't affect controls visibility.
-  if (!MediaElement().ShouldShowControls() || is_touch_interaction_)
+  // If the tap timer is active, then we will toggle the controls when the timer
+  // completes, so we don't want to start showing here.
+  if (!MediaElement().ShouldShowControls() || tap_timer_.IsActive())
     return;
 
   ResetHideMediaControlsTimer();
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
index e082018..9b8a91b 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -592,6 +592,7 @@
     case WebUserMediaRequest::Error::kInvalidState:
     case WebUserMediaRequest::Error::kFailedDueToShutdown:
     case WebUserMediaRequest::Error::kKillSwitchOn:
+    case WebUserMediaRequest::Error::kSystemPermissionDenied:
       exception_code = DOMExceptionCode::kNotAllowedError;
       break;
     case WebUserMediaRequest::Error::kDevicesNotFound:
diff --git a/third_party/blink/renderer/modules/service_worker/DEPS b/third_party/blink/renderer/modules/service_worker/DEPS
index 831dcbc..16135b6 100644
--- a/third_party/blink/renderer/modules/service_worker/DEPS
+++ b/third_party/blink/renderer/modules/service_worker/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
     "+base/barrier_closure.h",
     "+base/threading/thread_checker.h",
+    "+base/trace_event/trace_event.h",
     "+mojo/public/cpp/bindings/strong_binding.h",
     "+mojo/public/cpp/system/data_pipe.h",
     "-third_party/blink/renderer/modules",
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
index 679002e..cd30cfd 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
@@ -34,6 +34,7 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "base/trace_event/trace_event.h"
 #include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
@@ -172,7 +173,7 @@
 
 void ServiceWorkerGlobalScopeProxy::BindServiceWorkerHost(
     mojo::ScopedInterfaceEndpointHandle service_worker_host) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->BindServiceWorkerHost(
       mojom::blink::ServiceWorkerHostAssociatedPtrInfo(
           std::move(service_worker_host),
@@ -181,18 +182,19 @@
 
 void ServiceWorkerGlobalScopeProxy::SetRegistration(
     WebServiceWorkerRegistrationObjectInfo info) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->SetRegistration(std::move(info));
 }
 
 void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->ReadyToEvaluateScript();
 }
 
 void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent(
     int event_id,
     const WebBackgroundFetchRegistration& registration) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id);
 
@@ -217,7 +219,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent(
     int event_id,
     const WebBackgroundFetchRegistration& registration) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id);
 
@@ -235,7 +237,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent(
     int event_id,
     const WebBackgroundFetchRegistration& registration) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id);
 
@@ -261,7 +263,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchSuccessEvent(
     int event_id,
     const WebBackgroundFetchRegistration& registration) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchSuccess,
       event_id);
@@ -286,7 +288,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DispatchActivateEvent(int event_id) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kActivate, event_id);
   Event* event = ExtendableEvent::Create(
@@ -298,7 +300,7 @@
     int event_id,
     const WebCanonicalCookie& cookie,
     network::mojom::CookieChangeCause change_cause) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kCookieChange, event_id);
 
@@ -321,7 +323,7 @@
     TransferableMessage message,
     const WebSecurityOrigin& source_origin,
     const WebServiceWorkerClientInfo& client) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   auto msg = ToBlinkTransferableMessage(std::move(message));
   MessagePortArray* ports =
       MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
@@ -346,7 +348,7 @@
     TransferableMessage message,
     const WebSecurityOrigin& source_origin,
     WebServiceWorkerObjectInfo info) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   auto msg = ToBlinkTransferableMessage(std::move(message));
   MessagePortArray* ports =
       MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
@@ -367,7 +369,7 @@
     int fetch_event_id,
     const WebServiceWorkerRequest& web_request,
     bool navigation_preload_sent) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   ScriptState::Scope scope(
       WorkerGlobalScope()->ScriptController()->GetScriptState());
   WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
@@ -408,7 +410,7 @@
     int fetch_event_id,
     std::unique_ptr<WebURLResponse> response,
     mojo::ScopedDataPipeConsumerHandle data_pipe) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   auto it = pending_preload_fetch_events_.find(fetch_event_id);
   DCHECK(it != pending_preload_fetch_events_.end());
   FetchEvent* fetch_event = it->value.Get();
@@ -421,7 +423,7 @@
 void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
     int fetch_event_id,
     std::unique_ptr<WebServiceWorkerError> error) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
   DCHECK(fetch_event);
   // Display an error message to the console, preferring the unsanitized one if
@@ -446,7 +448,7 @@
     int64_t encoded_data_length,
     int64_t encoded_body_length,
     int64_t decoded_body_length) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
   DCHECK(fetch_event);
   fetch_event->OnNavigationPreloadComplete(
@@ -455,7 +457,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DispatchInstallEvent(int event_id) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kInstall, event_id);
   Event* event =
@@ -471,7 +473,7 @@
     const WebNotificationData& data,
     int action_index,
     const WebString& reply) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kNotificationClick, event_id);
   NotificationEventInit* event_init = NotificationEventInit::Create();
@@ -490,7 +492,7 @@
     int event_id,
     const WebString& notification_id,
     const WebNotificationData& data) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kNotificationClose, event_id);
   NotificationEventInit* event_init = NotificationEventInit::Create();
@@ -505,7 +507,7 @@
 
 void ServiceWorkerGlobalScopeProxy::DispatchPushEvent(int event_id,
                                                       const WebString& data) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kPush, event_id);
   Event* event = PushEvent::Create(event_type_names::kPush,
@@ -516,7 +518,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchSyncEvent(int event_id,
                                                       const WebString& id,
                                                       bool last_chance) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kSync, event_id);
   Event* event =
@@ -525,7 +527,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DispatchAbortPaymentEvent(int event_id) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kAbortPayment, event_id);
   AbortPaymentRespondWithObserver* respond_with_observer =
@@ -543,7 +545,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchCanMakePaymentEvent(
     int event_id,
     const WebCanMakePaymentEventData& web_event_data) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kCanMakePayment, event_id);
   CanMakePaymentRespondWithObserver* respond_with_observer =
@@ -564,7 +566,7 @@
 void ServiceWorkerGlobalScopeProxy::DispatchPaymentRequestEvent(
     int event_id,
     const WebPaymentRequestEventData& web_app_request) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
       WorkerGlobalScope(), WaitUntilObserver::kPaymentRequest, event_id);
   PaymentRequestRespondWithObserver* respond_with_observer =
@@ -583,15 +585,17 @@
 }
 
 bool ServiceWorkerGlobalScopeProxy::HasFetchEventHandler() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   return WorkerGlobalScope()->HasEventListeners(event_type_names::kFetch);
 }
 
 void ServiceWorkerGlobalScopeProxy::CountFeature(WebFeature feature) {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().CountFeature(feature);
 }
 
 void ServiceWorkerGlobalScopeProxy::CountDeprecation(WebFeature feature) {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   // Go through the same code path with countFeature() because a deprecation
   // message is already shown on the worker console and a remaining work is
   // just to record an API use.
@@ -602,6 +606,7 @@
     const String& error_message,
     std::unique_ptr<SourceLocation> location,
     int exception_id) {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().ReportException(error_message, location->LineNumber(),
                            location->ColumnNumber(), location->Url());
 }
@@ -611,12 +616,21 @@
     MessageLevel level,
     const String& message,
     SourceLocation* location) {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().ReportConsoleMessage(source, level, message, location->LineNumber(),
                                 location->Url());
 }
 
+void ServiceWorkerGlobalScopeProxy::WillInitializeWorkerContext() {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
+  TRACE_EVENT_ASYNC_BEGIN0(
+      "ServiceWorker", "ServiceWorkerGlobalScopeProxy::InitializeWorkerContext",
+      this);
+}
+
 void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
     WorkerOrWorkletGlobalScope* worker_global_scope) {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(!worker_global_scope_);
   worker_global_scope_ =
       static_cast<ServiceWorkerGlobalScope*>(worker_global_scope);
@@ -624,21 +638,30 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DidInitializeWorkerContext() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   ScriptState::Scope scope(
       WorkerGlobalScope()->ScriptController()->GetScriptState());
   Client().DidInitializeWorkerContext(
       WorkerGlobalScope()->ScriptController()->GetContext());
+  TRACE_EVENT_ASYNC_END1(
+      "ServiceWorker", "ServiceWorkerGlobalScopeProxy::InitializeWorkerContext",
+      this, "success", true);
+}
+
+void ServiceWorkerGlobalScopeProxy::DidFailToInitializeWorkerContext() {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
+  TRACE_EVENT_ASYNC_END1(
+      "ServiceWorker", "ServiceWorkerGlobalScopeProxy::InitializeWorkerContext",
+      this, "success", false);
 }
 
 void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().WorkerScriptLoaded();
 }
 
 void ServiceWorkerGlobalScopeProxy::DidFailToLoadInstalledClassicScript() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
-
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   // Tell ServiceWorkerContextClient about the failure. The generic
   // WorkerContextFailedToStart() wouldn't make sense because
   // WorkerContextStarted() was already called.
@@ -646,14 +669,17 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DidFailToFetchModuleScript() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().FailedToFetchModuleScript();
 }
 
 void ServiceWorkerGlobalScopeProxy::WillEvaluateClassicScript(
     size_t script_size,
     size_t cached_metadata_size) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
+  TRACE_EVENT_ASYNC_BEGIN0(
+      "ServiceWorker", "ServiceWorkerGlobalScopeProxy::EvaluateClassicScript",
+      this);
   // TODO(asamidoi): Remove CountWorkerScript which is called for recording
   // metrics if the metrics are no longer referenced, and then merge
   // WillEvaluateClassicScript and WillEvaluateModuleScript for cleanup.
@@ -664,29 +690,32 @@
 void ServiceWorkerGlobalScopeProxy::WillEvaluateImportedClassicScript(
     size_t script_size,
     size_t cached_metadata_size) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   worker_global_scope_->CountImportedScript(script_size, cached_metadata_size);
 }
 
 void ServiceWorkerGlobalScopeProxy::WillEvaluateModuleScript() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   Client().WillEvaluateScript();
 }
 
 void ServiceWorkerGlobalScopeProxy::DidEvaluateClassicScript(bool success) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->DidEvaluateScript();
   Client().DidEvaluateScript(success);
+  TRACE_EVENT_ASYNC_END1("ServiceWorker",
+                         "ServiceWorkerGlobalScopeProxy::EvaluateClassicScript",
+                         this, "success", success);
 }
 
 void ServiceWorkerGlobalScopeProxy::DidEvaluateModuleScript(bool success) {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   WorkerGlobalScope()->DidEvaluateScript();
   Client().DidEvaluateScript(success);
 }
 
 void ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   // close() is not web-exposed for ServiceWorker. This is called when
   // ServiceWorkerGlobalScope internally requests close(), for example, due to
   // failure on startup when installed scripts couldn't be read.
@@ -708,7 +737,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::WillDestroyWorkerGlobalScope() {
-  DCHECK(WorkerGlobalScope()->IsContextThread());
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   v8::HandleScope handle_scope(WorkerGlobalScope()->GetThread()->GetIsolate());
   Client().WillDestroyWorkerContext(
       WorkerGlobalScope()->ScriptController()->GetContext());
@@ -716,6 +745,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::DidTerminateWorkerThread() {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   // This must be called after WillDestroyWorkerGlobalScope().
   DCHECK(!worker_global_scope_);
   Client().WorkerContextDestroyed();
@@ -728,6 +758,7 @@
       client_(&client),
       worker_global_scope_(nullptr) {
   DCHECK(IsMainThread());
+  DETACH_FROM_THREAD(worker_thread_checker_);
   // ServiceWorker can sometimes run tasks that are initiated by/associated
   // with a document's frame but these documents can be from a different
   // process. So we intentionally populate the task runners with default task
@@ -754,8 +785,8 @@
 
 ServiceWorkerGlobalScope* ServiceWorkerGlobalScopeProxy::WorkerGlobalScope()
     const {
+  DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
   DCHECK(worker_global_scope_);
-  DCHECK(worker_global_scope_->IsContextThread());
   return worker_global_scope_;
 }
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
index 5daac90..232aa39d 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/threading/thread_checker.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
 #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
@@ -154,8 +155,10 @@
                             MessageLevel,
                             const String& message,
                             SourceLocation*) override;
+  void WillInitializeWorkerContext() override;
   void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
   void DidInitializeWorkerContext() override;
+  void DidFailToInitializeWorkerContext() override;
   void DidLoadInstalledScript() override;
   void DidFailToLoadInstalledClassicScript() override;
   void DidFailToFetchModuleScript() override;
@@ -206,6 +209,8 @@
 
   CrossThreadPersistent<ServiceWorkerGlobalScope> worker_global_scope_;
 
+  THREAD_CHECKER(worker_thread_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerGlobalScopeProxy);
 };
 
diff --git a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
index a2ea7c5..e40b02a 100644
--- a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
+++ b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.cc
@@ -47,16 +47,6 @@
   return MakeGarbageCollected<KHRParallelShaderCompile>(context);
 }
 
-void KHRParallelShaderCompile::maxShaderCompilerThreadsKHR(GLuint count) {
-  WebGLExtensionScopedContext scoped(this);
-  if (scoped.IsLost())
-    return;
-  // For WebGL contexts, we don't want applications to be able to spin up huge
-  // numbers of shader compliation threads. Enforce a maximum of 2 here.
-  scoped.Context()->ContextGL()->MaxShaderCompilerThreadsKHR(
-      std::min(2u, count));
-}
-
 bool KHRParallelShaderCompile::Supported(WebGLRenderingContextBase* context) {
   return context->ExtensionsUtil()->SupportsExtension(
       "GL_KHR_parallel_shader_compile");
diff --git a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.h b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.h
index 02886101..4739526 100644
--- a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.h
+++ b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.h
@@ -40,8 +40,6 @@
 
   WebGLExtensionName GetName() const override;
 
-  void maxShaderCompilerThreadsKHR(GLuint count);
-
   explicit KHRParallelShaderCompile(WebGLRenderingContextBase*);
 };
 
diff --git a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.idl b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.idl
index a851234..658af3f 100644
--- a/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.idl
+++ b/third_party/blink/renderer/modules/webgl/khr_parallel_shader_compile.idl
@@ -29,8 +29,5 @@
     NoInterfaceObject,
     DoNotCheckConstants
 ] interface KHRParallelShaderCompile {
-    const GLenum MAX_SHADER_COMPILER_THREADS_KHR      = 0x91B0;
     const GLenum COMPLETION_STATUS_KHR                = 0x91B1;
-
-    void maxShaderCompilerThreadsKHR(GLuint count);
 };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 5332c24..545c96f5 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -3364,13 +3364,6 @@
       SynthesizeGLError(GL_INVALID_ENUM, "getParameter",
                         "invalid parameter name, WEBGL_multiview not enabled");
       return ScriptValue::CreateNull(script_state);
-    case GL_MAX_SHADER_COMPILER_THREADS_KHR:
-      if (ExtensionEnabled(kKHRParallelShaderCompileName))
-        return GetUnsignedIntParameter(script_state, pname);
-      SynthesizeGLError(
-          GL_INVALID_ENUM, "getParameter",
-          "invalid parameter name, KHR_parallel_shader_compile not enabled");
-      return ScriptValue::CreateNull(script_state);
     default:
       if ((ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2OrHigher()) &&
           pname >= GL_DRAW_BUFFER0_EXT &&
diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
index b834a2d..9fd45a29 100644
--- a/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/third_party/blink/renderer/modules/webusb/usb.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "device/usb/public/mojom/device.mojom-blink.h"
+#include "device/usb/public/mojom/device_enumeration_options.mojom-blink.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
diff --git a/third_party/blink/renderer/modules/webusb/usb.h b/third_party/blink/renderer/modules/webusb/usb.h
index 78e713b4..7f23e6a 100644
--- a/third_party/blink/renderer/modules/webusb/usb.h
+++ b/third_party/blink/renderer/modules/webusb/usb.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBUSB_USB_H_
 
 #include "device/usb/public/mojom/device_manager.mojom-blink.h"
+#include "device/usb/public/mojom/device_manager_client.mojom-blink.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "third_party/blink/public/mojom/usb/web_usb_service.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
diff --git a/third_party/blink/renderer/platform/blob/blob_data.cc b/third_party/blink/renderer/platform/blob/blob_data.cc
index 2abdefe..fe4c038 100644
--- a/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -37,6 +37,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/single_thread_task_runner.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
 #include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/public/platform/interface_provider.h"
diff --git a/third_party/blink/renderer/platform/blob/testing/fake_blob.cc b/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
index f8e69fd..cefdbf3 100644
--- a/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
+++ b/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
@@ -6,6 +6,7 @@
 
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
 #include "third_party/blink/public/platform/web_string.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc b/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
index 0063695..90d6c8b6 100644
--- a/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
+++ b/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc
@@ -4,6 +4,8 @@
 
 #include "third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h"
 
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+
 namespace blink {
 
 void FakeBlobURLStore::Register(mojom::blink::BlobPtr blob,
diff --git a/third_party/blink/renderer/platform/graphics/image_decoding_store.cc b/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
index ce30ef7..d8a8b910 100644
--- a/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
+++ b/third_party/blink/renderer/platform/graphics/image_decoding_store.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
 
 #include <memory>
+#include "base/bind.h"
 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
@@ -40,7 +41,10 @@
 
 ImageDecodingStore::ImageDecodingStore()
     : heap_limit_in_bytes_(kDefaultMaxTotalSizeOfHeapEntries),
-      heap_memory_usage_in_bytes_(0) {}
+      heap_memory_usage_in_bytes_(0),
+      memory_pressure_listener_(
+          base::BindRepeating(&ImageDecodingStore::OnMemoryPressure,
+                              base::Unretained(this))) {}
 
 ImageDecodingStore::~ImageDecodingStore() {
 #if DCHECK_IS_ON()
@@ -220,6 +224,18 @@
   }
 }
 
+void ImageDecodingStore::OnMemoryPressure(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  switch (level) {
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+      break;
+    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+      Clear();
+      break;
+  }
+}
+
 template <class T, class U, class V>
 void ImageDecodingStore::InsertCacheInternal(std::unique_ptr<T> cache_entry,
                                              U* cache_map,
diff --git a/third_party/blink/renderer/platform/graphics/image_decoding_store.h b/third_party/blink/renderer/platform/graphics/image_decoding_store.h
index 91a6071..a97e28f 100644
--- a/third_party/blink/renderer/platform/graphics/image_decoding_store.h
+++ b/third_party/blink/renderer/platform/graphics/image_decoding_store.h
@@ -32,6 +32,7 @@
 #include "SkSize.h"
 #include "SkTypes.h"
 #include "base/macros.h"
+#include "base/memory/memory_pressure_listener.h"
 #include "base/memory/ptr_util.h"
 #include "cc/paint/paint_image_generator.h"
 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
@@ -290,6 +291,10 @@
 
   void Prune();
 
+  // Called by the memory pressure listener when the memory pressure rises.
+  void OnMemoryPressure(
+      base::MemoryPressureListener::MemoryPressureLevel level);
+
   // These helper methods are called while m_mutex is locked.
   template <class T, class U, class V>
   void InsertCacheInternal(std::unique_ptr<T> cache_entry,
@@ -347,6 +352,9 @@
   size_t heap_limit_in_bytes_;
   size_t heap_memory_usage_in_bytes_;
 
+  // A listener to global memory pressure events.
+  base::MemoryPressureListener memory_pressure_listener_;
+
   // Protect concurrent access to these members:
   //   m_orderedCacheList
   //   m_decoderCacheMap and all CacheEntrys stored in it
diff --git a/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc b/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
index ce45677d..ad632ecc 100644
--- a/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
+++ b/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
 
 #include <memory>
+#include "base/memory/memory_pressure_listener.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
 #include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h"
@@ -233,4 +234,28 @@
   EXPECT_EQ(ImageDecodingStore::Instance().CacheEntries(), 0);
 }
 
+TEST_F(ImageDecodingStoreTest, OnMemoryPressure) {
+  std::unique_ptr<ImageDecoder> decoder = MockImageDecoder::Create(this);
+  decoder->SetSize(1, 1);
+  ImageDecodingStore::Instance().InsertDecoder(
+      generator_.get(), cc::PaintImage::kDefaultGeneratorClientId,
+      std::move(decoder));
+  EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
+  EXPECT_EQ(4u, ImageDecodingStore::Instance().MemoryUsageInBytes());
+
+  base::MemoryPressureListener::SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(1, ImageDecodingStore::Instance().CacheEntries());
+  EXPECT_EQ(4u, ImageDecodingStore::Instance().MemoryUsageInBytes());
+
+  base::MemoryPressureListener::SimulatePressureNotification(
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(0, ImageDecodingStore::Instance().CacheEntries());
+  EXPECT_EQ(0u, ImageDecodingStore::Instance().MemoryUsageInBytes());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/test/mock_paint_canvas.h b/third_party/blink/renderer/platform/graphics/test/mock_paint_canvas.h
index 23682b16..dc1227c62 100644
--- a/third_party/blink/renderer/platform/graphics/test/mock_paint_canvas.h
+++ b/third_party/blink/renderer/platform/graphics/test/mock_paint_canvas.h
@@ -88,6 +88,12 @@
   MOCK_METHOD4(
       drawTextBlob,
       void(sk_sp<SkTextBlob>, SkScalar x, SkScalar y, const PaintFlags& flags));
+  MOCK_METHOD5(drawTextBlob,
+               void(sk_sp<SkTextBlob>,
+                    SkScalar x,
+                    SkScalar y,
+                    const PaintFlags& flags,
+                    const cc::NodeHolder& holder));
   MOCK_METHOD1(drawPicture, void(sk_sp<const PaintRecord> record));
   MOCK_CONST_METHOD0(isClipEmpty, bool());
   MOCK_CONST_METHOD0(isClipRect, bool());
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 bc87013..2a368459 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -23,6 +23,7 @@
 #include "third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "ui/gfx/mojo/presentation_feedback.mojom-blink.h"
 
 namespace blink {
 
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 3f7e0dc..b4bf833 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
@@ -19,6 +19,7 @@
 #include "media/base/video_frame.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
+#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom-blink.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/graphics/test/mock_compositor_frame_sink.h"
diff --git a/third_party/blink/renderer/platform/memory_coordinator.cc b/third_party/blink/renderer/platform/memory_coordinator.cc
index 73b958a8..54ed9a59 100644
--- a/third_party/blink/renderer/platform/memory_coordinator.cc
+++ b/third_party/blink/renderer/platform/memory_coordinator.cc
@@ -124,10 +124,8 @@
 }
 
 void MemoryCoordinator::ClearMemory() {
-  // Clear the image cache.
-  // TODO(tasak|bashi): Make ImageDecodingStore and FontCache be
-  // MemoryCoordinatorClients rather than clearing caches here.
-  ImageDecodingStore::Instance().Clear();
+  // TODO(tasak|bashi): Make FontCache a MemoryCoordinatorClient rather than
+  // clearing caches here.
   FontGlobalContext::ClearMemory();
 }
 
diff --git a/third_party/blink/renderer/platform/wtf/thread_specific.h b/third_party/blink/renderer/platform/wtf/thread_specific.h
index 44179d69..31a7d75 100644
--- a/third_party/blink/renderer/platform/wtf/thread_specific.h
+++ b/third_party/blink/renderer/platform/wtf/thread_specific.h
@@ -87,7 +87,10 @@
   // longer has a graceful shutdown sequence. Be careful to call this function
   // (which can be re-entrant) while the pointer is still set, to avoid lazily
   // allocating WTFThreadData after it is destroyed.
-  if (IsMainThread())
+  // This check cannot be performed using WTF::IsMainThread, as it uses TLS to
+  // store thread information, and we can't rely on the destruction order of
+  // TLS variables.
+  if (CurrentThread() == g_main_thread_identifier)
     return;
 
   // The memory was allocated via Partitions::FastZeroedMalloc, and then the
diff --git a/third_party/blink/renderer/platform/wtf/wtf.cc b/third_party/blink/renderer/platform/wtf/wtf.cc
index 856f353..26f42da5 100644
--- a/third_party/blink/renderer/platform/wtf/wtf.cc
+++ b/third_party/blink/renderer/platform/wtf/wtf.cc
@@ -49,6 +49,15 @@
 void (*g_call_on_main_thread_function)(MainThreadFunction, void*);
 ThreadIdentifier g_main_thread_identifier;
 
+#if defined(COMPONENT_BUILD) && defined(OS_WIN)
+static thread_local bool g_is_main_thread = false;
+bool IsMainThread() {
+  return g_is_main_thread;
+}
+#else
+thread_local bool g_is_main_thread = false;
+#endif
+
 namespace internal {
 
 void CallOnMainThread(MainThreadFunction* function, void* context) {
@@ -57,16 +66,13 @@
 
 }  // namespace internal
 
-bool IsMainThread() {
-  return CurrentThread() == g_main_thread_identifier;
-}
-
 void Initialize(void (*call_on_main_thread_function)(MainThreadFunction,
                                                      void*)) {
   // WTF, and Blink in general, cannot handle being re-initialized.
   // Make that explicit here.
   CHECK(!g_initialized);
   g_initialized = true;
+  g_is_main_thread = true;
   InitializeCurrentThread();
   g_main_thread_identifier = CurrentThread();
 
diff --git a/third_party/blink/renderer/platform/wtf/wtf.h b/third_party/blink/renderer/platform/wtf/wtf.h
index 312b69d2..f9a53868 100644
--- a/third_party/blink/renderer/platform/wtf/wtf.h
+++ b/third_party/blink/renderer/platform/wtf/wtf.h
@@ -31,17 +31,30 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_H_
 
+#include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/compiler.h"
+#include "third_party/blink/renderer/platform/wtf/threading.h"
 #include "third_party/blink/renderer/platform/wtf/wtf_export.h"
 
 namespace WTF {
 
 typedef void MainThreadFunction(void*);
+WTF_EXPORT extern ThreadIdentifier g_main_thread_identifier;
 
 // This function must be called exactly once from the main thread before using
 // anything else in WTF.
 WTF_EXPORT void Initialize(void (*)(MainThreadFunction, void*));
+
+// thread_local variables can't be exported on Windows, so we use an extra
+// function call on component builds.
+#if defined(COMPONENT_BUILD) && defined(OS_WIN)
 WTF_EXPORT bool IsMainThread();
+#else
+WTF_EXPORT extern thread_local bool g_is_main_thread;
+inline bool IsMainThread() {
+  return g_is_main_thread;
+}
+#endif
 
 namespace internal {
 void CallOnMainThread(MainThreadFunction*, void* context);
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 1fc146f..6e837b61 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -325,6 +325,8 @@
 crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-update-measure-remove.html [ Failure ]
 crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-forced-layout.html [ Failure ]
 crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-updated-layout.html [ Failure ]
+crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update.html [ Timeout ]
+crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update-and-commit.html [ Timeout ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 4e162ef9..f2782fd2 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -344,6 +344,8 @@
 
 # Display locking, currently only available via a virtual test.
 crbug.com/882663 display-lock [ Skip ]
+crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update.html [ Timeout ]
+crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update-and-commit.html [ Timeout ]
 
 # Sheriff 2018/05/25
 crbug.com/846747 http/tests/navigation/navigation-interrupted-by-fragment.html  [ Pass Timeout ]
@@ -2604,9 +2606,6 @@
 crbug.com/v8/8672 http/tests/devtools/bindings/suspendtarget-bindings.js [ Skip ]
 crbug.com/v8/8672 http/tests/devtools/bindings/suspendtarget-navigator.js [ Skip ]
 crbug.com/v8/8672 http/tests/devtools/tracing/decode-resize.js [ Skip ]
-crbug.com/v8/6776 virtual/outofblink-cors/external/wpt/fetch/api/headers/headers-record.html [ Skip ]
-crbug.com/v8/6776 external/wpt/fetch/api/headers/headers-record.html [ Skip ]
-crbug.com/v8/6776 virtual/outofblink-cors-ns/external/wpt/fetch/api/headers/headers-record.html [ Skip ]
 
 # These testcases are incorrect, mark them as failing until they're fixed in the testsuite.
 # https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html
@@ -3092,6 +3091,9 @@
 crbug.com/918664 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-table-1a.html [ Failure Pass ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-grid/abspos/descendant-static-position-003.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-grid/abspos/descendant-static-position-002.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-grid/abspos/descendant-static-position-001.html [ Failure ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/inside-worker/shared-inheritance.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/content-security-policy/frame-ancestors/frame-ancestors-self-block.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/fetch/api/cors/cors-redirect.any.html [ Timeout ]
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire.html
new file mode 100644
index 0000000..04c8737
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-acquire.html
@@ -0,0 +1,54 @@
+<!doctype HTML>
+
+<style>
+.container {
+  contain: style layout;
+}
+#outer {
+  width: 100px;
+  height: 100px;
+  background: lightblue;
+}
+#inner {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+div > div > div {
+  width: 10px;
+  height: 10px;
+  background: red;
+}
+</style>
+
+<div id="log"></div>
+<div id="outer" class="container">
+  <div id="inner" class="container"></div>
+</div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let outer = document.getElementById("outer");
+  let inner = document.getElementById("inner");
+
+  await outer.displayLock.acquire({ timeout: Infinity });
+  // Dirty the inner layout
+  inner.appendChild(document.createElement("div"));
+  inner.displayLock.acquire().then(
+    () => { finishTest("PASS"); },
+    () => { finishTest("FAIL"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit.html
new file mode 100644
index 0000000..6163793
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-commit.html
@@ -0,0 +1,56 @@
+<!doctype HTML>
+
+<style>
+.container {
+  contain: style layout;
+}
+#outer {
+  width: 100px;
+  height: 100px;
+  background: lightblue;
+}
+#inner {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+div > div > div {
+  width: 10px;
+  height: 10px;
+  background: red;
+}
+</style>
+
+<div id="log"></div>
+<div id="outer" class="container">
+  <div id="inner" class="container"></div>
+</div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let outer = document.getElementById("outer");
+  let inner = document.getElementById("inner");
+
+  await Promise.all([
+    outer.displayLock.acquire({ timeout: Infinity }),
+    inner.displayLock.acquire({ timeout: Infinity })]);
+  // Dirty the inner layout
+  inner.appendChild(document.createElement("div"));
+  inner.displayLock.commit().then(
+    () => { finishTest("PASS"); },
+    () => { finishTest("FAIL"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit.html
new file mode 100644
index 0000000..aedda3ecb
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-and-commit.html
@@ -0,0 +1,56 @@
+<!doctype HTML>
+
+<style>
+.container {
+  contain: style layout;
+}
+#outer {
+  width: 100px;
+  height: 100px;
+  background: lightblue;
+}
+#inner {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+div > div > div {
+  width: 10px;
+  height: 10px;
+  background: red;
+}
+</style>
+
+<div id="log"></div>
+<div id="outer" class="container">
+  <div id="inner" class="container"></div>
+</div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let outer = document.getElementById("outer");
+  let inner = document.getElementById("inner");
+
+  await Promise.all([
+    outer.displayLock.acquire({ timeout: Infinity }),
+    inner.displayLock.acquire({ timeout: Infinity })]);
+  // Dirty the inner layout
+  inner.appendChild(document.createElement("div"));
+  inner.displayLock.updateAndCommit().then(
+    () => { finishTest("PASS"); },
+    () => { finishTest("FAIL"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/nested-update.html b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update.html
new file mode 100644
index 0000000..41d5d7f
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/nested-update.html
@@ -0,0 +1,56 @@
+<!doctype HTML>
+
+<style>
+.container {
+  contain: style layout;
+}
+#outer {
+  width: 100px;
+  height: 100px;
+  background: lightblue;
+}
+#inner {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+div > div > div {
+  width: 10px;
+  height: 10px;
+  background: red;
+}
+</style>
+
+<div id="log"></div>
+<div id="outer" class="container">
+  <div id="inner" class="container"></div>
+</div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+async function runTest() {
+  let outer = document.getElementById("outer");
+  let inner = document.getElementById("inner");
+
+  await Promise.all([
+    outer.displayLock.acquire({ timeout: Infinity }),
+    inner.displayLock.acquire({ timeout: Infinity })]);
+  // Dirty the inner layout
+  inner.appendChild(document.createElement("div"));
+  inner.displayLock.update().then(
+    () => { finishTest("PASS"); },
+    () => { finishTest("FAIL"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 336c1ed..b6ff4735 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -45871,6 +45871,54 @@
      {}
     ]
    ],
+   "css/css-grid/abspos/descendant-static-position-001.html": [
+    [
+     "/css/css-grid/abspos/descendant-static-position-001.html",
+     [
+      [
+       "/css/css-grid/abspos/descendant-static-position-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-002.html": [
+    [
+     "/css/css-grid/abspos/descendant-static-position-002.html",
+     [
+      [
+       "/css/css-grid/abspos/descendant-static-position-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-003.html": [
+    [
+     "/css/css-grid/abspos/descendant-static-position-003.html",
+     [
+      [
+       "/css/css-grid/abspos/descendant-static-position-003-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-004.html": [
+    [
+     "/css/css-grid/abspos/descendant-static-position-004.html",
+     [
+      [
+       "/css/css-grid/abspos/descendant-static-position-004-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-grid/abspos/grid-item-absolute-positioning-dynamic-001.html": [
     [
      "/css/css-grid/abspos/grid-item-absolute-positioning-dynamic-001.html",
@@ -59611,6 +59659,42 @@
      {}
     ]
    ],
+   "css/css-tables/subpixel-table-cell-width-001.html": [
+    [
+     "/css/css-tables/subpixel-table-cell-width-001.html",
+     [
+      [
+       "/css/css-tables/subpixel-table-cell-width-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-tables/subpixel-table-cell-width-002.html": [
+    [
+     "/css/css-tables/subpixel-table-cell-width-002.html",
+     [
+      [
+       "/css/css-tables/subpixel-table-cell-width-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-tables/subpixel-table-width-001.html": [
+    [
+     "/css/css-tables/subpixel-table-width-001.html",
+     [
+      [
+       "/css/css-tables/subpixel-table-width-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-tables/table-has-box-sizing-border-box-001.html": [
     [
      "/css/css-tables/table-has-box-sizing-border-box-001.html",
@@ -137360,6 +137444,26 @@
      {}
     ]
    ],
+   "css/css-grid/abspos/descendant-static-position-001-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-002-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-003-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-grid/abspos/descendant-static-position-004-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-grid/abspos/grid-paint-positioned-children-001-ref.html": [
     [
      {}
@@ -141590,6 +141694,16 @@
      {}
     ]
    ],
+   "css/css-tables/subpixel-table-cell-width-001-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-tables/subpixel-table-width-001-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-tables/support/base.css": [
     [
      {}
@@ -159230,11 +159344,6 @@
      {}
     ]
    ],
-   "fetch/api/headers/headers-record-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "fetch/api/idl.any-expected.txt": [
     [
      {}
@@ -220753,6 +220862,24 @@
      {}
     ]
    ],
+   "custom-elements/reactions/HTMLCanvasElement.html": [
+    [
+     "/custom-elements/reactions/HTMLCanvasElement.html",
+     {}
+    ]
+   ],
+   "custom-elements/reactions/HTMLDataElement.html": [
+    [
+     "/custom-elements/reactions/HTMLDataElement.html",
+     {}
+    ]
+   ],
+   "custom-elements/reactions/HTMLDetailsElement.html": [
+    [
+     "/custom-elements/reactions/HTMLDetailsElement.html",
+     {}
+    ]
+   ],
    "custom-elements/reactions/HTMLElement.html": [
     [
      "/custom-elements/reactions/HTMLElement.html",
@@ -220765,6 +220892,24 @@
      {}
     ]
    ],
+   "custom-elements/reactions/HTMLMapElement.html": [
+    [
+     "/custom-elements/reactions/HTMLMapElement.html",
+     {}
+    ]
+   ],
+   "custom-elements/reactions/HTMLModElement.html": [
+    [
+     "/custom-elements/reactions/HTMLModElement.html",
+     {}
+    ]
+   ],
+   "custom-elements/reactions/HTMLOListElement.html": [
+    [
+     "/custom-elements/reactions/HTMLOListElement.html",
+     {}
+    ]
+   ],
    "custom-elements/reactions/HTMLOptionElement.html": [
     [
      "/custom-elements/reactions/HTMLOptionElement.html",
@@ -220783,12 +220928,24 @@
      {}
     ]
    ],
+   "custom-elements/reactions/HTMLQuoteElement.html": [
+    [
+     "/custom-elements/reactions/HTMLQuoteElement.html",
+     {}
+    ]
+   ],
    "custom-elements/reactions/HTMLSelectElement.html": [
     [
      "/custom-elements/reactions/HTMLSelectElement.html",
      {}
     ]
    ],
+   "custom-elements/reactions/HTMLSlotElement.html": [
+    [
+     "/custom-elements/reactions/HTMLSlotElement.html",
+     {}
+    ]
+   ],
    "custom-elements/reactions/HTMLTableElement.html": [
     [
      "/custom-elements/reactions/HTMLTableElement.html",
@@ -220807,6 +220964,12 @@
      {}
     ]
    ],
+   "custom-elements/reactions/HTMLTimeElement.html": [
+    [
+     "/custom-elements/reactions/HTMLTimeElement.html",
+     {}
+    ]
+   ],
    "custom-elements/reactions/HTMLTitleElement.html": [
     [
      "/custom-elements/reactions/HTMLTitleElement.html",
@@ -234715,6 +234878,12 @@
      {}
     ]
    ],
+   "fetch/sec-metadata/iframe.tentative.sub.html": [
+    [
+     "/fetch/sec-metadata/iframe.tentative.sub.html",
+     {}
+    ]
+   ],
    "fetch/sec-metadata/img.tentative.https.sub.html": [
     [
      "/fetch/sec-metadata/img.tentative.https.sub.html",
@@ -234769,6 +234938,12 @@
      {}
     ]
    ],
+   "fetch/sec-metadata/script.tentative.sub.html": [
+    [
+     "/fetch/sec-metadata/script.tentative.sub.html",
+     {}
+    ]
+   ],
    "fetch/sec-metadata/serviceworker.tentative.https.sub.html": [
     [
      "/fetch/sec-metadata/serviceworker.tentative.https.sub.html",
@@ -312865,7 +313040,7 @@
    "reftest"
   ],
   "css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html": [
-   "4b1baff8b956d706b2f90e67277ccf3a7c4d3458",
+   "b54f0e8bf2f1804cd18adf953ef451f6b72b6ff8",
    "testharness"
   ],
   "css/CSS2/abspos/adjacent-to-relpos-inline-in-inline-that-had-block.html": [
@@ -337561,11 +337736,11 @@
    "testharness"
   ],
   "css/css-font-loading/idlharness.https-expected.txt": [
-   "c9ecfd5adc387d0909313f7e8519092c9cb1c20b",
+   "04294ca6d96a415b81c91be5aec1480ac76db4f8",
    "support"
   ],
   "css/css-font-loading/idlharness.https.html": [
-   "61a99e01b51529d4a11997a1a7392da0cc71b0ce",
+   "fcb31ad25650a758a3cedd0e94c3d38777eaed6c",
    "testharness"
   ],
   "css/css-fonts/META.yml": [
@@ -345156,6 +345331,38 @@
    "a7a38ad0a0ab8c8fa13b7fac0a75268e1a026cbb",
    "testharness"
   ],
+  "css/css-grid/abspos/descendant-static-position-001-ref.html": [
+   "05cdb41b3175d85966f84da13a163631e0acfc17",
+   "support"
+  ],
+  "css/css-grid/abspos/descendant-static-position-001.html": [
+   "ec19e4acff1ab6b6a30f28f66e1b6c16c9753705",
+   "reftest"
+  ],
+  "css/css-grid/abspos/descendant-static-position-002-ref.html": [
+   "f1a3d9efeb80fce94a55bb4da221de75eda95c68",
+   "support"
+  ],
+  "css/css-grid/abspos/descendant-static-position-002.html": [
+   "97fa299c0a0a20840ebaa0c1532695634b13c537",
+   "reftest"
+  ],
+  "css/css-grid/abspos/descendant-static-position-003-ref.html": [
+   "953d45de01bea21110dadcddb8b0cdef4e31ff60",
+   "support"
+  ],
+  "css/css-grid/abspos/descendant-static-position-003.html": [
+   "399ade2e8764eb0b0ee444340c0722707ab8dcac",
+   "reftest"
+  ],
+  "css/css-grid/abspos/descendant-static-position-004-ref.html": [
+   "83002f09cff37c9a76f40c3ce51d7a87b33ac3ea",
+   "support"
+  ],
+  "css/css-grid/abspos/descendant-static-position-004.html": [
+   "5496ce9986e1752916bd30d7195697628b50e8a8",
+   "reftest"
+  ],
   "css/css-grid/abspos/grid-item-absolute-positioning-dynamic-001.html": [
    "bcd5dbaab5db71463fa2ec511fcb4d21e7942b90",
    "reftest"
@@ -356256,6 +356463,26 @@
    "a24556aa0dedfab35ff7792f03b804f44c0f4160",
    "reftest"
   ],
+  "css/css-tables/subpixel-table-cell-width-001-ref.html": [
+   "ea2f38b6bb216d25a8d5656fdd8d6bcac40982db",
+   "support"
+  ],
+  "css/css-tables/subpixel-table-cell-width-001.html": [
+   "2174fbec3b6ffafe2a0f209b394418895822d200",
+   "reftest"
+  ],
+  "css/css-tables/subpixel-table-cell-width-002.html": [
+   "f47938f0cdac1c821d0a3f91907ed2ab5dfb09a3",
+   "reftest"
+  ],
+  "css/css-tables/subpixel-table-width-001-ref.html": [
+   "277a3274a917fb522f52e7a5df61c9139413d234",
+   "support"
+  ],
+  "css/css-tables/subpixel-table-width-001.html": [
+   "153282fa6373afe2680a2826b3b45db41279ff79",
+   "reftest"
+  ],
   "css/css-tables/support/base.css": [
    "52be1bb4e52e5705319ebf5525f6d89839356d65",
    "support"
@@ -380785,11 +381012,11 @@
    "reftest"
   ],
   "css/filter-effects/backdrop-filter-border-radius-ref.html": [
-   "eabcd996697024260a5936f8f81a77f9d1decb48",
+   "e5712a23774b6f27c6c2a1dfcfe45931aa0301a4",
    "support"
   ],
   "css/filter-effects/backdrop-filter-border-radius.html": [
-   "fc212501ad52ca7cd1e0a2fd35b7654c8233eea2",
+   "ec93de698aaab5d41709f0999d9f2bab3381945d",
    "reftest"
   ],
   "css/filter-effects/backdrop-filter-clip-rect-ref.html": [
@@ -389084,6 +389311,18 @@
    "90390108b42155b2e5fcd5984d3a43a3ad1f9f6b",
    "testharness"
   ],
+  "custom-elements/reactions/HTMLCanvasElement.html": [
+   "46b9201e7f22d5d3e1cb6af1cedc00c3b28d8cda",
+   "testharness"
+  ],
+  "custom-elements/reactions/HTMLDataElement.html": [
+   "01a3bf34281f5a4ce684ea51ea54f7fcc9171214",
+   "testharness"
+  ],
+  "custom-elements/reactions/HTMLDetailsElement.html": [
+   "cdcc2fcabf5a702ce1583131f0c102cab9bebf7f",
+   "testharness"
+  ],
   "custom-elements/reactions/HTMLElement.html": [
    "5fe422cdfc1df56d58e4eeac1be4669ba8fee967",
    "testharness"
@@ -389092,6 +389331,18 @@
    "dc4b22a22eea3ea841b1380e7db3e75e7f4eb256",
    "testharness"
   ],
+  "custom-elements/reactions/HTMLMapElement.html": [
+   "f6bd04bd1f9c9a92514d8ee3e626b3898ee0daad",
+   "testharness"
+  ],
+  "custom-elements/reactions/HTMLModElement.html": [
+   "850fe170a50d21c1a5cb5a042f05bd2fb062d3fd",
+   "testharness"
+  ],
+  "custom-elements/reactions/HTMLOListElement.html": [
+   "4e53cdb0a510453960feccd2104109610f23e665",
+   "testharness"
+  ],
   "custom-elements/reactions/HTMLOptionElement.html": [
    "418ef282b32fd5e7c29f21a0a9eb17b6c4796167",
    "testharness"
@@ -389104,10 +389355,18 @@
    "02e669bc7a75558686dd56b4ab8fc5918892de2e",
    "testharness"
   ],
+  "custom-elements/reactions/HTMLQuoteElement.html": [
+   "97ab10a170e66eba7e036321111e99dbba8bcff8",
+   "testharness"
+  ],
   "custom-elements/reactions/HTMLSelectElement.html": [
    "7c79634f668b294e5c32224e15e96e2397883777",
    "testharness"
   ],
+  "custom-elements/reactions/HTMLSlotElement.html": [
+   "aba8f20ccfcde3b9e1852cb4d496df5cf85e5e6d",
+   "testharness"
+  ],
   "custom-elements/reactions/HTMLTableElement.html": [
    "6adf2623d6bc208e4eaa41e1683b754f9cccf061",
    "testharness"
@@ -389120,6 +389379,10 @@
    "cbb0a146e8012ac8e44934604443fb300fbcfbb8",
    "testharness"
   ],
+  "custom-elements/reactions/HTMLTimeElement.html": [
+   "4643e340f517da28662712c7b9fef8beb832c7f0",
+   "testharness"
+  ],
   "custom-elements/reactions/HTMLTitleElement.html": [
    "6678944c919d45c42ca68f2585575d398287b15e",
    "testharness"
@@ -389149,7 +389412,7 @@
    "testharness"
   ],
   "custom-elements/reactions/resources/reactions.js": [
-   "6ac7ab838d9ac82e994fc4b963815103c4e35063",
+   "c7b1851c7bf2abba861f02e7aaae5fb810f8d4a9",
    "support"
   ],
   "custom-elements/reactions/with-exceptions.html": [
@@ -395584,10 +395847,6 @@
    "6dfcf9d8194776479d500a6f6c6a5851424d9efc",
    "testharness"
   ],
-  "fetch/api/headers/headers-record-expected.txt": [
-   "019fc2abd22772b812f126f389813688f7435ff0",
-   "support"
-  ],
   "fetch/api/headers/headers-record.html": [
    "85dfadd269d2c7460865dc5d1b16ae1b9834a5a8",
    "testharness"
@@ -396864,6 +397123,10 @@
    "6ee14300296b6f1e9f7f5083637eb06e620f30e8",
    "testharness"
   ],
+  "fetch/sec-metadata/iframe.tentative.sub.html": [
+   "ce31a8182510f246c22543b74ea40bec50d7b016",
+   "testharness"
+  ],
   "fetch/sec-metadata/img.tentative.https.sub.html": [
    "c5c389503ccafd2d2cf21a3634b6995bc22a2e91",
    "testharness"
@@ -396952,6 +397215,10 @@
    "d76378f1dd8df62fa5404dc1fda1b47fb6a8d409",
    "testharness"
   ],
+  "fetch/sec-metadata/script.tentative.sub.html": [
+   "482f4b98f9e8bf4b12e5f960cc39ea4e55ee6c77",
+   "testharness"
+  ],
   "fetch/sec-metadata/serviceworker.tentative.https.sub.html": [
    "d0b86d2d9a8ccf67119983890a29c52a5c875c62",
    "testharness"
@@ -431121,7 +431388,7 @@
    "support"
   ],
   "pointerevents/pointerevent_suppress_compat_events_on_click.html": [
-   "77b5daaed41ad29d3dce34cfde57edb4667d5ea7",
+   "341a82d97a8e0ff4ffbe2d87b817fce807dd39b6",
    "testharness"
   ],
   "pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html": [
@@ -451801,7 +452068,7 @@
    "support"
   ],
   "webaudio/js/helpers.js": [
-   "fbbfc8e00444dce1440fdbe8e28e11c5b064ce3d",
+   "5970b7ba031e320083d6f1c551499e8920792d0e",
    "support"
   ],
   "webaudio/js/worklet-recorder.js": [
@@ -451921,7 +452188,7 @@
    "testharness"
   ],
   "webaudio/the-audio-api/the-analysernode-interface/test-analyser-minimum.html": [
-   "62d90da1c7fd66599bd2d5b542c939efb8886f93",
+   "1b5531bd228c32f3d9d7e79ca053e480a599f311",
    "testharness"
   ],
   "webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html": [
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html b/third_party/blink/web_tests/external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html
index 4b1baff..b54f0e8b 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html
@@ -3,12 +3,14 @@
 <link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#containing-block-details">
 <link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level">
 <style>
+  body { margin: 0px;}
   .rel { position:relative; }
   .inline-block { display:inline-block; width:100px; height:1px; }
   .inline-block.large { width:200px; }
   #target { position:absolute; width:100%; height:100px; background:green; }
+  #target-fixed { position:fixed; width:100%; height:100px; background:yellow; }
 </style>
-<p>There should be a green square below.</p>
+<p>There should be a green square, and a yellow rectangle below.</p>
 <div style="height:200px;">
   <span class="rel" id="notContainingBlockOfTarget">
     <div class="large inline-block"></div>
@@ -17,6 +19,7 @@
       <div class="inline-block"></div>
       <span>
         <div>
+          <div id="target-fixed"></div>
           <div id="target"></div>
         </div>
       </span>
@@ -28,6 +31,11 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
   test(()=> {
-      assert_equals(document.getElementById("target").offsetWidth, 100);
-  }, "Make sure that we're sized by the right ancestor");
+    assert_equals(document.getElementById("target").offsetWidth,
+      document.querySelector("#containingBlockOfTarget").offsetWidth);
+  }, "position:absolute should be sized by the right ancestor");
+  test(()=> {
+    assert_equals(document.getElementById("target-fixed").offsetWidth,
+      document.body.offsetWidth);
+  }, "position:fixed should be sized by the right ancestor");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
index c9ecfd5..04294ca6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
@@ -19,20 +19,20 @@
 PASS FontFace interface: attribute status
 PASS FontFace interface: operation load()
 PASS FontFace interface: attribute loaded
-PASS FontFace must be primary interface of new FontFace("family", "src")
-PASS Stringification of new FontFace("family", "src")
-PASS FontFace interface: new FontFace("family", "src") must inherit property "family" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "style" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "weight" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "stretch" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "unicodeRange" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "variant" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "featureSettings" with the proper type
-FAIL FontFace interface: new FontFace("family", "src") must inherit property "variationSettings" with the proper type assert_inherits: property "variationSettings" not found in prototype chain
-PASS FontFace interface: new FontFace("family", "src") must inherit property "display" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "status" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "load()" with the proper type
-PASS FontFace interface: new FontFace("family", "src") must inherit property "loaded" with the proper type
+PASS FontFace must be primary interface of fontFace
+PASS Stringification of fontFace
+PASS FontFace interface: fontFace must inherit property "family" with the proper type
+PASS FontFace interface: fontFace must inherit property "style" with the proper type
+PASS FontFace interface: fontFace must inherit property "weight" with the proper type
+PASS FontFace interface: fontFace must inherit property "stretch" with the proper type
+PASS FontFace interface: fontFace must inherit property "unicodeRange" with the proper type
+PASS FontFace interface: fontFace must inherit property "variant" with the proper type
+PASS FontFace interface: fontFace must inherit property "featureSettings" with the proper type
+FAIL FontFace interface: fontFace must inherit property "variationSettings" with the proper type assert_inherits: property "variationSettings" not found in prototype chain
+PASS FontFace interface: fontFace must inherit property "display" with the proper type
+PASS FontFace interface: fontFace must inherit property "status" with the proper type
+PASS FontFace interface: fontFace must inherit property "load()" with the proper type
+PASS FontFace interface: fontFace must inherit property "loaded" with the proper type
 PASS FontFaceSetLoadEvent interface: existence and properties of interface object
 PASS FontFaceSetLoadEvent interface object length
 PASS FontFaceSetLoadEvent interface object name
@@ -40,9 +40,9 @@
 PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's "constructor" property
 PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's @@unscopables property
 PASS FontFaceSetLoadEvent interface: attribute fontfaces
-PASS FontFaceSetLoadEvent must be primary interface of new FontFaceSetLoadEvent("type")
-PASS Stringification of new FontFaceSetLoadEvent("type")
-PASS FontFaceSetLoadEvent interface: new FontFaceSetLoadEvent("type") must inherit property "fontfaces" with the proper type
+PASS FontFaceSetLoadEvent must be primary interface of fontFaceSetLoadEvent
+PASS Stringification of fontFaceSetLoadEvent
+PASS FontFaceSetLoadEvent interface: fontFaceSetLoadEvent must inherit property "fontfaces" with the proper type
 FAIL FontFaceSet interface: existence and properties of interface object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
 FAIL FontFaceSet interface object length assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
 FAIL FontFaceSet interface object name assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
diff --git a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html
index 61a99e01..fcb31ad2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-font-loading/idlharness.https.html
@@ -14,10 +14,15 @@
   idl_array => {
     idl_array.add_objects({
       Document: ['document'],
-      FontFace: ['new FontFace("family", "src")'],
-      FontFaceSetLoadEvent: ['new FontFaceSetLoadEvent("type")'],
+      FontFace: ['fontFace'],
+      FontFaceSetLoadEvent: ['fontFaceSetLoadEvent'],
       FontFaceSet: ['document.fonts'],
     });
+    self.fontFace = new FontFace("family", "src");
+    // The `fontFace.loaded` promise will be rejected, so handle that to
+    // avoid an unhandled promise rejection manifesting as a harness error.
+    self.fontFace.loaded.catch(() => {});
+    self.fontFaceSetLoadEvent = new FontFaceSetLoadEvent("type");
   }
 );
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001-ref.html
new file mode 100644
index 0000000..05cdb41
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001-ref.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Reference: Grid aligned descendants with static position</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 20px;
+  padding: 2px 4px 6px 1px;
+}
+.absolute {
+  position: absolute;
+  grid-column: 1 / 2;
+}
+.content {
+  float: left;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+    <div class="absolute" style="margin-top:2px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; border-left:2px solid black; padding-left:1px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="padding-bottom: 14px">
+    <div class="absolute" style="margin-top:10px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-left:8px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001.html
new file mode 100644
index 0000000..ec19e4a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-001.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid aligned descendants with static position</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#staticpos-rect" title="Appendix A: Static Position Terminology">
+<link rel="match" href="descendant-static-position-001-ref.html">
+<meta name="assert" content="This test checks that the position and size of the abs.pos. descendant is correct.">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 20px;
+  padding: 2px 4px 6px 1px;
+}
+.grid > div {
+  background: red;
+  background-clip: content-box;
+}
+.absolute {
+  position: absolute;
+  background: red;
+  grid-column: 1 / 2;
+}
+.content {
+  float: left;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="padding-left:3px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="border-left:2px solid black; padding-left:1px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="padding-top:10px">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-left:8px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002-ref.html
new file mode 100644
index 0000000..f1a3d9e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002-ref.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Reference: Grid aligned descendants with static position (direction: rtl)</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 20px;
+  padding: 2px 4px 6px 1px;
+  direction: rtl;
+  margin-left: 40px;
+}
+.absolute {
+  position: absolute;
+  grid-column: 1 / 2;
+}
+.content {
+  float: right;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+    <div class="absolute" style="margin-top:2px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; border-left:2px solid black; padding-left:1px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="padding-bottom: 14px">
+    <div class="absolute" style="margin-top:10px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-right:8px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-right:8px; padding-left:10px">
+    <div class="absolute" style="margin-top:2px;">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002.html
new file mode 100644
index 0000000..97fa299
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-002.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid aligned descendants with static position (direction: rtl)</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#staticpos-rect" title="Appendix A: Static Position Terminology">
+<link rel="match" href="descendant-static-position-002-ref.html">
+<meta name="assert" content="This test checks that the position and size of the abs.pos. descendant is correct.">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 20px;
+  padding: 2px 4px 6px 1px;
+  direction: rtl;
+  margin-left: 40px;
+}
+.grid > div {
+  background: red;
+  background-clip: content-box;
+}
+.absolute {
+  position: absolute;
+  background: red;
+  grid-column: 1 / 2;
+}
+.content {
+  float: right;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="padding-left:3px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="border-left:2px solid black; padding-left:1px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="padding-top:10px">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-right:8px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-right:8px; padding-left:10px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003-ref.html
new file mode 100644
index 0000000..953d45d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Reference: Grid aligned descendants with static position</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 100px;
+  justify-content: end;
+  padding: 2px 4px 6px 1px;
+}
+.absolute {
+  position: absolute;
+  grid-column: 1 / 2;
+}
+.content {
+  float: left;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+    <div class="absolute" style="margin-top:2px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; border-left:2px solid black; padding-left:1px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="padding-bottom: 14px">
+    <div class="absolute" style="margin-top:10px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-left:8px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003.html
new file mode 100644
index 0000000..399ade2e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-003.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid aligned descendants with static position</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#staticpos-rect" title="Appendix A: Static Position Terminology">
+<link rel="match" href="descendant-static-position-003-ref.html">
+<meta name="assert" content="This test checks that the position and size of the abs.pos. descendant is correct.">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 100px;
+  justify-content: end;
+  padding: 2px 4px 6px 1px;
+}
+.grid > div {
+  background: red;
+  background-clip: content-box;
+}
+.absolute {
+  position: absolute;
+  background: red;
+  grid-column: 1 / 2;
+}
+.content {
+  float: left;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="padding-left:3px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="border-left:2px solid black; padding-left:1px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="padding-top:10px">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-left:8px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004-ref.html
new file mode 100644
index 0000000..83002f09
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004-ref.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Reference: Grid aligned descendants with static position (direction: rtl)</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 100px;
+  justify-content: center;
+  padding: 2px 4px 6px 1px;
+  direction: rtl;
+  margin-left: 40px;
+}
+.absolute {
+  position: absolute;
+  grid-column: 1 / 2;
+}
+.content {
+  float: right;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+    <div class="absolute" style="margin-top:2px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+    <div class="absolute" style="margin-top:2px; border-left:2px solid black; padding-left:1px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="padding-bottom: 14px">
+    <div class="absolute" style="margin-top:10px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-right:8px">
+    <div class="absolute" style="margin-top:2px; margin-left:3px">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px; padding-right:8px; padding-left:10px">
+    <div class="absolute" style="margin-top:2px;">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004.html
new file mode 100644
index 0000000..5496ce99
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/descendant-static-position-004.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html><head>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid aligned descendants with static position (direction: rtl)</title>
+<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#staticpos-rect" title="Appendix A: Static Position Terminology">
+<link rel="match" href="descendant-static-position-004-ref.html">
+<meta name="assert" content="This test checks that the position and size of the abs.pos. descendant is correct.">
+<style>
+.grid {
+  position: relative;
+  display: grid;
+  grid: 40px / 40px;
+  border: 2px solid;
+  border-top-width: 5px;
+  border-left-width: 3px;
+  width: 100px;
+  justify-content: center;
+  padding: 2px 4px 6px 1px;
+  direction: rtl;
+  margin-left: 40px;
+}
+.grid > div {
+  background: red;
+  background-clip: content-box;
+}
+.absolute {
+  position: absolute;
+  background: red;
+  grid-column: 1 / 2;
+}
+.content {
+  float: right;
+  width: 20px;
+  height: 40px;
+  background: green;
+}
+.content:nth-child(2) {
+  background: grey;
+}
+
+</style></head>
+<body>
+There should be no red:
+
+<div class="grid">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="padding-left:3px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 43px">
+  <div style="border-left:2px solid black; padding-left:1px">
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="padding-top:10px">
+  <div>
+    <div class="absolute">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-right:8px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+<div class="grid" style="grid-template-columns: 10px 33px; padding-right:8px; padding-left:10px">
+  <div style="padding-left:3px">
+    <div class="absolute" style="grid-column: 2 / 3">
+      <div class="content"></div>
+      <div class="content"></div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLCanvasElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLCanvasElement.html
new file mode 100644
index 0000000..46b9201e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLCanvasElement.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLCanvasElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="width, height of HTMLCanvasElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-canvas-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('width', 'width', '15', '20', 'width on HTMLCanvasElement', 'canvas', HTMLCanvasElement);
+testReflectAttribute('height', 'height', '23', '45', 'height on HTMLCanvasElement', 'canvas', HTMLCanvasElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDataElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDataElement.html
new file mode 100644
index 0000000..01a3bf34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDataElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLDataElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="value of HTMLDataElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-data-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('value', 'value', '1234', '2345', 'name on HTMLDataElement', 'data', HTMLDataElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDetailsElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDetailsElement.html
new file mode 100644
index 0000000..cdcc2fca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLDetailsElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLDetailsElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="open of HTMLDetailsElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-details-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectBooleanAttribute('open', 'open', 'open on HTMLDetailsElement', 'details', HTMLDetailsElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLMapElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLMapElement.html
new file mode 100644
index 0000000..f6bd04b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLMapElement.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLMapElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLMapElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-map-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<img usemap="#yellow" src="/images/yellow.png" alt="yellow pic">
+<img usemap="#green" src="/images/green.png" alt="green pic">
+<script>
+
+testReflectAttribute('name', 'name', 'yellow', 'green', 'name on HTMLMapElement', 'map', HTMLMapElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLModElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLModElement.html
new file mode 100644
index 0000000..850fe17
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLModElement.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLModElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="cite, dateTime of HTMLModElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#attributes-common-to-ins-and-del-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on ins use HTMLModElement', 'ins', HTMLModElement);
+testReflectAttribute('dateTime', 'datetime', '2018-12-19 00:00Z', '2018-12-20 00:00Z', 'dateTime on ins use HTMLModElement', 'ins', HTMLModElement);
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on del use HTMLModElement', 'del', HTMLModElement);
+testReflectAttribute('dateTime', 'datetime', '2018-10-11T01:25-07:00', '2018-10-12T01:25-07:00', 'dateTime on del use HTMLModElement', 'del', HTMLModElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLOListElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLOListElement.html
new file mode 100644
index 0000000..4e53cdb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLOListElement.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLOListElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="reversed, start, type of HTMLOListElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-ol-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectBooleanAttribute('reversed', 'reversed', 'reversed on HTMLOListElement', 'ol', HTMLOListElement);
+testReflectAttribute('start', 'start', '2', '5', 'start on HTMLOListElement', 'ol', HTMLOListElement);
+testReflectAttribute('type', 'type', '1', 'a', 'type on HTMLOListElement', 'ol', HTMLOListElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLQuoteElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLQuoteElement.html
new file mode 100644
index 0000000..97ab10a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLQuoteElement.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLQuoteElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="cite of HTMLQuoteElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-blockquote-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on blockquote use HTMLQuoteElement', 'blockquote', HTMLQuoteElement);
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on q use HTMLQuoteElement', 'q', HTMLQuoteElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLSlotElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLSlotElement.html
new file mode 100644
index 0000000..aba8f20
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLSlotElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLSlotElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLSlotElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-slot-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('name', 'name', 'slot1', 'slot2', 'name on HTMLSlotElement', 'slot', HTMLSlotElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLTimeElement.html b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLTimeElement.html
new file mode 100644
index 0000000..4643e34
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/HTMLTimeElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLTimeElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLTimeElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-time-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('dateTime', 'datetime', '2018-12-10', '2018-12-12', 'dateTime on HTMLTimeElement', 'time', HTMLTimeElement);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/resources/reactions.js b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/resources/reactions.js
index 6ac7ab8..c7b1851 100644
--- a/third_party/blink/web_tests/external/wpt/custom-elements/reactions/resources/reactions.js
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/reactions/resources/reactions.js
@@ -164,8 +164,8 @@
     testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, validValue1, validValue1, validValue2, validValue2, name, elementName, interfaceName);
 }
 
-function testReflectBooleanAttribute(jsAttributeName, contentAttributeName, name) {
-    testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, true, '', false, null, name);
+function testReflectBooleanAttribute(jsAttributeName, contentAttributeName, name, elementName, interfaceName) {
+    testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, true, '', false, null, name, elementName, interfaceName);
 }
 
 function testAttributeAdder(testFunction, name) {
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record-expected.txt
deleted file mode 100644
index 019fc2ab..0000000
--- a/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-This is a testharness.js-based test.
-PASS Passing nothing to Headers constructor
-PASS Passing undefined to Headers constructor
-PASS Passing null to Headers constructor
-PASS Basic operation with one property
-PASS Basic operation with one property and a proto
-PASS Correct operation ordering with two properties
-PASS Correct operation ordering with two properties one of which has an invalid name
-PASS Correct operation ordering with two properties one of which has an invalid value
-PASS Correct operation ordering with non-enumerable properties
-PASS Correct operation ordering with undefined descriptors
-FAIL Correct operation ordering with repeated keys assert_throws: function "function() { var h = new Headers(proxy); }" did not throw
-PASS Basic operation with Symbol keys
-PASS Operation with non-enumerable Symbol keys
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/offline/application-cache-api/api_update.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/offline/application-cache-api/api_update.https-expected.txt
deleted file mode 100644
index 4466e82c..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/offline/application-cache-api/api_update.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Offline Application Cache - API_update assert_unreached: update method failed. Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/lint.whitelist b/third_party/blink/web_tests/external/wpt/lint.whitelist
index 8c5a32935..765256d0 100644
--- a/third_party/blink/web_tests/external/wpt/lint.whitelist
+++ b/third_party/blink/web_tests/external/wpt/lint.whitelist
@@ -800,6 +800,4 @@
 
 # Signed Exchange files have hard-coded URLs in the certUrl field
 WEB-PLATFORM.TEST:signed-exchange/resources/*.sxg
-WEB-PLATFORM.TEST:signed-exchange/resources/generate-test-sxgs.sh
-
-WEB-PLATFORM.TEST: workers/Worker-location.any.js
\ No newline at end of file
+WEB-PLATFORM.TEST:signed-exchange/resources/generate-test-sxgs.sh
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any-expected.txt
deleted file mode 100644
index 6408c87..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-This is a testharness.js-based test.
-PASS name
-PASS length
-PASS No arguments
-PASS Calling
-PASS Order of evaluation
-PASS Invalid descriptor argument
-PASS Invalid type argument
-FAIL i64 with default WebAssembly.Global(): Descriptor property 'value' must be 'i32', 'f32', or 'f64'
-PASS Default value for type i32
-PASS Explicit value undefined for type i32
-PASS Explicit value null for type i32
-PASS Explicit value true for type i32
-PASS Explicit value false for type i32
-PASS Explicit value 2 for type i32
-PASS Explicit value "3" for type i32
-PASS Explicit value object with toString for type i32
-PASS Explicit value object with valueOf for type i32
-PASS Default value for type f32
-PASS Explicit value undefined for type f32
-PASS Explicit value null for type f32
-PASS Explicit value true for type f32
-PASS Explicit value false for type f32
-PASS Explicit value 2 for type f32
-PASS Explicit value "3" for type f32
-PASS Explicit value object with toString for type f32
-PASS Explicit value object with valueOf for type f32
-PASS Default value for type f64
-PASS Explicit value undefined for type f64
-PASS Explicit value null for type f64
-PASS Explicit value true for type f64
-PASS Explicit value false for type f64
-PASS Explicit value 2 for type f64
-PASS Explicit value "3" for type f64
-PASS Explicit value object with toString for type f64
-PASS Explicit value object with valueOf for type f64
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any.worker-expected.txt
deleted file mode 100644
index 6408c87..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/constructor.any.worker-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-This is a testharness.js-based test.
-PASS name
-PASS length
-PASS No arguments
-PASS Calling
-PASS Order of evaluation
-PASS Invalid descriptor argument
-PASS Invalid type argument
-FAIL i64 with default WebAssembly.Global(): Descriptor property 'value' must be 'i32', 'f32', or 'f64'
-PASS Default value for type i32
-PASS Explicit value undefined for type i32
-PASS Explicit value null for type i32
-PASS Explicit value true for type i32
-PASS Explicit value false for type i32
-PASS Explicit value 2 for type i32
-PASS Explicit value "3" for type i32
-PASS Explicit value object with toString for type i32
-PASS Explicit value object with valueOf for type i32
-PASS Default value for type f32
-PASS Explicit value undefined for type f32
-PASS Explicit value null for type f32
-PASS Explicit value true for type f32
-PASS Explicit value false for type f32
-PASS Explicit value 2 for type f32
-PASS Explicit value "3" for type f32
-PASS Explicit value object with toString for type f32
-PASS Explicit value object with valueOf for type f32
-PASS Default value for type f64
-PASS Explicit value undefined for type f64
-PASS Explicit value null for type f64
-PASS Explicit value true for type f64
-PASS Explicit value false for type f64
-PASS Explicit value 2 for type f64
-PASS Explicit value "3" for type f64
-PASS Explicit value object with toString for type f64
-PASS Explicit value object with valueOf for type f64
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any-expected.txt
deleted file mode 100644
index e1ffba45..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any-expected.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-This is a testharness.js-based test.
-PASS Branding
-PASS Immutable i32 (missing)
-PASS Immutable i32 (undefined)
-PASS Immutable i32 (null)
-PASS Immutable i32 (false)
-PASS Immutable i32 (empty string)
-PASS Immutable i32 (zero)
-PASS Mutable i32 (true)
-PASS Mutable i32 (one)
-PASS Mutable i32 (string)
-PASS Mutable i32 (true on prototype)
-PASS Immutable f32 (missing)
-PASS Immutable f32 (undefined)
-PASS Immutable f32 (null)
-PASS Immutable f32 (false)
-PASS Immutable f32 (empty string)
-PASS Immutable f32 (zero)
-PASS Mutable f32 (true)
-PASS Mutable f32 (one)
-PASS Mutable f32 (string)
-PASS Mutable f32 (true on prototype)
-PASS Immutable f64 (missing)
-PASS Immutable f64 (undefined)
-PASS Immutable f64 (null)
-PASS Immutable f64 (false)
-PASS Immutable f64 (empty string)
-PASS Immutable f64 (zero)
-PASS Mutable f64 (true)
-PASS Mutable f64 (one)
-PASS Mutable f64 (string)
-PASS Mutable f64 (true on prototype)
-FAIL i64 with default WebAssembly.Global(): Descriptor property 'value' must be 'i32', 'f32', or 'f64'
-FAIL Calling setter without argument assert_throws: function "() => setter.call(global)" did not throw
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any.worker-expected.txt
deleted file mode 100644
index e1ffba45..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/global/value-get-set.any.worker-expected.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-This is a testharness.js-based test.
-PASS Branding
-PASS Immutable i32 (missing)
-PASS Immutable i32 (undefined)
-PASS Immutable i32 (null)
-PASS Immutable i32 (false)
-PASS Immutable i32 (empty string)
-PASS Immutable i32 (zero)
-PASS Mutable i32 (true)
-PASS Mutable i32 (one)
-PASS Mutable i32 (string)
-PASS Mutable i32 (true on prototype)
-PASS Immutable f32 (missing)
-PASS Immutable f32 (undefined)
-PASS Immutable f32 (null)
-PASS Immutable f32 (false)
-PASS Immutable f32 (empty string)
-PASS Immutable f32 (zero)
-PASS Mutable f32 (true)
-PASS Mutable f32 (one)
-PASS Mutable f32 (string)
-PASS Mutable f32 (true on prototype)
-PASS Immutable f64 (missing)
-PASS Immutable f64 (undefined)
-PASS Immutable f64 (null)
-PASS Immutable f64 (false)
-PASS Immutable f64 (empty string)
-PASS Immutable f64 (zero)
-PASS Mutable f64 (true)
-PASS Mutable f64 (one)
-PASS Mutable f64 (string)
-PASS Mutable f64 (true on prototype)
-FAIL i64 with default WebAssembly.Global(): Descriptor property 'value' must be 'i32', 'f32', or 'f64'
-FAIL Calling setter without argument assert_throws: function "() => setter.call(global)" did not throw
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any-expected.txt
deleted file mode 100644
index d120c0a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any-expected.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-This is a testharness.js-based test.
-Found 63 tests; 46 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS wasm-js-api interfaces.
-FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false
-PASS Module interface: existence and properties of interface object
-PASS Module interface object length
-PASS Module interface object name
-PASS Module interface: existence and properties of interface prototype object
-PASS Module interface: existence and properties of interface prototype object's "constructor" property
-PASS Module interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Module interface: operation exports(Module) assert_true: property should be enumerable expected true got false
-FAIL Module interface: operation imports(Module) assert_true: property should be enumerable expected true got false
-FAIL Module interface: operation customSections(Module, USVString) assert_true: property should be enumerable expected true got false
-PASS Module must be primary interface of mod
-PASS Stringification of mod
-PASS Module interface: mod must inherit property "exports(Module)" with the proper type
-PASS Module interface: calling exports(Module) on mod with too few arguments must throw TypeError
-PASS Module interface: mod must inherit property "imports(Module)" with the proper type
-PASS Module interface: calling imports(Module) on mod with too few arguments must throw TypeError
-PASS Module interface: mod must inherit property "customSections(Module, USVString)" with the proper type
-PASS Module interface: calling customSections(Module, USVString) on mod with too few arguments must throw TypeError
-PASS Instance interface: existence and properties of interface object
-PASS Instance interface object length
-PASS Instance interface object name
-PASS Instance interface: existence and properties of interface prototype object
-PASS Instance interface: existence and properties of interface prototype object's "constructor" property
-PASS Instance interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Instance interface: attribute exports assert_true: property should be enumerable expected true got false
-PASS Instance must be primary interface of instance
-PASS Stringification of instance
-PASS Instance interface: instance must inherit property "exports" with the proper type
-PASS Memory interface: existence and properties of interface object
-PASS Memory interface object length
-PASS Memory interface object name
-PASS Memory interface: existence and properties of interface prototype object
-PASS Memory interface: existence and properties of interface prototype object's "constructor" property
-PASS Memory interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Memory interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Memory interface: attribute buffer assert_true: property should be enumerable expected true got false
-PASS Memory must be primary interface of memory
-PASS Stringification of memory
-PASS Memory interface: memory must inherit property "grow(unsigned long)" with the proper type
-FAIL Memory interface: calling grow(unsigned long) on memory with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function() {
-            fn.apply(obj, args);
-        }" did not throw
-PASS Memory interface: memory must inherit property "buffer" with the proper type
-PASS Table interface: existence and properties of interface object
-PASS Table interface object length
-PASS Table interface object name
-PASS Table interface: existence and properties of interface prototype object
-PASS Table interface: existence and properties of interface prototype object's "constructor" property
-PASS Table interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Table interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Table interface: operation get(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Table interface: operation set(unsigned long, Function) assert_true: property should be enumerable expected true got false
-FAIL Table interface: attribute length assert_true: property should be enumerable expected true got false
-PASS Global interface: existence and properties of interface object
-PASS Global interface object length
-PASS Global interface object name
-PASS Global interface: existence and properties of interface prototype object
-PASS Global interface: existence and properties of interface prototype object's "constructor" property
-PASS Global interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Global interface: operation valueOf() assert_true: property should be enumerable expected true got false
-FAIL Global interface: attribute value assert_true: property should be enumerable expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt
deleted file mode 100644
index d120c0a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/idlharness.any.worker-expected.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-This is a testharness.js-based test.
-Found 63 tests; 46 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS wasm-js-api interfaces.
-FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false
-PASS Module interface: existence and properties of interface object
-PASS Module interface object length
-PASS Module interface object name
-PASS Module interface: existence and properties of interface prototype object
-PASS Module interface: existence and properties of interface prototype object's "constructor" property
-PASS Module interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Module interface: operation exports(Module) assert_true: property should be enumerable expected true got false
-FAIL Module interface: operation imports(Module) assert_true: property should be enumerable expected true got false
-FAIL Module interface: operation customSections(Module, USVString) assert_true: property should be enumerable expected true got false
-PASS Module must be primary interface of mod
-PASS Stringification of mod
-PASS Module interface: mod must inherit property "exports(Module)" with the proper type
-PASS Module interface: calling exports(Module) on mod with too few arguments must throw TypeError
-PASS Module interface: mod must inherit property "imports(Module)" with the proper type
-PASS Module interface: calling imports(Module) on mod with too few arguments must throw TypeError
-PASS Module interface: mod must inherit property "customSections(Module, USVString)" with the proper type
-PASS Module interface: calling customSections(Module, USVString) on mod with too few arguments must throw TypeError
-PASS Instance interface: existence and properties of interface object
-PASS Instance interface object length
-PASS Instance interface object name
-PASS Instance interface: existence and properties of interface prototype object
-PASS Instance interface: existence and properties of interface prototype object's "constructor" property
-PASS Instance interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Instance interface: attribute exports assert_true: property should be enumerable expected true got false
-PASS Instance must be primary interface of instance
-PASS Stringification of instance
-PASS Instance interface: instance must inherit property "exports" with the proper type
-PASS Memory interface: existence and properties of interface object
-PASS Memory interface object length
-PASS Memory interface object name
-PASS Memory interface: existence and properties of interface prototype object
-PASS Memory interface: existence and properties of interface prototype object's "constructor" property
-PASS Memory interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Memory interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Memory interface: attribute buffer assert_true: property should be enumerable expected true got false
-PASS Memory must be primary interface of memory
-PASS Stringification of memory
-PASS Memory interface: memory must inherit property "grow(unsigned long)" with the proper type
-FAIL Memory interface: calling grow(unsigned long) on memory with too few arguments must throw TypeError assert_throws: Called with 0 arguments function "function() {
-            fn.apply(obj, args);
-        }" did not throw
-PASS Memory interface: memory must inherit property "buffer" with the proper type
-PASS Table interface: existence and properties of interface object
-PASS Table interface object length
-PASS Table interface object name
-PASS Table interface: existence and properties of interface prototype object
-PASS Table interface: existence and properties of interface prototype object's "constructor" property
-PASS Table interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Table interface: operation grow(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Table interface: operation get(unsigned long) assert_true: property should be enumerable expected true got false
-FAIL Table interface: operation set(unsigned long, Function) assert_true: property should be enumerable expected true got false
-FAIL Table interface: attribute length assert_true: property should be enumerable expected true got false
-PASS Global interface: existence and properties of interface object
-PASS Global interface object length
-PASS Global interface object name
-PASS Global interface: existence and properties of interface prototype object
-PASS Global interface: existence and properties of interface prototype object's "constructor" property
-PASS Global interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Global interface: operation valueOf() assert_true: property should be enumerable expected true got false
-FAIL Global interface: attribute value assert_true: property should be enumerable expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any-expected.txt
deleted file mode 100644
index b1d0c2b..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any-expected.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-This is a testharness.js-based test.
-Found 72 tests; 57 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS WebAssembly: property descriptor
-PASS WebAssembly: calling
-PASS WebAssembly: constructing
-PASS WebAssembly.Module: property descriptor
-PASS WebAssembly.Module: prototype
-PASS WebAssembly.Module: prototype.constructor
-PASS WebAssembly.Instance: property descriptor
-PASS WebAssembly.Instance: prototype
-PASS WebAssembly.Instance: prototype.constructor
-PASS WebAssembly.Memory: property descriptor
-PASS WebAssembly.Memory: prototype
-PASS WebAssembly.Memory: prototype.constructor
-PASS WebAssembly.Table: property descriptor
-PASS WebAssembly.Table: prototype
-PASS WebAssembly.Table: prototype.constructor
-PASS WebAssembly.Global: property descriptor
-PASS WebAssembly.Global: prototype
-PASS WebAssembly.Global: prototype.constructor
-PASS WebAssembly.CompileError: property descriptor
-PASS WebAssembly.CompileError: prototype
-PASS WebAssembly.CompileError: prototype.constructor
-PASS WebAssembly.LinkError: property descriptor
-PASS WebAssembly.LinkError: prototype
-PASS WebAssembly.LinkError: prototype.constructor
-PASS WebAssembly.RuntimeError: property descriptor
-PASS WebAssembly.RuntimeError: prototype
-PASS WebAssembly.RuntimeError: prototype.constructor
-FAIL WebAssembly.validate assert_true: enumerable expected true got false
-PASS WebAssembly.validate: name
-PASS WebAssembly.validate: length
-FAIL WebAssembly.compile assert_true: enumerable expected true got false
-PASS WebAssembly.compile: name
-PASS WebAssembly.compile: length
-FAIL WebAssembly.instantiate assert_true: enumerable expected true got false
-PASS WebAssembly.instantiate: name
-PASS WebAssembly.instantiate: length
-FAIL WebAssembly.Module.exports assert_true: enumerable expected true got false
-PASS WebAssembly.Module.exports: name
-PASS WebAssembly.Module.exports: length
-FAIL WebAssembly.Module.imports assert_true: enumerable expected true got false
-PASS WebAssembly.Module.imports: name
-PASS WebAssembly.Module.imports: length
-FAIL WebAssembly.Module.customSections assert_true: enumerable expected true got false
-PASS WebAssembly.Module.customSections: name
-PASS WebAssembly.Module.customSections: length
-FAIL WebAssembly.Instance.exports assert_true: enumerable expected true got false
-PASS WebAssembly.Instance.exports: getter
-PASS WebAssembly.Instance.exports: setter
-FAIL WebAssembly.Memory.grow assert_true: enumerable expected true got false
-PASS WebAssembly.Memory.grow: name
-PASS WebAssembly.Memory.grow: length
-FAIL WebAssembly.Memory.buffer assert_true: enumerable expected true got false
-PASS WebAssembly.Memory.buffer: getter
-PASS WebAssembly.Memory.buffer: setter
-FAIL WebAssembly.Table.grow assert_true: enumerable expected true got false
-PASS WebAssembly.Table.grow: name
-PASS WebAssembly.Table.grow: length
-FAIL WebAssembly.Table.get assert_true: enumerable expected true got false
-PASS WebAssembly.Table.get: name
-PASS WebAssembly.Table.get: length
-FAIL WebAssembly.Table.set assert_true: enumerable expected true got false
-PASS WebAssembly.Table.set: name
-PASS WebAssembly.Table.set: length
-FAIL WebAssembly.Table.length assert_true: enumerable expected true got false
-PASS WebAssembly.Table.length: getter
-PASS WebAssembly.Table.length: setter
-FAIL WebAssembly.Global.valueOf assert_true: enumerable expected true got false
-PASS WebAssembly.Global.valueOf: name
-PASS WebAssembly.Global.valueOf: length
-FAIL WebAssembly.Global.value assert_true: enumerable expected true got false
-PASS WebAssembly.Global.value: getter
-PASS WebAssembly.Global.value: setter
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt
deleted file mode 100644
index b1d0c2b..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-This is a testharness.js-based test.
-Found 72 tests; 57 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS WebAssembly: property descriptor
-PASS WebAssembly: calling
-PASS WebAssembly: constructing
-PASS WebAssembly.Module: property descriptor
-PASS WebAssembly.Module: prototype
-PASS WebAssembly.Module: prototype.constructor
-PASS WebAssembly.Instance: property descriptor
-PASS WebAssembly.Instance: prototype
-PASS WebAssembly.Instance: prototype.constructor
-PASS WebAssembly.Memory: property descriptor
-PASS WebAssembly.Memory: prototype
-PASS WebAssembly.Memory: prototype.constructor
-PASS WebAssembly.Table: property descriptor
-PASS WebAssembly.Table: prototype
-PASS WebAssembly.Table: prototype.constructor
-PASS WebAssembly.Global: property descriptor
-PASS WebAssembly.Global: prototype
-PASS WebAssembly.Global: prototype.constructor
-PASS WebAssembly.CompileError: property descriptor
-PASS WebAssembly.CompileError: prototype
-PASS WebAssembly.CompileError: prototype.constructor
-PASS WebAssembly.LinkError: property descriptor
-PASS WebAssembly.LinkError: prototype
-PASS WebAssembly.LinkError: prototype.constructor
-PASS WebAssembly.RuntimeError: property descriptor
-PASS WebAssembly.RuntimeError: prototype
-PASS WebAssembly.RuntimeError: prototype.constructor
-FAIL WebAssembly.validate assert_true: enumerable expected true got false
-PASS WebAssembly.validate: name
-PASS WebAssembly.validate: length
-FAIL WebAssembly.compile assert_true: enumerable expected true got false
-PASS WebAssembly.compile: name
-PASS WebAssembly.compile: length
-FAIL WebAssembly.instantiate assert_true: enumerable expected true got false
-PASS WebAssembly.instantiate: name
-PASS WebAssembly.instantiate: length
-FAIL WebAssembly.Module.exports assert_true: enumerable expected true got false
-PASS WebAssembly.Module.exports: name
-PASS WebAssembly.Module.exports: length
-FAIL WebAssembly.Module.imports assert_true: enumerable expected true got false
-PASS WebAssembly.Module.imports: name
-PASS WebAssembly.Module.imports: length
-FAIL WebAssembly.Module.customSections assert_true: enumerable expected true got false
-PASS WebAssembly.Module.customSections: name
-PASS WebAssembly.Module.customSections: length
-FAIL WebAssembly.Instance.exports assert_true: enumerable expected true got false
-PASS WebAssembly.Instance.exports: getter
-PASS WebAssembly.Instance.exports: setter
-FAIL WebAssembly.Memory.grow assert_true: enumerable expected true got false
-PASS WebAssembly.Memory.grow: name
-PASS WebAssembly.Memory.grow: length
-FAIL WebAssembly.Memory.buffer assert_true: enumerable expected true got false
-PASS WebAssembly.Memory.buffer: getter
-PASS WebAssembly.Memory.buffer: setter
-FAIL WebAssembly.Table.grow assert_true: enumerable expected true got false
-PASS WebAssembly.Table.grow: name
-PASS WebAssembly.Table.grow: length
-FAIL WebAssembly.Table.get assert_true: enumerable expected true got false
-PASS WebAssembly.Table.get: name
-PASS WebAssembly.Table.get: length
-FAIL WebAssembly.Table.set assert_true: enumerable expected true got false
-PASS WebAssembly.Table.set: name
-PASS WebAssembly.Table.set: length
-FAIL WebAssembly.Table.length assert_true: enumerable expected true got false
-PASS WebAssembly.Table.length: getter
-PASS WebAssembly.Table.length: setter
-FAIL WebAssembly.Global.valueOf assert_true: enumerable expected true got false
-PASS WebAssembly.Global.valueOf: name
-PASS WebAssembly.Global.valueOf: length
-FAIL WebAssembly.Global.value assert_true: enumerable expected true got false
-PASS WebAssembly.Global.value: getter
-PASS WebAssembly.Global.value: setter
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt
deleted file mode 100644
index 1f0c1b04..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-This is a testharness.js-based test.
-FAIL Missing arguments assert_throws: function "() => memory.grow()" did not throw
-PASS Branding
-PASS Zero initial
-PASS Zero initial with valueOf
-PASS Non-zero initial
-PASS Zero initial with respected maximum
-PASS Zero initial with respected maximum grown twice
-PASS Zero initial growing too much
-FAIL Out-of-range argument: undefined assert_throws: function "() => memory.grow(value)" did not throw
-FAIL Out-of-range argument: NaN assert_throws: function "() => memory.grow(value)" did not throw
-FAIL Out-of-range argument: Infinity assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -Infinity assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): trying to shrink memory" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -1 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): trying to shrink memory" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 4294967296 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 68719476736 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: "0x100000000" assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: object "[object Object]" assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt
deleted file mode 100644
index 1f0c1b04..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-This is a testharness.js-based test.
-FAIL Missing arguments assert_throws: function "() => memory.grow()" did not throw
-PASS Branding
-PASS Zero initial
-PASS Zero initial with valueOf
-PASS Non-zero initial
-PASS Zero initial with respected maximum
-PASS Zero initial with respected maximum grown twice
-PASS Zero initial growing too much
-FAIL Out-of-range argument: undefined assert_throws: function "() => memory.grow(value)" did not throw
-FAIL Out-of-range argument: NaN assert_throws: function "() => memory.grow(value)" did not throw
-FAIL Out-of-range argument: Infinity assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -Infinity assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): trying to shrink memory" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -1 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): trying to shrink memory" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 4294967296 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 68719476736 assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: "0x100000000" assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: object "[object Object]" assert_throws: function "() => memory.grow(value)" threw object "RangeError: WebAssembly.Memory.grow(): maximum memory size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt
deleted file mode 100644
index db2b748..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-This is a testharness.js-based test.
-PASS name
-PASS length
-PASS No arguments
-PASS Calling
-PASS Empty descriptor
-PASS Invalid descriptor argument
-FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })" did not throw
-PASS Undefined element value in descriptor
-FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" did not throw
-FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" did not throw
-FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-PASS Initial value exceeds maximum
-PASS Basic (zero)
-PASS Basic (non-zero)
-PASS Stray argument
-FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code
-PASS Type conversion for descriptor.element
-PASS Order of evaluation for descriptor
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt
deleted file mode 100644
index db2b748..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-This is a testharness.js-based test.
-PASS name
-PASS length
-PASS No arguments
-PASS Calling
-PASS Empty descriptor
-PASS Invalid descriptor argument
-FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })" did not throw
-PASS Undefined element value in descriptor
-FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" did not throw
-FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" did not throw
-FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError")
-PASS Initial value exceeds maximum
-PASS Basic (zero)
-PASS Basic (non-zero)
-PASS Stray argument
-FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code
-PASS Type conversion for descriptor.element
-PASS Order of evaluation for descriptor
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any-expected.txt
deleted file mode 100644
index 522e84a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-This is a testharness.js-based test.
-FAIL Missing arguments assert_throws: function "() => table.grow()" did not throw
-PASS Branding
-FAIL Basic assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Reached maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Exceeded maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: undefined assert_throws: function "() => table.grow(value)" did not throw
-FAIL Out-of-range argument: NaN assert_throws: function "() => table.grow(value)" did not throw
-FAIL Out-of-range argument: Infinity assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -Infinity assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): trying to shrink table" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -1 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): trying to shrink table" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 4294967296 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 68719476736 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: "0x100000000" assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: object "[object Object]" assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Stray argument assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any.worker-expected.txt
deleted file mode 100644
index 522e84a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/grow.any.worker-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-This is a testharness.js-based test.
-FAIL Missing arguments assert_throws: function "() => table.grow()" did not throw
-PASS Branding
-FAIL Basic assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Reached maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Exceeded maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: undefined assert_throws: function "() => table.grow(value)" did not throw
-FAIL Out-of-range argument: NaN assert_throws: function "() => table.grow(value)" did not throw
-FAIL Out-of-range argument: Infinity assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -Infinity assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): trying to shrink table" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: -1 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): trying to shrink table" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 4294967296 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: 68719476736 assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: "0x100000000" assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Out-of-range argument: object "[object Object]" assert_throws: function "() => table.grow(value)" threw object "RangeError: WebAssembly.Table.grow(): maximum table size exceeded" ("RangeError") expected object "TypeError" ("TypeError")
-FAIL Stray argument assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "RangeError: WebAssembly.Table.get(): index out of bounds" ("RangeError") expected object "TypeError" ("TypeError")
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any-expected.txt
deleted file mode 100644
index c0d8c7a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial namespace WebAssembly: original namespace defined
-FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compileStreaming([object Object]) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiateStreaming([object Object], object) assert_true: property should be enumerable expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any.worker-expected.txt
deleted file mode 100644
index c0d8c7a..0000000
--- a/third_party/blink/web_tests/external/wpt/wasm/webapi/idlharness.any.worker-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS Partial namespace WebAssembly: original namespace defined
-FAIL WebAssembly namespace: operation validate(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compile(BufferSource) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(BufferSource, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiate(Module, object) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation compileStreaming([object Object]) assert_true: property should be enumerable expected true got false
-FAIL WebAssembly namespace: operation instantiateStreaming([object Object], object) assert_true: property should be enumerable expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/workers/Worker-location.any.js b/third_party/blink/web_tests/external/wpt/workers/Worker-location.any.js
deleted file mode 100644
index c2a4590..0000000
--- a/third_party/blink/web_tests/external/wpt/workers/Worker-location.any.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// META: global=!default, dedicatedworker, sharedworker
-test(() => {
-  assert_equals(String(WorkerLocation), "function WorkerLocation() { [native code] }");
-  assert_true(location instanceof Object);
-  assert_equals(location.href, "http://web-platform.test:8001/workers/Worker-location.any.worker.js")
-  assert_equals(location.origin, "http://web-platform.test:8001");
-  assert_equals(location.protocol, "http:");
-  assert_equals(location.host, "web-platform.test:8001");
-  assert_equals(location.hostname, "web-platform.test");
-  assert_equals(location.port, "8001");
-  assert_equals(location.pathname, "/workers/Worker-location.any.worker.js");
-  assert_equals(location.search, "");
-  assert_equals(location.hash, "");
-}, 'Test WorkerLocation properties.');
diff --git a/third_party/blink/web_tests/external/wpt/workers/Worker-location.sub.any.js b/third_party/blink/web_tests/external/wpt/workers/Worker-location.sub.any.js
new file mode 100644
index 0000000..2ef9445
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/workers/Worker-location.sub.any.js
@@ -0,0 +1,14 @@
+// META: global=!default, dedicatedworker, sharedworker
+test(() => {
+  assert_equals(String(WorkerLocation), "function WorkerLocation() { [native code] }");
+  assert_true(location instanceof Object);
+  assert_equals(location.href, 'http://{{host}}:{{ports[http][0]}}/workers/Worker-location.sub.any.worker.js');
+  assert_equals(location.origin, "http://{{host}}:{{ports[http][0]}}");
+  assert_equals(location.protocol, "http:");
+  assert_equals(location.host, "{{host}}:{{ports[http][0]}}");
+  assert_equals(location.hostname, "{{host}}");
+  assert_equals(location.port, "{{ports[http][0]}}");
+  assert_equals(location.pathname, "/workers/Worker-location.sub.any.worker.js");
+  assert_equals(location.search, "");
+  assert_equals(location.hash, "");
+}, 'Test WorkerLocation properties.');
diff --git a/third_party/blink/web_tests/media/controls/tab-into-controls-after-touch.html b/third_party/blink/web_tests/media/controls/tab-into-controls-after-touch.html
new file mode 100644
index 0000000..c7ad4cfe
--- /dev/null
+++ b/third_party/blink/web_tests/media/controls/tab-into-controls-after-touch.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Test that when a video is touched to play, you can still tab into the controls.</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../media-controls.js"></script>
+<video controls width=500 preload=none src="../content/60_sec_video.webm"></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+  enableTestMode(video);
+
+  video.addEventListener('loadedmetadata', t.step_func(() => {
+    assert_true(isControlsPanelVisible(video),
+        'controls should be visible before tapping');
+
+    // Touch the play button to start the video and hide the controls.
+    singleTouchOnControl(enabledPlayButton(video));
+  }));
+
+  video.addEventListener('playing', t.step_func(() => {
+    // Once the video is playing, wait for the controls to hide.
+    runAfterHideMediaControlsTimerFired(t.step_func_done(() => {
+      assert_false(isControlsPanelVisible(video),
+          'controls should hide after tapping on the play button');
+
+      // Tab to focus the video.
+      eventSender.keyDown('Tab');
+      assert_true(isControlsPanelVisible(video),
+          'controls should show when tabbed into')
+    }), video);
+  }));
+
+  video.load();
+});
+</script>
+</html>
diff --git a/third_party/blink/web_tests/media/media-controls-fit-properly-while-zoomed-expected.txt b/third_party/blink/web_tests/media/media-controls-fit-properly-while-zoomed-expected.txt
deleted file mode 100644
index b191f24..0000000
--- a/third_party/blink/web_tests/media/media-controls-fit-properly-while-zoomed-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL media controls adjust for zoom when filling the bar assert_true: timeline should not be hidden while zoomed expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt
deleted file mode 100644
index 93d4b4ef..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/dom/events/Event-dispatch-on-disabled-elements-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS Can dispatch untrusted 'click' Events at disabled HTML elements.
-PASS Can dispatch untrusted Events at disabled HTML elements.
-PASS Can dispatch CustomEvents at disabled HTML elements.
-PASS Calling click() on disabled elements must not dispatch events.
-FAIL Real clicks on disabled elements must not dispatch events. assert_true: HTMLSelectElement is enabled, so onclick must fire. expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub-expected.txt
deleted file mode 100644
index 618f0bf..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-PASS General setup
-PASS Set location.protocol = location.protocol
-PASS Set location.protocol to http:gunk
-PASS Message listener
-FAIL Message listener Cannot read property 'test' of undefined
-PASS Message listener
-Harness: the test ran to completion.
-
diff --git a/tools/clang/pylib/clang/PRESUBMIT.py b/tools/clang/pylib/clang/PRESUBMIT.py
new file mode 100644
index 0000000..0ca7653
--- /dev/null
+++ b/tools/clang/pylib/clang/PRESUBMIT.py
@@ -0,0 +1,21 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def _CommonChecks(input_api, output_api):
+  results = []
+
+  # Run the unit tests.
+  results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
+      input_api, output_api, '.', [ r'^.+_test\.py$']))
+
+  return results
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return _CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return _CommonChecks(input_api, output_api)
diff --git a/tools/clang/pylib/clang/compile_db.py b/tools/clang/pylib/clang/compile_db.py
index 4dbe39c..5c769d886 100755
--- a/tools/clang/pylib/clang/compile_db.py
+++ b/tools/clang/pylib/clang/compile_db.py
@@ -6,25 +6,42 @@
 import json
 import os
 import re
-import shlex
 import sys
 import subprocess
 
 
 _RSP_RE = re.compile(r' (@(.+?\.rsp)) ')
+_CMD_LINE_RE = re.compile(
+    r'^(?P<gomacc>.*gomacc\.exe"?\s+)?(?P<clang>\S*clang\S*)\s+(?P<args>.*)$')
 _debugging = False
 
 
-def _ProcessEntry(entry):
-  """Transforms one entry in the compile database to be clang-tool friendly."""
-  split_command = shlex.split(entry['command'], posix=(sys.platform != 'win32'))
+def _ProcessCommand(command):
+  """Removes gomacc.exe and inserts --driver-mode=cl as the first argument.
 
-  # Drop gomacc.exe from the front, if present.
-  if split_command[0].endswith('gomacc.exe'):
-    split_command = split_command[1:]
-  # Insert --driver-mode=cl as the first argument.
-  split_command = split_command[:1] + ['--driver-mode=cl'] + split_command[1:]
-  entry['command'] = subprocess.list2cmdline(split_command)
+  Note that we deliberately don't use shlex.split here, because it doesn't work
+  predictably for Windows commands (specifically, it doesn't parse args the same
+  way that Clang does on Windows).
+
+  Instead, we just use a regex, with the simplifying assumption that the path to
+  clang-cl.exe contains no spaces.
+  """
+  match = _CMD_LINE_RE.search(command)
+  if match:
+    match_dict = match.groupdict()
+    command = ' '.join(
+        [match_dict['clang'], '--driver-mode=cl', match_dict['args']])
+  elif _debugging:
+    print 'Compile command didn\'t match expected regex!'
+    print 'Command:', command
+    print 'Regex:', _CMD_LINE_RE.pattern
+
+  return command
+
+
+def _ProcessEntry(entry):
+  """Transforms one entry in a Windows compile db to be clang-tool friendly."""
+  entry['command'] = _ProcessCommand(entry['command'])
 
   # Expand the contents of the response file, if any.
   # http://llvm.org/bugs/show_bug.cgi?id=21634
@@ -59,7 +76,7 @@
   if sys.platform != 'win32':
     return compile_db
 
-  if _debugging > 0:
+  if _debugging:
     print 'Read in %d entries from the compile db' % len(compile_db)
   compile_db = [_ProcessEntry(e) for e in compile_db]
   original_length = len(compile_db)
@@ -68,7 +85,7 @@
   # TODO(dcheng): This doesn't appear to do anything anymore, remove?
   compile_db = [e for e in compile_db if '_nacl.cc.pdb' not in e['command']
       and '_nacl_win64.cc.pdb' not in e['command']]
-  if _debugging > 0:
+  if _debugging:
     print 'Filtered out %d entries...' % (original_length - len(compile_db))
 
   # TODO(dcheng): Also filter out multiple commands for the same file. Not sure
diff --git a/tools/clang/pylib/clang/compile_db_test.py b/tools/clang/pylib/clang/compile_db_test.py
new file mode 100755
index 0000000..493f2f815
--- /dev/null
+++ b/tools/clang/pylib/clang/compile_db_test.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env vpython
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Tests for compile_db."""
+
+import sys
+import unittest
+
+import compile_db
+
+
+# Input compile DB.
+_TEST_COMPILE_DB = [
+    # Verifies that gomacc.exe is removed.
+    {
+        'command': r'C:\gomacc.exe C:\clang-cl.exe /blah',
+    },
+    # Verifies a goma path containing a space.
+    {
+        'command': r'"C:\Program Files\gomacc.exe" C:\clang-cl.exe /blah',
+    },
+    # Includes a string define.
+    {
+        'command': r'clang-cl.exe /blah "-DCR_CLANG_REVISION=\"346388-1\""',
+    },
+    # Includes a string define with a space in it.
+    {
+        'command': r'clang-cl.exe /blah -D"MY_DEFINE=\"MY VALUE\""',
+    },
+]
+
+# Expected compile DB after processing for windows.
+_EXPECTED_COMPILE_DB = [
+    {
+        'command': r'C:\clang-cl.exe --driver-mode=cl /blah',
+    },
+    {
+        'command': r'C:\clang-cl.exe --driver-mode=cl /blah',
+    },
+    {
+        'command': r'clang-cl.exe --driver-mode=cl /blah '
+                   r'"-DCR_CLANG_REVISION=\"346388-1\""',
+    },
+    {
+        'command': r'clang-cl.exe --driver-mode=cl /blah '
+                   r'-D"MY_DEFINE=\"MY VALUE\""',
+    },
+]
+
+
+class CompileDbTest(unittest.TestCase):
+
+  def setUp(self):
+    self.maxDiff = None
+
+  def testProcessNotOnWindows(self):
+    sys.platform = 'linux2'
+    processed_compile_db = compile_db.ProcessCompileDatabaseIfNeeded(
+        _TEST_COMPILE_DB)
+
+    # Assert no changes were made.
+    self.assertItemsEqual(processed_compile_db, _TEST_COMPILE_DB)
+
+  def testProcessForWindows(self):
+    sys.platform = 'win32'
+    processed_compile_db = compile_db.ProcessCompileDatabaseIfNeeded(
+        _TEST_COMPILE_DB)
+
+    # Check each entry individually to improve readability of the output.
+    for actual, expected in zip(processed_compile_db, _EXPECTED_COMPILE_DB):
+      self.assertDictEqual(actual, expected)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 94cfcc4..3e8adec 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -605,6 +605,8 @@
       'android_n5x_swarming_dbg': 'android_debug_trybot_arm64',
       'android_optional_gpu_tests_rel': 'gpu_tests_android_release_trybot_arm64',
       'android_unswarmed_pixel_aosp': 'android_debug_trybot_arm64',
+      'android-deterministic-dbg': 'android_debug_trybot',
+      'android-deterministic-rel': 'android_without_codecs_release_trybot_minimal_symbols',
       'cast_shell_android': 'android_cast_debug_static_bot_compile_only',
       'gpu-manual-try-android-l-nexus-5-32': 'gpu_tests_android_release_trybot',
       'gpu-manual-try-android-l-nexus-6-32': 'gpu_tests_android_release_trybot',
@@ -1030,6 +1032,10 @@
       'android_without_codecs', 'release_bot', 'minimal_symbols', 'strip_debug_info',
     ],
 
+    'android_without_codecs_release_trybot_minimal_symbols': [
+      'android_without_codecs', 'release_trybot', 'minimal_symbols', 'strip_debug_info',
+    ],
+
     'asan_clang_edge_fuzzer_static_v8_heap_minimal_symbols_release_tot': [
       'asan', 'clang_tot', 'edge', 'fuzzer', 'static', 'v8_heap', 'minimal_symbols', 'release',
     ],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 2fec970..99f7c8be 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -30934,6 +30934,7 @@
   <int value="-1454397907" label="OptimizationHints:disabled"/>
   <int value="-1451644187" label="OverviewSwipeToClose:enabled"/>
   <int value="-1450576851" label="OmniboxUIExperimentVerticalLayout:enabled"/>
+  <int value="-1448511207" label="UseMessagesStagingUrl:disabled"/>
   <int value="-1447147245" label="VideoPlayerNativeControls:enabled"/>
   <int value="-1446425986" label="ProtectSyncCredentialOnReauth:disabled"/>
   <int value="-1444051091" label="ash-disable-night-light"/>
@@ -31848,6 +31849,7 @@
   <int value="123097915" label="FaviconsFromWebManifest:enabled"/>
   <int value="125581289" label="WebRtcHWVP8Encoding:disabled"/>
   <int value="125934378" label="enable-password-link"/>
+  <int value="128086566" label="D3D11VideoDecoder:enabled"/>
   <int value="131881947" label="D3DVsync:enabled"/>
   <int value="132560299"
       label="OmniboxUIExperimentHideSteadyStateUrlScheme:disabled"/>
@@ -32596,6 +32598,7 @@
   <int value="1454527518" label="ArcNativeBridgeExperiment:enabled"/>
   <int value="1455881930" label="V8VmFuture:enabled"/>
   <int value="1458255488" label="BlinkGenPropertyTrees:enabled"/>
+  <int value="1458475849" label="D3D11VideoDecoder:disabled"/>
   <int value="1458583431" label="arc-use-auth-endpoint"/>
   <int value="1459529277" label="disable-text-input-focus-manager"/>
   <int value="1460747747" label="GdiTextPrinting:enabled"/>
@@ -32880,7 +32883,6 @@
   <int value="1949908940" label="disable-zip-archiver-unpacker"/>
   <int value="1951466218" label="enable-data-reduction-proxy-lite-page"/>
   <int value="1951645673" label="PasswordsKeyboardAccessory:disabled"/>
-  <int value="1955677113" label="trace-export-events-to-etw"/>
   <int value="1957273171" label="PageAlmostIdle:disabled"/>
   <int value="1957358530" label="ContextualSearchSecondTap:enabled"/>
   <int value="1957472162"
@@ -32942,6 +32944,7 @@
   <int value="2040316611" label="IPH_ReopenTab:enabled"/>
   <int value="2043321329" label="OfflinePagesPrefetchingUI:disabled"/>
   <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
+  <int value="2058148069" label="UseMessagesStagingUrl:enabled"/>
   <int value="2058283872" label="CCTModuleCache:disabled"/>
   <int value="2058439723" label="CalculateNativeWinOcclusion:disabled"/>
   <int value="2059322877" label="new-avatar-menu"/>
@@ -34653,6 +34656,14 @@
   <int value="27" label="iPhoto file system used this session (obsolete)"/>
 </enum>
 
+<enum name="MediaHardwareKeyAction">
+  <int value="0" label="Play"/>
+  <int value="1" label="Pause"/>
+  <int value="2" label="Stop"/>
+  <int value="3" label="Next Track"/>
+  <int value="4" label="Previous Track"/>
+</enum>
+
 <enum name="MediaKeyError">
   <int value="1" label="kUnknownError"/>
   <int value="2" label="kClientError"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 403ede301..18ceb694 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -41653,7 +41653,8 @@
   <summary>The trigger type of input method switches by user.</summary>
 </histogram>
 
-<histogram name="InputMethod.MatchesSystemLanguage" enum="BooleanMatched">
+<histogram name="InputMethod.MatchesSystemLanguage" enum="BooleanMatched"
+    expires_after="2019-01-30">
   <owner>aurimas@chromium.org</owner>
   <summary>
     Whether the currently selected keyboard language matches the system
@@ -41880,7 +41881,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.AttemptsCount.Total" units="count">
+<histogram name="Installer.AttemptsCount.Total" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of update attempts until the update has been applied. This is
@@ -41893,7 +41895,8 @@
   <summary>Errors from update_engine process when running in dev mode.</summary>
 </histogram>
 
-<histogram name="Installer.DownloadOverheadPercentage" units="%">
+<histogram name="Installer.DownloadOverheadPercentage" units="%"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The overhead in downloading extra bytes due to errors/interruptions.
@@ -41903,7 +41906,7 @@
 </histogram>
 
 <histogram name="Installer.DownloadSourcesUsed"
-    enum="UpdateEngineDownloadSources">
+    enum="UpdateEngineDownloadSources" expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The combinations of protocol and source server that were used to complete a
@@ -41911,7 +41914,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.FullPayloadAttemptNumber" units="count">
+<histogram name="Installer.FullPayloadAttemptNumber" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of update attempts with a full update payload until the update
@@ -41920,7 +41924,7 @@
 </histogram>
 
 <histogram name="Installer.InstallDateProvisioningSource"
-    enum="UpdateEngineInstallDateProvisioningSource">
+    enum="UpdateEngineInstallDateProvisioningSource" expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The source used to provision the install-date-days value sent to Omaha with
@@ -41929,14 +41933,15 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.NormalErrorCodes" enum="UpdateEngineErrorCode">
+<histogram name="Installer.NormalErrorCodes" enum="UpdateEngineErrorCode"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Errors from update_engine process when running in normal mode.
   </summary>
 </histogram>
 
-<histogram name="Installer.OSAgeDays" units="days">
+<histogram name="Installer.OSAgeDays" units="days" expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The age of the OS, defined as the age of the /etc/lsb-release file. This is
@@ -41944,7 +41949,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.PayloadAttemptNumber" units="count">
+<histogram name="Installer.PayloadAttemptNumber" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of update attempts until the update has been applied. This is
@@ -41952,7 +41958,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.PayloadFormat" enum="UpdateEnginePayloadFormat">
+<histogram name="Installer.PayloadFormat" enum="UpdateEnginePayloadFormat"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The type of update payload used to update the device. The difference between
@@ -41964,7 +41971,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.RebootToNewPartitionAttempt" units="count">
+<histogram name="Installer.RebootToNewPartitionAttempt" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of consecutive times a device has failed to boot an update that
@@ -42000,14 +42008,16 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.SuccessfulMBsDownloadedFrom" units="MB">
+<histogram name="Installer.SuccessfulMBsDownloadedFrom" units="MB"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Number of MBs downloaded from during an update that completed successfully.
   </summary>
 </histogram>
 
-<histogram name="Installer.TimeToRebootMinutes" units="Minutes">
+<histogram name="Installer.TimeToRebootMinutes" units="Minutes"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Wall-clock duration between when an update has successfully completed (and
@@ -42017,7 +42027,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.TotalMBsDownloadedFrom" units="MB">
+<histogram name="Installer.TotalMBsDownloadedFrom" units="MB"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Total number of MBs downloaded since the last successful update. This also
@@ -42025,7 +42036,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdateDurationMinutes" units="Minutes">
+<histogram name="Installer.UpdateDurationMinutes" units="Minutes"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Absolute wall-clock time duration it took for the update to complete from
@@ -42034,7 +42046,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdateDurationUptimeMinutes" units="Minutes">
+<histogram name="Installer.UpdateDurationUptimeMinutes" units="Minutes"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Uptime duration it took for the update to complete from the time an update
@@ -42044,7 +42057,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdateNumReboots" units="count">
+<histogram name="Installer.UpdateNumReboots" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Number of times the device was rebooted by the user since an update began
@@ -42052,7 +42066,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdatesAbandonedCount" units="count">
+<histogram name="Installer.UpdatesAbandonedCount" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of update attempts that didn't complete because a newer update
@@ -42061,7 +42076,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdatesAbandonedEventCount" units="count">
+<histogram name="Installer.UpdatesAbandonedEventCount" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     The number of consecutive different abandoned update payloads since the last
@@ -42070,7 +42086,8 @@
   </summary>
 </histogram>
 
-<histogram name="Installer.UpdateURLSwitches" units="count">
+<histogram name="Installer.UpdateURLSwitches" units="count"
+    expires_after="2019-01-30">
   <owner>zeuthen@chromium.org</owner>
   <summary>
     Number of times the download URLs were switched due to failures.
@@ -48351,6 +48368,15 @@
   </summary>
 </histogram>
 
+<histogram name="Media.HardwareKeyPressed" enum="MediaHardwareKeyAction">
+  <owner>steimel@chromium.org</owner>
+  <owner>media-dev@chromium.org</owner>
+  <summary>
+    Records media key presses that are handled by the
+    HardwareKeyMediaController.
+  </summary>
+</histogram>
+
 <histogram name="Media.HasEverPlayed" enum="BooleanHasPlayed">
   <owner>dalecurtis@chromium.org</owner>
   <summary>
@@ -110504,7 +110530,7 @@
   <summary>Amount of time taken to serialize a call stack profile.</summary>
 </histogram>
 
-<histogram name="Stars.Goog_Related" units="%">
+<histogram name="Stars.Goog_Related" units="%" expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips with Google related urls (points to internal Google
@@ -110512,7 +110538,8 @@
   </summary>
 </histogram>
 
-<histogram name="Stars.Goog_Related_20_Percent" units="%">
+<histogram name="Stars.Goog_Related_20_Percent" units="%"
+    expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips with Google related urls within first 20 (points to
@@ -110520,7 +110547,7 @@
   </summary>
 </histogram>
 
-<histogram name="Stars.Images_Percent" units="%">
+<histogram name="Stars.Images_Percent" units="%" expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips with images. Logs every time user goes to
@@ -110528,7 +110555,8 @@
   </summary>
 </histogram>
 
-<histogram name="Stars.Images_Percent_First20" units="%">
+<histogram name="Stars.Images_Percent_First20" units="%"
+    expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips with images within first 20. Logs every time user goes
@@ -110536,12 +110564,13 @@
   </summary>
 </histogram>
 
-<histogram name="Stars.LaunchLocation" enum="StarsLaunchLocation">
+<histogram name="Stars.LaunchLocation" enum="StarsLaunchLocation"
+    expires_after="2019-01-30">
   <owner>ianwen@chromium.org</owner>
   <summary>Logs a UI location from which a bookmark is launched.</summary>
 </histogram>
 
-<histogram name="Stars.No_Images_Snippets" units="%">
+<histogram name="Stars.No_Images_Snippets" units="%" expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips without images or snippets. Logs every time user goes to
@@ -110549,7 +110578,8 @@
   </summary>
 </histogram>
 
-<histogram name="Stars.No_Img_No_Snippet_20_Percent" units="%">
+<histogram name="Stars.No_Img_No_Snippet_20_Percent" units="%"
+    expires_after="2019-01-30">
   <owner>yefim@chromium.org</owner>
   <summary>
     Percentage of clips without images or snippets within first 20. Logs every
@@ -119330,7 +119360,8 @@
   <summary>Whether a scroll is executed on main thread.</summary>
 </histogram>
 
-<histogram name="UI.CompositorResizeLock.Duration" units="ms">
+<histogram name="UI.CompositorResizeLock.Duration" units="ms"
+    expires_after="2019-01-30">
   <owner>kylechar@chromium.org</owner>
   <summary>
     The amount of time the CompositorResizeLock was held in milliseconds. This
@@ -119339,7 +119370,8 @@
   </summary>
 </histogram>
 
-<histogram name="UI.CompositorResizeLock.TimedOut" units="Boolean">
+<histogram name="UI.CompositorResizeLock.TimedOut" units="Boolean"
+    expires_after="2019-01-30">
   <owner>kylechar@chromium.org</owner>
   <summary>
     Tracks whether the CompositorResizeLock is being released due to timing out
@@ -123517,7 +123549,8 @@
   </summary>
 </histogram>
 
-<histogram name="Vibration.Context" enum="NavigatorVibrationType">
+<histogram name="Vibration.Context" enum="NavigatorVibrationType"
+    expires_after="2019-01-30">
   <owner>binlu@google.com</owner>
   <summary>
     Records instances of navigator.vibrate. Includes whether or not it comes
diff --git a/tools/perf/contrib/vr_benchmarks/BUILD.gn b/tools/perf/contrib/vr_benchmarks/BUILD.gn
index a04709f3..ea31c49 100644
--- a/tools/perf/contrib/vr_benchmarks/BUILD.gn
+++ b/tools/perf/contrib/vr_benchmarks/BUILD.gn
@@ -24,11 +24,6 @@
     "//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
     "//chrome/test/data/xr/webvr_info/samples/",
     "//chrome/test/data/xr/webxr_samples/",
-
-    # Necessary for running on bots
-    "//testing/scripts/common.py",
-    "//testing/xvfb.py",
-    "//testing/scripts/run_telemetry_benchmark_as_googletest.py",
   ]
   data_deps = [
     "//chrome/android:vr_nfc_simulator_apk",
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 192a1397..a90813fd 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -18,7 +18,7 @@
  <item id="affiliation_lookup" hash_code="111904019" type="0" content_hash_code="81061452" os_list="linux,windows" file_path="components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc"/>
  <item id="android_device_manager_socket" hash_code="37249086" type="0" content_hash_code="6436865" os_list="linux,windows" file_path="chrome/browser/devtools/device/android_device_manager.cc"/>
  <item id="android_web_socket" hash_code="39356976" type="0" content_hash_code="12310113" os_list="linux,windows" file_path="chrome/browser/devtools/device/android_web_socket.cc"/>
- <item id="appcache_update_job" hash_code="25790702" type="0" content_hash_code="27424887" os_list="linux,windows" file_path="content/browser/appcache/appcache_update_request_base.cc"/>
+ <item id="appcache_update_job" hash_code="25790702" type="0" content_hash_code="27424887" os_list="linux,windows" file_path="content/browser/appcache/appcache_update_url_loader_request.cc"/>
  <item id="autofill_query" hash_code="88863520" type="0" content_hash_code="15563339" os_list="linux,windows" file_path="components/autofill/core/browser/autofill_download_manager.cc"/>
  <item id="autofill_upload" hash_code="104798869" type="0" content_hash_code="110634763" os_list="linux,windows" file_path="components/autofill/core/browser/autofill_download_manager.cc"/>
  <item id="backdrop_collection_images_download" hash_code="34767164" type="0" content_hash_code="103835921" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
diff --git a/ui/aura/mus/DEPS b/ui/aura/mus/DEPS
index 5971c42..307694a0 100644
--- a/ui/aura/mus/DEPS
+++ b/ui/aura/mus/DEPS
@@ -13,6 +13,7 @@
   "+gpu/ipc/client/gpu_channel_host.h",
   "+mojo/public/cpp/system/buffer.h",
   "+mojo/public/cpp/system/platform_handle.h",
+  "+services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h",
   "+services/ws/common/accelerator_util.h",
   "+services/ws/common/task_runner_test_base.h",
   "+services/ws/public",
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 8b2c607..54578c1 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -23,6 +23,7 @@
 #include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
 #include "mojo/public/cpp/bindings/map.h"
 #include "services/service_manager/public/cpp/connector.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
 #include "services/ws/common/util.h"
 #include "services/ws/public/cpp/gpu/gpu.h"
 #include "services/ws/public/cpp/property_type_converters.h"
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index 3c0e2b8..429be3b 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -24,6 +24,7 @@
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/ws/public/mojom/screen_provider_observer.mojom.h"
+#include "services/ws/public/mojom/window_manager.mojom.h"
 #include "services/ws/public/mojom/window_tree.mojom.h"
 #include "ui/aura/aura_export.h"
 #include "ui/aura/client/transient_window_client_observer.h"
diff --git a/ui/aura/mus/window_tree_client_delegate.h b/ui/aura/mus/window_tree_client_delegate.h
index aa73c1b..1c2767e 100644
--- a/ui/aura/mus/window_tree_client_delegate.h
+++ b/ui/aura/mus/window_tree_client_delegate.h
@@ -14,6 +14,7 @@
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "services/ws/public/mojom/screen_provider_observer.mojom.h"
 #include "services/ws/public/mojom/window_tree.mojom.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
 #include "ui/aura/aura_export.h"
 
 namespace aura {
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 965ef3e..8e04ec3 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -319,13 +319,6 @@
       "dragdrop/file_info.cc",
       "dragdrop/file_info.h",
       "emoji/emoji_panel_helper.h",
-      "idle/idle.cc",
-      "idle/idle.h",
-      "idle/idle_android.cc",
-      "idle/idle_chromeos.cc",
-      "idle/idle_linux.cc",
-      "idle/idle_mac.mm",
-      "idle/idle_win.cc",
       "pointer/pointer_device.h",
       "pointer/pointer_device_util.cc",
       "pointer/touch_editing_controller.cc",
@@ -374,7 +367,6 @@
 
   if (is_fuchsia) {
     sources += [
-      "idle/idle_fuchsia.cc",
       "l10n/l10n_util_posix.cc",
       "resource/resource_bundle_fuchsia.cc",
     ]
@@ -434,17 +426,6 @@
   if (use_x11) {
     public_deps += [ "//ui/base/x" ]
     configs += [ "//build/config/linux:x11" ]
-
-    if (!is_chromeos) {
-      sources += [
-        "idle/idle_query_x11.cc",
-        "idle/idle_query_x11.h",
-        "idle/screensaver_window_finder_x11.cc",
-        "idle/screensaver_window_finder_x11.h",
-      ]
-      configs += [ "//build/config/linux:xscrnsaver" ]
-      deps += [ "//ui/gfx/x" ]
-    }
   }
 
   if (use_x11 && use_aura) {
@@ -495,14 +476,6 @@
     ]
   }
 
-  if (is_chromeos) {
-    deps += [
-      "//chromeos",
-      "//chromeos/dbus",
-    ]
-    sources -= [ "idle/idle_linux.cc" ]
-  }
-
   if (is_chromeos || (use_aura && is_linux && !use_x11)) {
     sources += [
       "dragdrop/os_exchange_data_provider_aura.cc",
@@ -600,8 +573,6 @@
     sources -= [
       "cursor/cursor_android.cc",
       "default_theme_provider.cc",
-      "idle/idle.cc",
-      "idle/idle.h",
       "l10n/l10n_font_util.cc",
       "models/button_menu_item_model.cc",
       "pointer/touch_editing_controller.cc",
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
new file mode 100644
index 0000000..bfa6e5d
--- /dev/null
+++ b/ui/base/idle/BUILD.gn
@@ -0,0 +1,69 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/jumbo.gni")
+import("//build/config/ui.gni")
+import("//testing/test.gni")
+if (is_android) {
+  import("//build/config/android/rules.gni")
+} else if (is_mac) {
+  import("//build/config/mac/rules.gni")
+}
+jumbo_component("idle") {
+  output_name = "ui_base_idle"
+  defines = [ "IS_UI_BASE_IDLE_IMPL" ]
+  sources = [
+    "idle.cc",
+    "idle.h",
+    "idle_android.cc",
+    "idle_chromeos.cc",
+    "idle_linux.cc",
+    "idle_mac.mm",
+    "idle_win.cc",
+  ]
+
+  deps = [
+    "//ui/base",
+  ]
+  public_deps = []
+  libs = []
+
+  if (is_fuchsia) {
+    sources += [ "idle_fuchsia.cc" ]
+  }
+
+  if (use_x11) {
+    public_deps += [ "//ui/base/x" ]
+    deps += [ "//ui/gfx/x" ]
+    configs += [
+      "//build/config/linux:x11",
+      "//build/config/linux:xscrnsaver",
+    ]
+    sources += [
+      "idle_query_x11.cc",
+      "idle_query_x11.h",
+      "screensaver_window_finder_x11.cc",
+      "screensaver_window_finder_x11.h",
+    ]
+  }
+
+  if (is_chromeos) {
+    deps += [
+      "//chromeos",
+      "//chromeos/dbus",
+    ]
+    sources -= [ "idle_linux.cc" ]
+  }
+
+  if (is_android) {
+    sources -= [ "idle.cc" ]
+  }
+
+  if (is_mac) {
+    libs += [
+      "Carbon.framework",
+      "Foundation.framework",
+    ]
+  }
+}
diff --git a/ui/base/idle/idle.h b/ui/base/idle/idle.h
index 269ca44..83420c7 100644
--- a/ui/base/idle/idle.h
+++ b/ui/base/idle/idle.h
@@ -5,8 +5,8 @@
 #ifndef UI_BASE_IDLE_IDLE_H_
 #define UI_BASE_IDLE_IDLE_H_
 
+#include "base/component_export.h"
 #include "build/build_config.h"
-#include "ui/base/ui_base_export.h"
 
 namespace ui {
 
@@ -20,18 +20,18 @@
 
 // For MacOSX, InitIdleMonitor needs to be called first to setup the monitor.
 #if defined(OS_MACOSX)
-UI_BASE_EXPORT void InitIdleMonitor();
+COMPONENT_EXPORT(UI_BASE_IDLE) void InitIdleMonitor();
 #endif
 
 // Calculate the Idle state. |idle_threshold| is the amount of time (in seconds)
 // before the user is considered idle.
-UI_BASE_EXPORT IdleState CalculateIdleState(int idle_threshold);
+COMPONENT_EXPORT(UI_BASE_IDLE) IdleState CalculateIdleState(int idle_threshold);
 
 // Calculate Idle time in seconds.
-UI_BASE_EXPORT int CalculateIdleTime();
+COMPONENT_EXPORT(UI_BASE_IDLE) int CalculateIdleTime();
 
 // Checks synchronously if Idle state is IDLE_STATE_LOCKED.
-UI_BASE_EXPORT bool CheckIdleStateIsLocked();
+COMPONENT_EXPORT(UI_BASE_IDLE) bool CheckIdleStateIsLocked();
 
 }  // namespace ui
 
diff --git a/ui/events/devices/input_device_observer_win.h b/ui/events/devices/input_device_observer_win.h
index 049cf4e..ec96725 100644
--- a/ui/events/devices/input_device_observer_win.h
+++ b/ui/events/devices/input_device_observer_win.h
@@ -16,7 +16,7 @@
 
 namespace ui {
 
-class EVENTS_DEVICES_EXPORT InputDeviceObserverWin {
+class EVENTS_DEVICES_EXPORT InputDeviceObserverWin final {
  public:
   static InputDeviceObserverWin* GetInstance();
   ~InputDeviceObserverWin();
@@ -24,12 +24,11 @@
   void AddObserver(InputDeviceEventObserver* observer);
   void RemoveObserver(InputDeviceEventObserver* observer);
 
- protected:
-  InputDeviceObserverWin();
-
  private:
   friend struct base::DefaultSingletonTraits<InputDeviceObserverWin>;
 
+  InputDeviceObserverWin();
+
   void OnRegistryKeyChanged();
   bool IsSlateModeEnabled();
   void NotifyObserversKeyboardDeviceConfigurationChanged();
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 744445c7..d6b88c5 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -491,10 +491,8 @@
     return true;
 
   // Command line overrides extension and touch enabled flags.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableVirtualKeyboard)) {
+  if (IsEnableFlagSet(KeyboardEnableFlag::kCommandLineEnabled))
     return true;
-  }
 
   if (IsEnableFlagSet(KeyboardEnableFlag::kExtensionDisabled))
     return false;
diff --git a/ui/keyboard/public/keyboard_controller_types.mojom b/ui/keyboard/public/keyboard_controller_types.mojom
index 95f2f0a..451c226 100644
--- a/ui/keyboard/public/keyboard_controller_types.mojom
+++ b/ui/keyboard/public/keyboard_controller_types.mojom
@@ -35,6 +35,10 @@
 
   // Temporarily enable the keyboard; cleared once the keyboard is shown.
   kTemporarilyEnabled,
+
+  // Enabled via the "--enable-virtual-keyboard" command line switch.
+  // Used for development and debugging.
+  kCommandLineEnabled,
 };
 
 // Container types used to set and identify contaner behavior. Used in UMA
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index 3d8d3f3..a03c115 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -295,8 +295,6 @@
     return arrow_key_traversal_enabled_;
   }
 
-  // TODO(weidongg): converts compatible usages of
-  // |arrow_key_traversal_enabled_| to this (https://crbug.com/899431).
   // Similar to above, but only for the widget that owns this FocusManager.
   void set_arrow_key_traversal_enabled_for_widget(bool enabled) {
     arrow_key_traversal_enabled_for_widget_ = enabled;
diff --git a/ui/views/mus/screen_mus_unittest.cc b/ui/views/mus/screen_mus_unittest.cc
index 196698f..ef67cc0b 100644
--- a/ui/views/mus/screen_mus_unittest.cc
+++ b/ui/views/mus/screen_mus_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/test/scoped_task_environment.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
 #include "ui/display/display_switches.h"
 #include "ui/display/screen.h"
 #include "ui/views/test/views_test_base.h"
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
index b49b3e7d..6afb8024 100644
--- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
+++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
@@ -152,6 +152,7 @@
             }
 
             this.devices_ = responseParams.eligibleHostDevices;
+            this.fire('forward-button-focus-requested');
           })
           .catch((error) => {
             console.warn('Mojo service failure: ' + error);
@@ -170,6 +171,7 @@
 
       this.$$('password-page').clearPasswordTextInput();
       this.visiblePageName = PageName.START;
+      this.fire('forward-button-focus-requested');
     },
 
     /** @private */
@@ -211,7 +213,7 @@
       // An authentication token must be set if a password is required.
       assert(this.delegate.isPasswordRequiredToSetHost() == !!this.authToken_);
 
-      let deviceId = /** @type {string} */ (this.selectedDeviceId_);
+      const deviceId = /** @type {string} */ (this.selectedDeviceId_);
       this.delegate.setHostDevice(deviceId, this.authToken_)
           .then((responseParams) => {
             if (!responseParams.success) {
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
index 551405b..4e6acc1 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
@@ -62,6 +62,11 @@
         margin-inline-end: 0;
         margin-inline-start: 0;
       }
+
+      .icon-picture-delete {
+        margin-inline-end: 0;
+        margin-inline-start: 0;
+      }
     </style>
     <div id="preview" hidden="[[!showImagePreview_(cameraActive_, imageSrc)]]">
       <img id="image" alt="[[previewAltText]]" src="[[getImgSrc_(imageUrl)]]"
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.html b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.html
index 0390425..56013c2 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.html
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.html
@@ -141,7 +141,8 @@
     <div id="icon"
         class$="[[getIconClass_(networkState, deviceState, isListItem)]]">
     </div>
-    <iron-icon id="technology" hidden="[[!showTechnology_(networkState)]]"
+    <iron-icon id="technology"
+        hidden="[[!showTechnology_(networkState, showTechnologyBadge)]]"
         icon="[[getTechnology_(networkState)]]">
     </iron-icon>
     <iron-icon id="secure" hidden="[[!showSecure_(networkState)]]"
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
index a6359a1..5e47f525 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
@@ -38,6 +38,14 @@
       type: Boolean,
       value: false,
     },
+
+    /**
+     * If true, cellular technology badge is displayed in the network icon.
+     */
+    showTechnologyBadge: {
+      type: Boolean,
+      value: true,
+    },
   },
 
   /**
@@ -115,7 +123,7 @@
    * @private
    */
   showTechnology_: function() {
-    return this.getTechnology_() != '';
+    return this.getTechnology_() != '' && this.showTechnologyBadge;
   },
 
   /**
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.html b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.html
index 7a16782..b198f316 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.html
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.html
@@ -41,6 +41,7 @@
           scroll-target="container" selected-item="{{selectedItem}}">
         <template>
           <cr-network-list-item item="[[item]]"
+              show-technology-badge="[[showTechnologyBadge]]"
               show-buttons="[[showButtons]]" tabindex$="[[tabIndex]]">
           </cr-network-list-item>
         </template>
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.js
index e474e81..a8f4b93 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list.js
@@ -42,6 +42,9 @@
       reflectToAttribute: true,
     },
 
+    /** Whether to show technology badges on mobile network icons. */
+    showTechnologyBadge: {type: Boolean, value: true},
+
     /**
      * Reflects the iron-list selecteditem property.
      * @type {!CrNetworkList.CrNetworkListItemType}
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
index 7580886..264d5d0 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
@@ -59,7 +59,9 @@
     <div id="divOuter"
         class="layout horizontal center flex" actionable>
       <template is="dom-if" if="[[networkState]]">
-        <cr-network-icon is-list-item network-state="[[networkState]]">
+        <cr-network-icon
+            show-technology-badge="[[showTechnologyBadge]]"
+            is-list-item network-state="[[networkState]]">
         </cr-network-icon>
       </template>
       <template is="dom-if" if="[[item.polymerIcon]]">
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
index 5b4f0b4..a8e2fb44 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
@@ -56,6 +56,9 @@
      * @type {!CrOnc.ConnectionState|undefined}
      */
     connectionState_: String,
+
+    /** Whether to show technology badge on mobile network icon. */
+    showTechnologyBadge: {type: Boolean, value: true},
   },
 
   behaviors: [CrPolicyNetworkBehavior],
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.html b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.html
index a190e85..0157fda 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.html
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.html
@@ -18,6 +18,7 @@
         on-selected="onNetworkListItemSelected_"
         networks="[[networkStateList_]]" custom-items="[[customItems]]"
         show-buttons="[[showButtons]]"
+        show-technology-badge="[[showTechnologyBadge]]"
         no-bottom-scroll-border="[[noBottomScrollBorder]]">
     </cr-network-list>
   </template>
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
index d7ee6e1..82fbcc3 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
@@ -44,6 +44,9 @@
       reflectToAttribute: true,
     },
 
+    /** Whether to show technology badges on mobile network icons. */
+    showTechnologyBadge: {type: Boolean, value: true},
+
     /**
      * List of all network state data for all visible networks.
      * @private {!Array<!CrOnc.NetworkStateProperties>}