diff --git a/BUILD.gn b/BUILD.gn
index 375462b..4e5a0226 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -658,10 +658,10 @@
       "//chrome/installer/util:strings",
       "//chrome/tools/convert_dict",
       "//components/constrained_window:unit_tests",
-      "//components/filesystem:filesystem_service_unittests",
-      "//components/leveldb:leveldb_service_unittests",
       "//components/metrics:serialization",
       "//components/rappor:unit_tests",
+      "//components/services/filesystem:filesystem_service_unittests",
+      "//components/services/leveldb:leveldb_service_unittests",
       "//components/sessions:unit_tests",
       "//media/blink:media_blink_unittests",
       "//media/cast:udp_proxy",
diff --git a/DEPS b/DEPS
index 30e40ade..c85fd5c 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,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': 'c25e2693ab00cfe7691b68b7d47f2159640d783a',
+  'skia_revision': 'fd6ed022db18d7e1b48a544f4e0f0dbf6ef206b6',
   # 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': '21cb7e30e4995fe0602963da903bdc84de78a82a',
+  'v8_revision': '5018e7b89920ff8b9deff450fa25fec1e4e05f4c',
   # 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.
@@ -91,7 +91,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': '64e5ed2abd8a4cc77d3647e4b245db57a8c42ae5',
+  'angle_revision': 'f0b30dd8bd2bd68d6aad0e161f5fc3816d5a5077',
   # 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.
@@ -103,7 +103,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '0c6b98182403868334b4dfe4852caa4d0e2ba272',
+  'pdfium_revision': '7a1aa5f659110e99950b00b6b326b41436872635',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -341,7 +341,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f4c2703a6dedd8aed2d00fd7b57a6adf579271d9',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '68de9f34db445a1371a421cc0fa6b9480bd9a853',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -657,7 +657,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '207a75d8f3fae1dc47aa20dda0636e88f6b8d2b3', # commit position 21742
+    Var('webrtc_git') + '/src.git' + '@' + '3133857266925d4bc66e0bddef8c9a1fefc3a060', # commit position 21742
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/OWNERS b/OWNERS
index db7e31d..1988231 100644
--- a/OWNERS
+++ b/OWNERS
@@ -19,6 +19,7 @@
 per-file codereview.settings=agable@chromium.org
 per-file DEPS=*
 per-file PRESUBMIT*.py=dcheng@chromium.org
+per-file PRESUBMIT*.py=dpranke@chromium.org
 per-file PRESUBMIT*.py=jochen@chromium.org
 per-file README.md=*
 per-file WATCHLISTS=*
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 6e30749..482790ad 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -556,8 +556,8 @@
 # Bypass the AUTHORS check for these accounts.
 _KNOWN_ROBOTS = set(
   '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
-  for s in ('afdo', 'angle', 'catapult', 'depot-tools', 'nacl', 'pdfium',
-            'skia', 'src-internal', 'webrtc'))
+  for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools', 'nacl',
+            'pdfium', 'skia', 'src-internal', 'webrtc'))
 
 
 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
diff --git a/WATCHLISTS b/WATCHLISTS
index 2f95b4be..3cc62e2 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -62,6 +62,10 @@
                   '|media/midi/*_android.*' \
                   '|media/video/capture/android'
     },
+    'android_search_widget': {
+      'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/locale/' \
+                  '|chrome/android/java/src/org/chromium/chrome/browser/searchwidget/'
+    },
     'android_studio': {
       'filepath': 'build/android/gradle/' \
                   '|docs/android_studio.md' \
@@ -1649,6 +1653,8 @@
     'android_loading': ['gabadie+watch@chromium.org',
                         'lizeb+watch-android-loading@chromium.org'],
     'android_media': ['mlamouri+watch-media@chromium.org'],
+    'android_search_widget': ['tedchoc+watch@chromium.org',
+                              'yusufo+watch@chromium.org'],
     'android_studio': ['wnwen+watch@chromium.org',
                        'nyquist+watch@chromium.org'],
     'android_tab': ['dtrainor+watch@chromium.org'],
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index b924567a..2189f9c6 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -205,6 +205,8 @@
     "frame/frame_border_hit_test.cc",
     "frame/frame_border_hit_test.h",
     "frame/frame_header.h",
+    "frame/frame_header_origin_text.cc",
+    "frame/frame_header_origin_text.h",
     "frame/frame_header_util.cc",
     "frame/frame_header_util.h",
     "frame/header_view.cc",
diff --git a/ash/frame/frame_header_origin_text.cc b/ash/frame/frame_header_origin_text.cc
new file mode 100644
index 0000000..4dc15a3
--- /dev/null
+++ b/ash/frame/frame_header_origin_text.cc
@@ -0,0 +1,114 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/frame/frame_header_origin_text.h"
+
+#include "base/i18n/rtl.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace ash {
+
+namespace {
+
+constexpr base::TimeDelta kOriginSlideInDuration =
+    base::TimeDelta::FromMilliseconds(800);
+constexpr base::TimeDelta kOriginPauseDuration =
+    base::TimeDelta::FromMilliseconds(2500);
+constexpr base::TimeDelta kOriginSlideOutDuration =
+    base::TimeDelta::FromMilliseconds(500);
+
+constexpr gfx::Tween::Type kTweenType = gfx::Tween::FAST_OUT_SLOW_IN_2;
+
+}  // namespace
+
+FrameHeaderOriginText::FrameHeaderOriginText(const base::string16& origin,
+                                             SkColor active_color,
+                                             SkColor inactive_color,
+                                             SkColor active_background_color,
+                                             SkColor inactive_background_color)
+    : active_color_(active_color),
+      inactive_color_(inactive_color),
+      active_background_color_(active_background_color),
+      inactive_background_color_(inactive_background_color) {
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+
+  label_ = std::make_unique<views::Label>(origin).release();
+  label_->SetElideBehavior(gfx::ELIDE_HEAD);
+  label_->SetSubpixelRenderingEnabled(false);
+  label_->SetEnabledColor(active_color);
+  label_->SetBackgroundColor(active_background_color);
+  label_->SetPaintToLayer();
+  label_->layer()->SetFillsBoundsOpaquely(false);
+  label_->layer()->SetOpacity(0);
+  AddChildView(label_);
+
+  // Clip child views to this view.
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+  layer()->SetMasksToBounds(true);
+}
+
+FrameHeaderOriginText::~FrameHeaderOriginText() = default;
+
+void FrameHeaderOriginText::SetPaintAsActive(bool active) {
+  label_->SetEnabledColor(active ? active_color_ : inactive_color_);
+  label_->SetBackgroundColor(active ? active_background_color_
+                                    : inactive_background_color_);
+}
+
+void FrameHeaderOriginText::StartSlideAnimation() {
+  ui::Layer* label_layer = label_->layer();
+
+  // Current state will become the first animation keyframe.
+  DCHECK_EQ(label_layer->opacity(), 0);
+  gfx::Transform out_of_frame;
+  out_of_frame.Translate(
+      label_->bounds().width() * (base::i18n::IsRTL() ? -1 : 1), 0);
+  label_layer->SetTransform(out_of_frame);
+
+  auto opacity_sequence = std::make_unique<ui::LayerAnimationSequence>();
+  auto transform_sequence = std::make_unique<ui::LayerAnimationSequence>();
+
+  // Slide in.
+  auto opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement(
+      1, kOriginSlideInDuration);
+  opacity_keyframe->set_tween_type(kTweenType);
+  opacity_sequence->AddElement(std::move(opacity_keyframe));
+
+  auto transform_keyframe = ui::LayerAnimationElement::CreateTransformElement(
+      gfx::Transform(), kOriginSlideInDuration);
+  transform_keyframe->set_tween_type(kTweenType);
+  transform_sequence->AddElement(std::move(transform_keyframe));
+
+  // Pause.
+  opacity_sequence->AddElement(
+      ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration));
+  transform_sequence->AddElement(
+      ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration));
+
+  // Slide out.
+  opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement(
+      0, kOriginSlideOutDuration);
+  opacity_keyframe->set_tween_type(kTweenType);
+  opacity_sequence->AddElement(std::move(opacity_keyframe));
+
+  transform_keyframe = ui::LayerAnimationElement::CreateTransformElement(
+      out_of_frame, kOriginSlideOutDuration);
+  transform_keyframe->set_tween_type(kTweenType);
+  transform_sequence->AddElement(std::move(transform_keyframe));
+
+  label_layer->GetAnimator()->StartTogether(
+      {opacity_sequence.release(), transform_sequence.release()});
+}
+
+base::TimeDelta FrameHeaderOriginText::AnimationDuration() {
+  return kOriginSlideInDuration + kOriginPauseDuration +
+         kOriginSlideOutDuration;
+}
+
+}  // namespace ash
diff --git a/ash/frame/frame_header_origin_text.h b/ash/frame/frame_header_origin_text.h
new file mode 100644
index 0000000..9b3b9cd
--- /dev/null
+++ b/ash/frame/frame_header_origin_text.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
+#define ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
+
+#include "ash/ash_export.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/views/view.h"
+
+namespace views {
+class Label;
+}
+
+namespace ash {
+
+// A URL's origin text with a slide in/out animation.
+class ASH_EXPORT FrameHeaderOriginText : public views::View {
+ public:
+  FrameHeaderOriginText(const base::string16& origin,
+                        SkColor active_color,
+                        SkColor inactive_color,
+                        SkColor active_background_color,
+                        SkColor inactive_background_color);
+  ~FrameHeaderOriginText() override;
+
+  // Sets whether to paint the text with the active/inactive color.
+  void SetPaintAsActive(bool active);
+
+  // Slides the text in and out.
+  void StartSlideAnimation();
+
+  // How long the slide in+out animation takes.
+  static base::TimeDelta AnimationDuration();
+
+ private:
+  // Owned by the views hierarchy.
+  views::Label* label_ = nullptr;
+
+  const SkColor active_color_;
+  const SkColor inactive_color_;
+  const SkColor active_background_color_;
+  const SkColor inactive_background_color_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameHeaderOriginText);
+};
+
+}  // namespace ash
+
+#endif  // ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index fe2ef454..8a67242e 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -66,20 +66,19 @@
 #include "ui/gfx/transform_util.h"
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/core/window_util.h"
-#include "ui/wm/public/activation_delegate.h"
 
 namespace ash {
 namespace {
 
 // The label covers selector item windows with a padding in order to prevent
 // them from receiving user input events while in overview.
-static const int kWindowMargin = 5;
+constexpr int kWindowMargin = 5;
 
 // The overview mode header overlaps original window header. This value is used
 // to set top inset property on the windows.
-static const int kHeaderHeight = 32;
+constexpr int kHeaderHeight = 32;
 
-const char kActiveWindowChangedFromOverview[] =
+constexpr const char kActiveWindowChangedFromOverview[] =
     "WindowSelector_ActiveWindowChanged";
 
 // A simple window delegate that returns the specified hit-test code when
@@ -96,11 +95,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate);
 };
 
-class NonActivatableActivationDelegate : public ::wm::ActivationDelegate {
- public:
-  bool ShouldActivate() const override { return false; }
-};
-
 float GetItemScale(const gfx::Rect& source,
                    const gfx::Rect& target,
                    int top_view_inset,
@@ -121,9 +115,9 @@
   void SetUp() override {
     AshTestBase::SetUp();
 
-    shelf_view_test_.reset(
-        new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting()));
-    shelf_view_test_->SetAnimationDuration(1);
+    shelf_view_test_api_ = std::make_unique<ShelfViewTestAPI>(
+        GetPrimaryShelf()->GetShelfViewForTesting());
+    shelf_view_test_api_->SetAnimationDuration(1);
     ScopedTransformOverviewWindow::SetImmediateCloseForTests();
   }
 
@@ -147,12 +141,6 @@
     window->SetProperty(aura::client::kTopViewInset, kHeaderHeight);
     return window;
   }
-  aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) {
-    aura::Window* window = CreateWindow(bounds);
-    ::wm::SetActivationDelegate(window, &non_activatable_activation_delegate_);
-    EXPECT_FALSE(wm::CanActivateWindow(window));
-    return window;
-  }
 
   // Creates a Widget containing a Window with the given |bounds|. This should
   // be used when the test requires a Widget. For example any test that will
@@ -180,7 +168,7 @@
     window->SetProperty(kShelfIDKey, new std::string(shelf_id));
     window->SetProperty<int>(kShelfItemTypeKey, TYPE_APP_PANEL);
     window->SetProperty(aura::client::kTopViewInset, kHeaderHeight);
-    shelf_view_test()->RunMessageLoopUntilAnimationsDone();
+    shelf_view_test_api_->RunMessageLoopUntilAnimationsDone();
     return window;
   }
 
@@ -246,18 +234,10 @@
     event_generator.ClickLeftButton();
   }
 
-  void SendKey(ui::KeyboardCode key) {
+  void SendKey(ui::KeyboardCode key, int flags = ui::EF_NONE) {
     ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
-    event_generator.PressKey(key, 0);
-    event_generator.ReleaseKey(key, 0);
-  }
-
-  void SendCtrlKey(ui::KeyboardCode key) {
-    ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
-    event_generator.PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN);
-    event_generator.PressKey(key, ui::EF_CONTROL_DOWN);
-    event_generator.ReleaseKey(key, ui::EF_CONTROL_DOWN);
-    event_generator.ReleaseKey(ui::VKEY_CONTROL, ui::EF_NONE);
+    event_generator.PressKey(key, flags);
+    event_generator.ReleaseKey(key, flags);
   }
 
   bool IsSelecting() { return window_selector_controller()->IsSelecting(); }
@@ -352,8 +332,6 @@
     window_selector()->ContentsChanged(nullptr, base::UTF8ToUTF16(pattern));
   }
 
-  ShelfViewTestAPI* shelf_view_test() { return shelf_view_test_.get(); }
-
   views::Widget* text_filter_widget() {
     return window_selector()->text_filter_widget_.get();
   }
@@ -365,11 +343,6 @@
     return gfx::Rect();
   }
 
-  OverviewWindowDragController* window_drag_controller() {
-    DCHECK(window_selector());
-    return window_selector()->window_drag_controller_.get();
-  }
-
   views::Widget* item_widget(WindowSelectorItem* item) {
     return item->item_widget_.get();
   }
@@ -388,8 +361,7 @@
 
  private:
   aura::test::TestWindowDelegate delegate_;
-  NonActivatableActivationDelegate non_activatable_activation_delegate_;
-  std::unique_ptr<ShelfViewTestAPI> shelf_view_test_;
+  std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_;
 
   DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
 };
@@ -397,9 +369,9 @@
 // Tests that the text field in the overview menu is repositioned and resized
 // after a screen rotation.
 TEST_F(WindowSelectorTest, OverviewScreenRotation) {
-  gfx::Rect bounds(0, 0, 400, 300);
-  std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
-  std::unique_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
+  const gfx::Rect bounds(400, 300);
+  std::unique_ptr<aura::Window> window(CreateWindow(bounds));
+  std::unique_ptr<aura::Window> panel(CreatePanelWindow(bounds));
 
   // In overview mode the windows should no longer overlap and the text filter
   // widget should be focused.
@@ -415,8 +387,7 @@
   // w: std::min(kTextFilterWidth, total_bounds.width()).
   // h: kTextFilterHeight.
   gfx::Rect expected_bounds(60, -42, 280, 40);
-  EXPECT_EQ(expected_bounds.ToString(),
-            text_filter->GetClientAreaBoundsInScreen().ToString());
+  EXPECT_EQ(expected_bounds, text_filter->GetClientAreaBoundsInScreen());
 
   // Rotates the display, which triggers the WindowSelector's
   // RepositionTextFilterOnDisplayMetricsChange method.
@@ -424,18 +395,17 @@
 
   // Uses the same formulas as above using width = 300, height = 400.
   expected_bounds = gfx::Rect(10, -42, 280, 40);
-  EXPECT_EQ(expected_bounds.ToString(),
-            text_filter->GetClientAreaBoundsInScreen().ToString());
+  EXPECT_EQ(expected_bounds, text_filter->GetClientAreaBoundsInScreen());
 }
 
 // Tests that an a11y alert is sent on entering overview mode.
 TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   TestAccessibilityControllerClient client;
   AccessibilityController* controller =
       Shell::Get()->accessibility_controller();
   controller->SetClient(client.CreateInterfacePtrAndBind());
-  std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
+  std::unique_ptr<aura::Window> window(CreateWindow(bounds));
   EXPECT_NE(mojom::AccessibilityAlert::WINDOW_OVERVIEW_MODE_ENTERED,
             client.last_a11y_alert());
   ToggleOverview();
@@ -462,7 +432,7 @@
 
 // Tests entering overview mode with two windows and selecting one by clicking.
 TEST_F(WindowSelectorTest, Basic) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   aura::Window* root_window = Shell::GetPrimaryRootWindow();
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
@@ -504,7 +474,7 @@
 
 // Tests activating minimized window.
 TEST_F(WindowSelectorTest, ActivateMinimized) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window(CreateWindow(bounds));
 
   wm::WindowState* window_state = wm::GetWindowState(window.get());
@@ -540,12 +510,12 @@
 // Tests that entering overview mode with an App-list active properly focuses
 // and activates the overview text filter window.
 TEST_F(WindowSelectorTest, TextFilterActive) {
-  gfx::Rect bounds(0, 0, 400, 400);
-  std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
-  wm::ActivateWindow(window1.get());
+  const gfx::Rect bounds(400, 400);
+  std::unique_ptr<aura::Window> window(CreateWindow(bounds));
+  wm::ActivateWindow(window.get());
 
-  EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
-  EXPECT_EQ(window1.get(), wm::GetFocusedWindow());
+  EXPECT_TRUE(wm::IsActiveWindow(window.get()));
+  EXPECT_EQ(window.get(), wm::GetFocusedWindow());
 
   // Pass an enum to satisfy the function, it is arbitrary and will not affect
   // histograms.
@@ -556,7 +526,7 @@
   // previously active |window1|. Overview mode should properly transfer focus
   // and activation to the text filter widget.
   ToggleOverview();
-  EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
+  EXPECT_FALSE(wm::IsActiveWindow(window.get()));
   EXPECT_TRUE(wm::IsActiveWindow(wm::GetFocusedWindow()));
   EXPECT_EQ(text_filter_widget()->GetNativeWindow(), wm::GetFocusedWindow());
 }
@@ -564,7 +534,7 @@
 // Tests that the ordering of windows is stable across different overview
 // sessions even when the windows have the same bounds.
 TEST_F(WindowSelectorTest, WindowsOrder) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindowWithId(bounds, 1));
   std::unique_ptr<aura::Window> window2(CreateWindowWithId(bounds, 2));
   std::unique_ptr<aura::Window> window3(CreateWindowWithId(bounds, 3));
@@ -594,7 +564,7 @@
 
 // Tests selecting a window by tapping on it.
 TEST_F(WindowSelectorTest, BasicGesture) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   wm::ActivateWindow(window1.get());
@@ -613,7 +583,7 @@
 // in overview mode which is different from the previously-active window.
 TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionRecorded) {
   base::UserActionTester user_action_tester;
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -650,7 +620,7 @@
 // exiting overview without selecting a window does not record the action.
 TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionNotRecorded) {
   base::UserActionTester user_action_tester;
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -694,7 +664,7 @@
 TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionWindowClose) {
   base::UserActionTester user_action_tester;
   std::unique_ptr<views::Widget> widget =
-      CreateWindowWidget(gfx::Rect(0, 0, 400, 400));
+      CreateWindowWidget(gfx::Rect(400, 400));
 
   ToggleOverview();
 
@@ -737,7 +707,7 @@
 // Tests that we do not crash and a window is selected when appropriate when
 // we click on a window during touch.
 TEST_F(WindowSelectorTest, ClickOnWindowDuringTouch) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   wm::ActivateWindow(window2.get());
@@ -849,7 +819,7 @@
 // Tests minimizing/unminimizing in overview mode.
 TEST_F(WindowSelectorTest, MinimizeUnminimize) {
   std::unique_ptr<views::Widget> widget =
-      CreateWindowWidget(gfx::Rect(0, 0, 400, 400));
+      CreateWindowWidget(gfx::Rect(400, 400));
   aura::Window* window = widget->GetNativeWindow();
 
   ToggleOverview();
@@ -907,7 +877,7 @@
 
 // Tests entering overview mode with two windows and selecting one.
 TEST_F(WindowSelectorTest, FullscreenWindow) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
@@ -941,7 +911,7 @@
 }
 
 TEST_F(WindowSelectorTest, SkipOverviewWindow) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -964,7 +934,7 @@
 // mode correctly applies the transformations to the window and correctly
 // updates the window bounds on exiting overview mode: http://crbug.com/401664.
 TEST_F(WindowSelectorTest, FullscreenWindowTabletMode) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
@@ -974,34 +944,29 @@
   const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
   wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event);
   gfx::Rect fullscreen_window_bounds(window1->bounds());
-  EXPECT_NE(normal_window_bounds.ToString(),
-            fullscreen_window_bounds.ToString());
-  EXPECT_EQ(fullscreen_window_bounds.ToString(),
-            window2->GetTargetBounds().ToString());
+  EXPECT_NE(normal_window_bounds, fullscreen_window_bounds);
+  EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
   ToggleOverview();
   // Window 2 would normally resize to normal window bounds on showing the shelf
   // for overview but this is deferred until overview is exited.
-  EXPECT_EQ(fullscreen_window_bounds.ToString(),
-            window2->GetTargetBounds().ToString());
+  EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
   ToggleOverview();
 
   // Since the fullscreen window is still active, window2 will still have the
   // larger bounds.
-  EXPECT_EQ(fullscreen_window_bounds.ToString(),
-            window2->GetTargetBounds().ToString());
+  EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
 
   // Enter overview again and select window 2. Selecting window 2 should show
   // the shelf bringing window2 back to the normal bounds.
   ToggleOverview();
   ClickWindow(window2.get());
-  EXPECT_EQ(normal_window_bounds.ToString(),
-            window2->GetTargetBounds().ToString());
+  EXPECT_EQ(normal_window_bounds, window2->GetTargetBounds());
 }
 
 // Tests that beginning window selection hides the app list.
 TEST_F(WindowSelectorTest, SelectingHidesAppList) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -1018,7 +983,7 @@
 // stay invisible (A minimized window is cloned during overview),
 // and ignored_by_shelf state is restored upon exit.
 TEST_F(WindowSelectorTest, MinimizedWindowState) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   wm::WindowState* window_state = wm::GetWindowState(window1.get());
   window_state->Minimize();
@@ -1040,7 +1005,7 @@
 // Tests that it is safe to destroy a window while the overview header animation
 // is still active. See http://crbug.com/646350.
 TEST_F(WindowSelectorTest, SafeToDestroyWindowDuringAnimation) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   {
     // Quickly enter and exit overview mode to activate header animations.
     std::unique_ptr<aura::Window> window(CreateWindow(bounds));
@@ -1051,7 +1016,7 @@
 
     gfx::SlideAnimation* animation =
         GetBackgroundViewAnimationForWindow(0, window.get());
-    ASSERT_NE(nullptr, animation);
+    ASSERT_TRUE(animation);
     ToggleOverview();
     EXPECT_FALSE(IsSelecting());
     if (animation)
@@ -1086,7 +1051,7 @@
 
 // Tests that a newly created window aborts overview.
 TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   ToggleOverview();
@@ -1099,7 +1064,7 @@
 
 // Tests that a window activation exits overview mode.
 TEST_F(WindowSelectorTest, ActivationCancelsOveriew) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   window2->Focus();
@@ -1118,7 +1083,7 @@
 // Tests that exiting overview mode without selecting a window restores focus
 // to the previously focused window.
 TEST_F(WindowSelectorTest, CancelRestoresFocus) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window(CreateWindow(bounds));
   wm::ActivateWindow(window.get());
   EXPECT_EQ(window.get(), wm::GetFocusedWindow());
@@ -1134,7 +1099,7 @@
 
 // Tests that overview mode is exited if the last remaining window is destroyed.
 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   ToggleOverview();
@@ -1147,7 +1112,7 @@
 // Tests that entering overview mode restores a window to its original
 // target location.
 TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window(CreateWindow(bounds));
   gfx::Rect initial_bounds = GetTransformedBounds(window.get());
   ToggleOverview();
@@ -1169,7 +1134,7 @@
 // Tests that windows with modal child windows are transformed with the modal
 // child even though not activatable themselves.
 TEST_F(WindowSelectorTest, ModalChild) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> child1(CreateWindow(bounds));
   child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
@@ -1264,7 +1229,7 @@
 
 // Tests shutting down during overview.
 TEST_F(WindowSelectorTest, Shutdown) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   // These windows will be deleted when the test exits and the Shell instance
   // is shut down.
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
@@ -1347,7 +1312,7 @@
                                            window.get());
   event_generator.PressLeftButton();
   event_generator.MoveMouseBy(10, 10);
-  EXPECT_EQ(window->bounds().ToString(), "10,10 100x100");
+  EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->bounds());
 
   ToggleOverview();
   ASSERT_TRUE(IsSelecting());
@@ -1360,35 +1325,32 @@
   event_generator.MoveMouseBy(10, 10);
   event_generator.ReleaseLeftButton();
   RunAllPendingInMessageLoop();
-  EXPECT_EQ(window->bounds().ToString(), "30,30 100x100");
-
-  return;
+  EXPECT_EQ(gfx::Rect(30, 30, 100, 100), window->bounds());
 }
 
 // Test that a label is created under the window on entering overview mode.
 TEST_F(WindowSelectorTest, CreateLabelUnderWindow) {
   std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 300, 500)));
-  base::string16 window_title = base::UTF8ToUTF16("My window");
+  const base::string16 window_title = base::UTF8ToUTF16("My window");
   window->SetTitle(window_title);
   ToggleOverview();
   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back().get();
   views::Label* label = GetLabelView(window_item);
-  // Has the label view been created?
   ASSERT_TRUE(label);
 
   // Verify the label matches the window title.
-  EXPECT_EQ(label->text(), window_title);
+  EXPECT_EQ(window_title, label->text());
 
   // Update the window title and check that the label is updated, too.
-  base::string16 updated_title = base::UTF8ToUTF16("Updated title");
+  const base::string16 updated_title = base::UTF8ToUTF16("Updated title");
   window->SetTitle(updated_title);
-  EXPECT_EQ(label->text(), updated_title);
+  EXPECT_EQ(updated_title, label->text());
 
   // Labels are located based on target_bounds, not the actual window item
   // bounds.
   gfx::Rect label_bounds = label->GetWidget()->GetWindowBoundsInScreen();
   label_bounds.Inset(kWindowMargin, kWindowMargin);
-  EXPECT_EQ(window_item->target_bounds(), label_bounds);
+  EXPECT_EQ(label_bounds, window_item->target_bounds());
 }
 
 // Tests that overview updates the window positions if the display orientation
@@ -1446,7 +1408,7 @@
 
   SendKey(ui::VKEY_RIGHT);
   EXPECT_EQ(window1, GetSelectedWindow());
-  SendCtrlKey(ui::VKEY_W);
+  SendKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
   EXPECT_TRUE(widget->IsClosed());
 }
 
@@ -2196,7 +2158,7 @@
 
 // Tests window list animation states are correctly updated.
 TEST_F(WindowSelectorTest, SetWindowListAnimationStates) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2229,7 +2191,7 @@
 // Tests window list animation states are correctly updated with selected
 // window.
 TEST_F(WindowSelectorTest, SetWindowListAnimationStatesWithSelectedWindow) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2265,7 +2227,7 @@
 // Tests OverviewWindowAnimationObserver can handle deleted window.
 TEST_F(WindowSelectorTest,
        OverviewWindowAnimationObserverCanHandleDeletedWindow) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2305,7 +2267,7 @@
 
 // Tests can handle OverviewWindowAnimationObserver was deleted.
 TEST_F(WindowSelectorTest, HandleOverviewWindowAnimationObserverWasDeleted) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2342,7 +2304,7 @@
 // Tests can handle |gained_active| window is not in the |window_grid| when
 // OnWindowActivated.
 TEST_F(WindowSelectorTest, HandleActiveWindowNotInWindowGrid) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2381,7 +2343,7 @@
 // animations.
 // Fails consistently; see https://crbug.com/812497.
 TEST_F(WindowSelectorTest, DISABLED_HandleAlwaysOnTopWindow) {
-  gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -2606,7 +2568,6 @@
   ToggleOverview();
   WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get());
   WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get());
-
   // Start the drag on |item1|. Verify the dragged item, |item1| has both the
   // close button and titlebar hidden. All other items, |item2| should only have
   // the close button hidden.
@@ -2978,7 +2939,7 @@
 // snaps the window. If two windows are snapped to left and right side of the
 // screen, exit the overview mode.
 TEST_F(SplitViewWindowSelectorTest, DragOverviewWindowToSnap) {
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -3110,7 +3071,7 @@
 // overview mode when split view is enabled.
 TEST_F(SplitViewWindowSelectorTest, WindowGridSizeWhileDraggingWithSplitView) {
   // Add three windows and enter overview mode.
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -3210,7 +3171,7 @@
 // mode, snapping the window to one side of the screen will end the overview
 // mode since there is no more window left in the overview window grid.
 TEST_F(SplitViewWindowSelectorTest, EmptyWindowsListExitOverview) {
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
 
   ToggleOverview();
@@ -3295,7 +3256,7 @@
 
 // Verify that the split view overview overlay has the expected state.
 TEST_F(SplitViewWindowSelectorTest, SplitViewOverviewOverlayState) {
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -3457,6 +3418,8 @@
 
 // Test the overview window drag functionalities when screen rotates.
 TEST_F(SplitViewWindowSelectorTest, SplitViewRotationTest) {
+  using svc = SplitViewController;
+
   UpdateDisplay("807x407");
   int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
   display::DisplayManager* display_manager = Shell::Get()->display_manager();
@@ -3471,7 +3434,7 @@
   EXPECT_EQ(test_api.GetCurrentOrientation(),
             blink::kWebScreenOrientationLockLandscapePrimary);
 
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
@@ -3481,8 +3444,7 @@
   WindowSelectorItem* selector_item1 =
       GetWindowItemForWindow(grid_index, window1.get());
   DragWindowTo(selector_item1, gfx::Point(0, 0));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::LEFT_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::LEFT_SNAPPED);
   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
 
   // Test that dragging |window2| to the right of the screen snaps it to right.
@@ -3492,8 +3454,7 @@
       split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get());
   gfx::Point end_location2(work_area_rect.width(), work_area_rect.height());
   DragWindowTo(selector_item2, end_location2);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::BOTH_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED);
   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
 
   // Test that |left_window_| was snapped to left after rotated 0 degree.
@@ -3513,8 +3474,7 @@
   // Test that dragging |window1| to the top of the screen snaps it to left.
   selector_item1 = GetWindowItemForWindow(grid_index, window1.get());
   DragWindowTo(selector_item1, gfx::Point(0, 0));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::LEFT_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::LEFT_SNAPPED);
   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
 
   // Test that dragging |window2| to the bottom of the screen snaps it to right.
@@ -3523,8 +3483,7 @@
       split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get());
   end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height());
   DragWindowTo(selector_item2, end_location2, SelectorItemLocation::ORIGIN);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::BOTH_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED);
   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
 
   // Test that |left_window_| was snapped to top after rotated 270 degree.
@@ -3544,8 +3503,7 @@
   // Test that dragging |window1| to the left of the screen snaps it to right.
   selector_item1 = GetWindowItemForWindow(grid_index, window1.get());
   DragWindowTo(selector_item1, gfx::Point(0, 0));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::RIGHT_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::RIGHT_SNAPPED);
   EXPECT_EQ(split_view_controller()->right_window(), window1.get());
 
   // Test that dragging |window2| to the right of the screen snaps it to left.
@@ -3554,8 +3512,7 @@
       split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get());
   end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height());
   DragWindowTo(selector_item2, end_location2, SelectorItemLocation::ORIGIN);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::BOTH_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED);
   EXPECT_EQ(split_view_controller()->left_window(), window2.get());
 
   // Test that |right_window_| was snapped to left after rotated 180 degree.
@@ -3575,8 +3532,7 @@
   // Test that dragging |window1| to the top of the screen snaps it to right.
   selector_item1 = GetWindowItemForWindow(grid_index, window1.get());
   DragWindowTo(selector_item1, gfx::Point(0, 0));
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::RIGHT_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::RIGHT_SNAPPED);
   EXPECT_EQ(split_view_controller()->right_window(), window1.get());
 
   // Test that dragging |window2| to the bottom of the screen snaps it to left.
@@ -3585,8 +3541,7 @@
       split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get());
   end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height());
   DragWindowTo(selector_item2, end_location2);
-  EXPECT_EQ(split_view_controller()->state(),
-            SplitViewController::BOTH_SNAPPED);
+  EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED);
   EXPECT_EQ(split_view_controller()->left_window(), window2.get());
 
   // Test that |right_window_| was snapped to top after rotated 90 degree.
@@ -3603,7 +3558,7 @@
 TEST_F(SplitViewWindowSelectorTest, SplitViewOverviewBothActiveTest) {
   UpdateDisplay("907x407");
 
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -3753,7 +3708,7 @@
 TEST_F(SplitViewWindowSelectorTest, DragDividerToExitTest) {
   UpdateDisplay("907x407");
 
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -3828,7 +3783,7 @@
 }
 
 TEST_F(SplitViewWindowSelectorTest, SnappedWindowBoundsTest) {
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   const int kMinimumBoundSize = 100;
   const gfx::Size size(kMinimumBoundSize, kMinimumBoundSize);
 
@@ -3900,7 +3855,7 @@
 // still active.
 TEST_F(SplitViewWindowSelectorTest,
        DividerDraggedToEdgeReturnsWindowToOverviewList) {
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
@@ -3947,7 +3902,7 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kAshEnableNewOverviewUi);
 
-  const gfx::Rect bounds(0, 0, 400, 400);
+  const gfx::Rect bounds(400, 400);
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
 
   ToggleOverview();
diff --git a/base/sys_info.cc b/base/sys_info.cc
index 645605a..379d7f26 100644
--- a/base/sys_info.cc
+++ b/base/sys_info.cc
@@ -44,6 +44,15 @@
   return AmountOfAvailablePhysicalMemoryImpl();
 }
 
+bool SysInfo::IsLowEndDevice() {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableLowEndDeviceMode)) {
+    return true;
+  }
+
+  return IsLowEndDeviceImpl();
+}
+
 #if !defined(OS_ANDROID)
 
 bool DetectLowEndDevice() {
@@ -62,7 +71,7 @@
   g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER;
 
 // static
-bool SysInfo::IsLowEndDevice() {
+bool SysInfo::IsLowEndDeviceImpl() {
   return g_lazy_low_end_device.Get().value();
 }
 #endif
diff --git a/base/sys_info.h b/base/sys_info.h
index d435d58..6e58715 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -172,6 +172,7 @@
 
   static int64_t AmountOfPhysicalMemoryImpl();
   static int64_t AmountOfAvailablePhysicalMemoryImpl();
+  static bool IsLowEndDeviceImpl();
 
 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX)
   static int64_t AmountOfAvailablePhysicalMemory(
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
index 1d1710c7..7704796 100644
--- a/base/sys_info_android.cc
+++ b/base/sys_info_android.cc
@@ -222,7 +222,7 @@
         android::SysUtils::IsLowEndDeviceFromJni> >::Leaky
     g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER;
 
-bool SysInfo::IsLowEndDevice() {
+bool SysInfo::IsLowEndDeviceImpl() {
   // This code might be used in some environments
   // which might not have a Java environment.
   // Note that we need to call the Java version here.
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 88b57dd..520b354 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -19,7 +19,7 @@
 #include "cc/test/test_skcanvas.h"
 #include "cc/test/transfer_cache_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
 #include "third_party/skia/include/effects/SkDashPathEffect.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
@@ -1134,9 +1134,8 @@
 
       SkScalar intervals[] = {1.f, 1.f};
       flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
-      flags.setMaskFilter(
-          SkBlurMaskFilter::Make(SkBlurStyle::kOuter_SkBlurStyle, 4.3f,
-                                 test_rects[0], kHigh_SkBlurQuality));
+      flags.setMaskFilter(SkMaskFilter::MakeBlur(
+          SkBlurStyle::kOuter_SkBlurStyle, 4.3f, test_rects[0]));
       flags.setColorFilter(SkColorMatrixFilter::MakeLightingFilter(
           SK_ColorYELLOW, SK_ColorGREEN));
 
diff --git a/cc/paint/paint_op_perftest.cc b/cc/paint/paint_op_perftest.cc
index 93d7ef0..ee9f92f 100644
--- a/cc/paint/paint_op_perftest.cc
+++ b/cc/paint/paint_op_perftest.cc
@@ -11,7 +11,7 @@
 #include "cc/paint/paint_op_buffer_serializer.h"
 #include "cc/test/transfer_cache_test_helper.h"
 #include "testing/perf/perf_test.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
 #include "third_party/skia/include/effects/SkDashPathEffect.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
@@ -123,9 +123,8 @@
   PaintFlags flags;
   SkScalar intervals[] = {1.f, 1.f};
   flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
-  flags.setMaskFilter(SkBlurMaskFilter::Make(SkBlurStyle::kOuter_SkBlurStyle,
-                                             4.3f, SkRect::MakeXYWH(1, 1, 1, 1),
-                                             kHigh_SkBlurQuality));
+  flags.setMaskFilter(SkMaskFilter::MakeBlur(
+      SkBlurStyle::kOuter_SkBlurStyle, 4.3f, SkRect::MakeXYWH(1, 1, 1, 1)));
   flags.setColorFilter(
       SkColorMatrixFilter::MakeLightingFilter(SK_ColorYELLOW, SK_ColorGREEN));
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 08c032a..a29c4db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -231,7 +231,13 @@
                                             .setIcon(Icon.createWithBitmap(icon))
                                             .setIntent(shortcutIntent)
                                             .build();
-        sShortcutManager.requestPinShortcut(shortcutInfo, null);
+        try {
+            sShortcutManager.requestPinShortcut(shortcutInfo, null);
+        } catch (IllegalStateException e) {
+            Log.d(TAG,
+                    "Could not create pinned shortcut: device is locked, or "
+                            + "activity is backgrounded.");
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
index 6db1811..1b3f887 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -265,6 +265,17 @@
         mUidHasCalledWarmup.put(uid, true);
     }
 
+    /**
+     * @return all the sessions originating from a given {@code uid}.
+     */
+    public synchronized List<CustomTabsSessionToken> uidToSessions(int uid) {
+        List<CustomTabsSessionToken> sessions = new ArrayList<>();
+        for (Map.Entry<CustomTabsSessionToken, SessionParams> entry : mSessionParams.entrySet()) {
+            if (entry.getValue().uid == uid) sessions.add(entry.getKey());
+        }
+        return sessions;
+    }
+
     /** Updates the client behavior stats and returns whether speculation is allowed.
      *
      * The first call to the "low priority" mode is not throttled. Subsequent ones are.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 5dd7d11..eaada0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -17,6 +17,7 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.os.SystemClock;
+import android.support.annotation.Nullable;
 import android.support.customtabs.CustomTabsCallback;
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.CustomTabsService;
@@ -94,6 +95,8 @@
     static final String BOTTOM_BAR_SCROLL_STATE_CALLBACK = "onBottomBarScrollStateChanged";
     @VisibleForTesting
     static final String OPEN_IN_BROWSER_CALLBACK = "onOpenInBrowser";
+    @VisibleForTesting
+    static final String ON_WARMUP_COMPLETED = "onWarmupCompleted";
 
     // For CustomTabs.SpeculationStatusOnStart, see tools/metrics/enums.xml. Append only.
     private static final int SPECULATION_STATUS_ON_START_ALLOWED = 0;
@@ -211,7 +214,6 @@
     private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean();
     private ExternalPrerenderHandler mExternalPrerenderHandler;
     private boolean mForcePrerenderForTesting;
-    private volatile Runnable mWarmupFinishedCallback;
 
     // Conversion between native TimeTicks and SystemClock.uptimeMillis().
     private long mNativeTickOffsetUs;
@@ -379,7 +381,8 @@
     private boolean warmupInternal(final boolean mayCreateSpareWebContents) {
         // Here and in mayLaunchUrl(), don't do expensive work for background applications.
         if (!isCallerForegroundOrSelf()) return false;
-        mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid());
+        int uid = Binder.getCallingUid();
+        mClientManager.recordUidHasCalledWarmup(uid);
         final boolean initialized = !mWarmupHasBeenCalled.compareAndSet(false, true);
 
         // The call is non-blocking and this must execute on the UI thread, post chained tasks.
@@ -396,80 +399,61 @@
 
         // (1)
         if (!initialized) {
-            tasks.add(new Runnable() {
-                @Override
-                public void run() {
-                    try (TraceEvent e =
-                                    TraceEvent.scoped("CustomTabsConnection.initializeBrowser()")) {
-                        initializeBrowser(mContext);
-                        ChromeBrowserInitializer.initNetworkChangeNotifier(mContext);
-                        mWarmupHasBeenFinished.set(true);
-                    }
+            tasks.add(() -> {
+                try (TraceEvent e = TraceEvent.scoped("CustomTabsConnection.initializeBrowser()")) {
+                    initializeBrowser(mContext);
+                    ChromeBrowserInitializer.initNetworkChangeNotifier(mContext);
+                    mWarmupHasBeenFinished.set(true);
                 }
             });
         }
 
         // (2)
         if (mayCreateSpareWebContents && mSpeculation == null) {
-            tasks.add(new Runnable() {
-                @Override
-                public void run() {
-                    // Temporary fix for https://crbug.com/797832.
-                    // TODO(lizeb): Properly fix instead of papering over the bug, this code should
-                    // not be scheduled unless startup is done. See https://crbug.com/797832.
-                    if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
-                                    .isStartupSuccessfullyCompleted()) {
-                        return;
-                    }
-                    try (TraceEvent e = TraceEvent.scoped("CreateSpareWebContents")) {
-                        WarmupManager.getInstance().createSpareWebContents();
-                    }
+            tasks.add(() -> {
+                // Temporary fix for https://crbug.com/797832.
+                // TODO(lizeb): Properly fix instead of papering over the bug, this code should
+                // not be scheduled unless startup is done. See https://crbug.com/797832.
+                if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                                .isStartupSuccessfullyCompleted()) {
+                    return;
+                }
+                try (TraceEvent e = TraceEvent.scoped("CreateSpareWebContents")) {
+                    WarmupManager.getInstance().createSpareWebContents();
                 }
             });
         }
 
         // (3)
-        tasks.add(new Runnable() {
-            @Override
-            public void run() {
-                try (TraceEvent e = TraceEvent.scoped("InitializeViewHierarchy")) {
-                    WarmupManager.getInstance().initializeViewHierarchy(mContext,
-                            R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar);
-                }
+        tasks.add(() -> {
+            try (TraceEvent e = TraceEvent.scoped("InitializeViewHierarchy")) {
+                WarmupManager.getInstance().initializeViewHierarchy(mContext,
+                        R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar);
             }
         });
 
         if (!initialized) {
-            tasks.add(new Runnable() {
-                @Override
-                public void run() {
-                    try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) {
-                        // (4)
-                        Profile profile = Profile.getLastUsedProfile();
-                        new LoadingPredictor(profile).startInitialization();
+            tasks.add(() -> {
+                try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) {
+                    // (4)
+                    Profile profile = Profile.getLastUsedProfile();
+                    new LoadingPredictor(profile).startInitialization();
 
-                        // (5)
-                        // The throttling database uses shared preferences, that can cause a
-                        // StrictMode violation on the first access. Make sure that this access is
-                        // not in mayLauchUrl.
-                        RequestThrottler.loadInBackground(mContext);
-                    }
+                    // (5)
+                    // The throttling database uses shared preferences, that can cause a
+                    // StrictMode violation on the first access. Make sure that this access is
+                    // not in mayLauchUrl.
+                    RequestThrottler.loadInBackground(mContext);
                 }
             });
         }
-        if (mWarmupFinishedCallback != null) tasks.add(mWarmupFinishedCallback);
 
+        tasks.add(() -> notifyWarmupIsDone(uid));
         tasks.start(false);
         mWarmupTasks = tasks;
         return true;
     }
 
-    /** Sets a callback to be notified of the completion of all the warmup() tasks. */
-    @VisibleForTesting
-    void setWarmupCompletedCallbackForTesting(Runnable cb) {
-        mWarmupFinishedCallback = cb;
-    }
-
     /** @return the URL or null if it's invalid. */
     private boolean isValid(Uri uri) {
         if (uri == null) return false;
@@ -692,23 +676,19 @@
         if (!mClientManager.bindToPostMessageServiceForSession(session)) return false;
 
         final int uid = Binder.getCallingUid();
-        ThreadUtils.postOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                // If the API is not enabled, we don't set the post message origin, which will
-                // avoid PostMessageHandler initialization and disallow postMessage calls.
-                if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return;
+        ThreadUtils.postOnUiThread(() -> {
+            // If the API is not enabled, we don't set the post message origin, which will avoid
+            // PostMessageHandler initialization and disallow postMessage calls.
+            if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return;
 
-                // Attempt to verify origin synchronously. If successful directly initialize
-                // postMessage channel for session.
-                Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin);
-                if (verifiedOrigin == null) {
-                    mClientManager.verifyAndInitializeWithPostMessageOriginForSession(
-                            session, postMessageOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN);
-                } else {
-                    mClientManager.initializeWithPostMessageOriginForSession(
-                            session, verifiedOrigin);
-                }
+            // Attempt to verify origin synchronously. If successful directly initialize postMessage
+            // channel for session.
+            Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin);
+            if (verifiedOrigin == null) {
+                mClientManager.verifyAndInitializeWithPostMessageOriginForSession(
+                        session, postMessageOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN);
+            } else {
+                mClientManager.initializeWithPostMessageOriginForSession(session, verifiedOrigin);
             }
         });
         return true;
@@ -1118,6 +1098,14 @@
         return extras;
     }
 
+    private void notifyWarmupIsDone(int uid) {
+        ThreadUtils.assertOnUiThread();
+        // Notifies all the sessions, as warmup() is tied to a UID, not a session.
+        for (CustomTabsSessionToken session : mClientManager.uidToSessions(uid)) {
+            safeExtraCallback(session, ON_WARMUP_COMPLETED, null);
+        }
+    }
+
     /**
      * Notifies the application of a page load metric for a single metric.
      *
@@ -1183,8 +1171,8 @@
      * Wraps calling extraCallback in a try/catch so exceptions thrown by the host app don't crash
      * Chrome. See https://crbug.com/517023.
      */
-    private boolean safeExtraCallback(CustomTabsSessionToken session, String callbackName,
-            Bundle args) {
+    private boolean safeExtraCallback(
+            CustomTabsSessionToken session, String callbackName, @Nullable Bundle args) {
         CustomTabsCallback callback = mClientManager.getCallbackForSession(session);
         if (callback == null) return false;
 
@@ -1296,12 +1284,7 @@
      */
     @VisibleForTesting
     void cleanUpSession(final CustomTabsSessionToken session) {
-        ThreadUtils.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mClientManager.cleanupSession(session);
-            }
-        });
+        ThreadUtils.runOnUiThread(() -> mClientManager.cleanupSession(session));
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index 9e57f82..8fbc4052 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -485,4 +485,9 @@
     TextView getEmptyViewForTests() {
         return mEmptyView;
     }
+
+    @VisibleForTesting
+    public RecyclerView getRecyclerViewForTests() {
+        return mRecyclerView;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index ef6e344..6e4fdeb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -157,7 +157,7 @@
             mRoot.addChild(mSiteSection);
         }
 
-        if (FeatureUtilities.isChromeHomeEnabled()) {
+        if (FeatureUtilities.isChromeDuplexEnabled()) {
             if (mSigninPromo != null) mRoot.addChild(mSigninPromo);
             mRoot.addChildren(mAllDismissed);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
index a461b5f6..7f2eab5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
@@ -10,6 +10,7 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -17,6 +18,7 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener;
+import org.chromium.content.browser.test.NativeLibraryTestRule;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.Semaphore;
@@ -25,6 +27,9 @@
 /** Tests for OriginVerifier. */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class OriginVerifierTest {
+    @Rule
+    public NativeLibraryTestRule mNativeLibraryTestRule = new NativeLibraryTestRule();
+
     private static final long TIMEOUT_MS = 1000;
     private static final byte[] BYTE_ARRAY = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc,
             (byte) 0x10, (byte) 0x20, (byte) 0x30, (byte) 0x01, (byte) 0x02};
@@ -40,9 +45,9 @@
     private static final String SHA_256_FINGERPRINT = ChromeVersionInfo.isOfficialBuild()
             ? SHA_256_FINGERPRINT_OFFICIAL
             : SHA_256_FINGERPRINT_PUBLIC;
-    private static final Origin TEST_HTTPS_ORIGIN_1 = new Origin("https://www.example.com");
-    private static final Origin TEST_HTTPS_ORIGIN_2 = new Origin("https://www.android.com");
-    private static final Origin TEST_HTTP_ORIGIN = new Origin("http://www.android.com");
+
+    private Origin mHttpsOrigin;
+    private Origin mHttpOrigin;
 
     private class TestOriginVerificationListener implements OriginVerificationListener {
         @Override
@@ -63,6 +68,11 @@
 
     @Before
     public void setUp() throws Exception {
+        mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess();
+
+        mHttpsOrigin = new Origin("https://www.example.com");
+        mHttpOrigin = new Origin("http://www.android.com");
+
         mHandleAllUrlsVerifier = new OriginVerifier(new TestOriginVerificationListener(),
                 PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS);
         mUseAsOriginVerifier = new OriginVerifier(new TestOriginVerificationListener(),
@@ -86,7 +96,7 @@
         Assert.assertTrue(
                 mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         Assert.assertFalse(mLastVerified);
-        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(TEST_HTTP_ORIGIN));
+        ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(mHttpOrigin));
         Assert.assertTrue(
                 mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         Assert.assertFalse(mLastVerified);
@@ -98,26 +108,26 @@
         ThreadUtils.postOnUiThread(
                 ()
                         -> OriginVerifier.addVerifiedOriginForPackage(PACKAGE_NAME,
-                                TEST_HTTPS_ORIGIN_1, CustomTabsService.RELATION_USE_AS_ORIGIN));
-        ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(TEST_HTTPS_ORIGIN_1));
+                        mHttpsOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN));
+        ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(mHttpsOrigin));
         Assert.assertTrue(
                 mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         Assert.assertTrue(mLastVerified);
         Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
             @Override
             public Boolean call() throws Exception {
-                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
+                return OriginVerifier.isValidOrigin(PACKAGE_NAME, mHttpsOrigin,
                         CustomTabsService.RELATION_USE_AS_ORIGIN);
             }
         }));
         Assert.assertFalse(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
             @Override
             public Boolean call() throws Exception {
-                return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1,
+                return OriginVerifier.isValidOrigin(PACKAGE_NAME, mHttpsOrigin,
                         CustomTabsService.RELATION_HANDLE_ALL_URLS);
             }
         }));
         Assert.assertEquals(mLastPackageName, PACKAGE_NAME);
-        Assert.assertEquals(mLastOrigin, TEST_HTTPS_ORIGIN_1);
+        Assert.assertEquals(mLastOrigin, mHttpsOrigin);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 323d0cb..f4456c0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -35,10 +35,8 @@
 import android.os.SystemClock;
 import android.support.annotation.DrawableRes;
 import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsClient;
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsServiceConnection;
 import android.support.customtabs.CustomTabsSession;
 import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
@@ -709,10 +707,10 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testOpenInBrowser() throws InterruptedException, TimeoutException {
+    public void testOpenInBrowser() throws Exception {
         // Augment the CustomTabsSession to catch the callback.
         CallbackHelper callbackTriggered = new CallbackHelper();
-        CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
+        CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
             @Override
             public void extraCallback(String callbackName, Bundle args) {
                 if (callbackName.equals(CustomTabsConnection.OPEN_IN_BROWSER_CALLBACK)) {
@@ -1031,7 +1029,7 @@
     @Test
     @SmallTest
     @Feature({"UiCatalogue"})
-    public void testRemoteViews() throws InterruptedException {
+    public void testRemoteViews() throws Exception {
         Intent intent = createMinimalCustomTabIntent();
 
         Bitmap expectedIcon = createVectorDrawableBitmap(R.drawable.ic_credit_card_black, 77, 48);
@@ -1058,7 +1056,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testLaunchWithSession() throws InterruptedException, TimeoutException {
+    public void testLaunchWithSession() throws Exception {
         CustomTabsSessionToken session = warmUpAndLaunchUrlWithSession();
         Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session);
     }
@@ -1066,7 +1064,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testLoadNewUrlWithSession() throws InterruptedException, TimeoutException {
+    public void testLoadNewUrlWithSession() throws Exception {
         final Context context = InstrumentationRegistry.getTargetContext();
         final Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
         CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
@@ -1100,7 +1098,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testCreateNewTab() throws InterruptedException, TimeoutException {
+    public void testCreateNewTab() throws Exception {
         final String testUrl = mTestServer.getURL(
                 "/chrome/test/data/android/customtabs/test_window_open.html");
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
@@ -1130,7 +1128,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testReferrerAddedAutomatically() throws InterruptedException, TimeoutException {
+    public void testReferrerAddedAutomatically() throws Exception {
         final Context context = InstrumentationRegistry.getInstrumentation()
                                         .getTargetContext()
                                         .getApplicationContext();
@@ -1165,7 +1163,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testVerifiedReferrer() throws InterruptedException, TimeoutException {
+    public void testVerifiedReferrer() throws Exception {
         final Context context = InstrumentationRegistry.getInstrumentation()
                                         .getTargetContext()
                                         .getApplicationContext();
@@ -1207,10 +1205,10 @@
      */
     @Test
     @SmallTest
-    public void testCallbacksAreSent() throws InterruptedException {
+    public void testCallbacksAreSent() throws Exception {
         final Semaphore navigationStartSemaphore = new Semaphore(0);
         final Semaphore navigationFinishedSemaphore = new Semaphore(0);
-        CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
+        CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
             @Override
             public void onNavigationEvent(int navigationEvent, Bundle extras) {
                 Assert.assertNotEquals(CustomTabsCallback.NAVIGATION_FAILED, navigationEvent);
@@ -1241,7 +1239,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPageLoadMetricIsSent() throws InterruptedException {
+    public void testPageLoadMetricIsSent() throws Exception {
         final AtomicReference<Long> firstContentfulPaintMs = new AtomicReference<>(-1L);
         final AtomicReference<Long> activityStartTimeMs = new AtomicReference<>(-1L);
         final AtomicReference<Long> loadEventStartMs = new AtomicReference<>(-1L);
@@ -1280,7 +1278,7 @@
             }
         };
 
-        CustomTabsSession session = bindWithCallback(cb);
+        CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(cb);
         Intent intent = new CustomTabsIntent.Builder(session).build().intent;
         intent.setData(Uri.parse(mTestPage));
         intent.setComponent(new ComponentName(
@@ -1322,14 +1320,14 @@
      */
     @Test
     @SmallTest
-    public void testNavigationHistogramsRecorded() throws InterruptedException {
+    public void testNavigationHistogramsRecorded() throws Exception {
         String startHistogramPrefix = "CustomTabs.IntentToFirstNavigationStartTime";
         String commitHistogramPrefix = "CustomTabs.IntentToFirstCommitNavigationTime3";
         assertSuffixedHistogramTotalCount(0, startHistogramPrefix);
         assertSuffixedHistogramTotalCount(0, commitHistogramPrefix);
 
         final Semaphore semaphore = new Semaphore(0);
-        CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
+        CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
             @Override
             public void onNavigationEvent(int navigationEvent, Bundle extras) {
                 if (navigationEvent == CustomTabsCallback.NAVIGATION_FINISHED) semaphore.release();
@@ -1376,15 +1374,14 @@
      */
     @Test
     @SmallTest
-    public void testToolbarTitleOnlyStateWithDelayedTitle()
-            throws TimeoutException, InterruptedException {
+    public void testToolbarTitleOnlyStateWithDelayedTitle() throws Exception {
         final String url = mWebServer.setResponse("/test.html", DELAYED_TITLE_CHANGE, null);
         hideDomainAndEnsureTitleIsSet(
                 url, CustomTabsConnection.SpeculationParams.NO_SPECULATION, "nytimes.com");
     }
 
-    private void hideDomainAndEnsureTitleIsSet(final String url, int speculation,
-            final String expectedTitle) throws InterruptedException, TimeoutException {
+    private void hideDomainAndEnsureTitleIsSet(
+            final String url, int speculation, final String expectedTitle) throws Exception {
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
@@ -1428,7 +1425,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageBasic() throws InterruptedException, TimeoutException {
+    public void testPostMessageBasic() throws Exception {
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
@@ -1468,8 +1465,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageWebContentsDestroyed()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageWebContentsDestroyed() throws Exception {
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
@@ -1514,7 +1510,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageRequiresValidation() throws InterruptedException, TimeoutException {
+    public void testPostMessageRequiresValidation() throws Exception {
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
@@ -1539,7 +1535,7 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageReceivedInPage() throws InterruptedException, TimeoutException {
+    public void testPostMessageReceivedInPage() throws Exception {
         final String url =
                 mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
@@ -1574,22 +1570,23 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageReceivedFromPage() throws InterruptedException, TimeoutException {
+    public void testPostMessageReceivedFromPage() throws Exception {
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final CallbackHelper onPostMessageHelper = new CallbackHelper();
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
         CustomTabsTestUtils.warmUpAndWait();
-        final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
-            @Override
-            public void onMessageChannelReady(Bundle extras) {
-                messageChannelHelper.notifyCalled();
-            }
+        final CustomTabsSession session =
+                CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
+                    @Override
+                    public void onMessageChannelReady(Bundle extras) {
+                        messageChannelHelper.notifyCalled();
+                    }
 
-            @Override
-            public void onPostMessage(String message, Bundle extras) {
-                onPostMessageHelper.notifyCalled();
-            }
-        });
+                    @Override
+                    public void onPostMessage(String message, Bundle extras) {
+                        onPostMessageHelper.notifyCalled();
+                    }
+                });
         session.requestPostMessageChannel(null);
         Intent intent = new CustomTabsIntent.Builder(session).build().intent;
         intent.setData(Uri.parse(url));
@@ -1612,23 +1609,23 @@
     @Test
     @SmallTest
     @RetryOnFailure
-    public void testPostMessageReceivedFromPageWithLateRequest()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageReceivedFromPageWithLateRequest() throws Exception {
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final CallbackHelper onPostMessageHelper = new CallbackHelper();
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
         CustomTabsTestUtils.warmUpAndWait();
-        final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
-            @Override
-            public void onMessageChannelReady(Bundle extras) {
-                messageChannelHelper.notifyCalled();
-            }
+        final CustomTabsSession session =
+                CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
+                    @Override
+                    public void onMessageChannelReady(Bundle extras) {
+                        messageChannelHelper.notifyCalled();
+                    }
 
-            @Override
-            public void onPostMessage(String message, Bundle extras) {
-                onPostMessageHelper.notifyCalled();
-            }
-        });
+                    @Override
+                    public void onPostMessage(String message, Bundle extras) {
+                        onPostMessageHelper.notifyCalled();
+                    }
+                });
 
         Intent intent = new CustomTabsIntent.Builder(session).build().intent;
         intent.setData(Uri.parse(url));
@@ -1665,8 +1662,7 @@
     @SmallTest
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPostMessageThroughPrerenderWithRequestBeforeMayLaunchUrl()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughPrerenderWithRequestBeforeMayLaunchUrl() throws Exception {
         sendPostMessageDuringPrerenderTransition(BEFORE_MAY_LAUNCH_URL);
     }
 
@@ -1678,8 +1674,7 @@
     @SmallTest
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPostMessageThroughPrerenderWithRequestBeforeIntent()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughPrerenderWithRequestBeforeIntent() throws Exception {
         sendPostMessageDuringPrerenderTransition(BEFORE_INTENT);
     }
 
@@ -1691,13 +1686,11 @@
     @SmallTest
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPostMessageThroughPrerenderWithRequestAfterIntent()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughPrerenderWithRequestAfterIntent() throws Exception {
         sendPostMessageDuringPrerenderTransition(AFTER_INTENT);
     }
 
-    private void sendPostMessageDuringPrerenderTransition(int requestTime)
-            throws InterruptedException, TimeoutException {
+    private void sendPostMessageDuringPrerenderTransition(int requestTime) throws Exception {
         sendPostMessageDuringSpeculationTransition(
                 requestTime, CustomTabsConnection.SpeculationParams.PRERENDER);
     }
@@ -1711,8 +1704,7 @@
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB)
-    public void testPostMessageThroughHiddenTabWithRequestBeforeMayLaunchUrl()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughHiddenTabWithRequestBeforeMayLaunchUrl() throws Exception {
         sendPostMessageDuringHiddenTabTransition(BEFORE_MAY_LAUNCH_URL);
     }
 
@@ -1725,8 +1717,7 @@
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB)
-    public void testPostMessageThroughHiddenTabWithRequestBeforeIntent()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughHiddenTabWithRequestBeforeIntent() throws Exception {
         sendPostMessageDuringHiddenTabTransition(BEFORE_INTENT);
     }
 
@@ -1739,31 +1730,30 @@
     @RetryOnFailure
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB)
-    public void testPostMessageThroughHiddenTabWithRequestAfterIntent()
-            throws InterruptedException, TimeoutException {
+    public void testPostMessageThroughHiddenTabWithRequestAfterIntent() throws Exception {
         sendPostMessageDuringHiddenTabTransition(AFTER_INTENT);
     }
 
     @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB)
-    private void sendPostMessageDuringHiddenTabTransition(int requestTime)
-            throws InterruptedException, TimeoutException {
+    private void sendPostMessageDuringHiddenTabTransition(int requestTime) throws Exception {
         sendPostMessageDuringSpeculationTransition(
                 requestTime, CustomTabsConnection.SpeculationParams.HIDDEN_TAB);
     }
 
     private void sendPostMessageDuringSpeculationTransition(int requestTime, int speculationMode)
-            throws InterruptedException, TimeoutException {
+            throws Exception {
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final String url =
                 mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
 
-        final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
-            @Override
-            public void onMessageChannelReady(Bundle extras) {
-                messageChannelHelper.notifyCalled();
-            }
-        });
+        final CustomTabsSession session =
+                CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() {
+                    @Override
+                    public void onMessageChannelReady(Bundle extras) {
+                        messageChannelHelper.notifyCalled();
+                    }
+                });
 
         Intent intent = new CustomTabsIntent.Builder(session).build().intent;
         intent.setData(Uri.parse(url));
@@ -1914,7 +1904,7 @@
     @DisabledTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
     @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
-    public void testWarmupAndLaunchRegularChrome() throws InterruptedException, TimeoutException {
+    public void testWarmupAndLaunchRegularChrome() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         Intent intent = new Intent(
                 InstrumentationRegistry.getTargetContext(), ChromeLauncherActivity.class);
@@ -1942,8 +1932,7 @@
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
     @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
-    public void testWarmupAndLaunchRightToolbarLayout()
-            throws InterruptedException, TimeoutException {
+    public void testWarmupAndLaunchRightToolbarLayout() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         mCustomTabActivityTestRule.startActivityCompletely(createMinimalCustomTabIntent());
         Assert.assertNull("Should not have a tab switcher button.",
@@ -2683,7 +2672,7 @@
     }
 
     private void verifyHistoryAfterSpeculation(int speculationMode, boolean speculationWasAHit)
-            throws InterruptedException, TimeoutException {
+            throws Exception {
         String speculationUrl = mTestPage;
         String navigationUrl = speculationWasAHit ? mTestPage : mTestPage2;
         final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
@@ -2778,7 +2767,7 @@
     }
 
     private CustomTabsSessionToken warmUpAndLaunchUrlWithSession(Intent intentWithSession)
-            throws InterruptedException, TimeoutException {
+            throws Exception {
         CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token =
                 CustomTabsSessionToken.getSessionTokenFromIntent(intentWithSession);
@@ -2788,8 +2777,7 @@
         return token;
     }
 
-    private CustomTabsSessionToken warmUpAndLaunchUrlWithSession()
-            throws InterruptedException, TimeoutException {
+    private CustomTabsSessionToken warmUpAndLaunchUrlWithSession() throws Exception {
         return warmUpAndLaunchUrlWithSession(CustomTabsTestUtils.createMinimalCustomTabIntent(
                 InstrumentationRegistry.getTargetContext(), mTestPage));
     }
@@ -2819,29 +2807,6 @@
         }
     }
 
-    private CustomTabsSession bindWithCallback(final CustomTabsCallback callback) {
-        final AtomicReference<CustomTabsSession> sessionReference = new AtomicReference<>(null);
-        CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(),
-                InstrumentationRegistry.getTargetContext().getPackageName(),
-                new CustomTabsServiceConnection() {
-                    @Override
-                    public void onServiceDisconnected(ComponentName name) {}
-
-                    @Override
-                    public void onCustomTabsServiceConnected(
-                            ComponentName name, CustomTabsClient client) {
-                        sessionReference.set(client.newSession(callback));
-                    }
-                });
-        CriteriaHelper.pollInstrumentationThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return sessionReference.get() != null;
-            }
-        });
-        return sessionReference.get();
-    }
-
     /**
       * A helper class to monitor sending status of a {@link PendingIntent}.
       */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
index 95a3479..f542c595 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -6,13 +6,19 @@
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
 
+import android.content.ComponentName;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Process;
+import android.support.customtabs.CustomTabsCallback;
+import android.support.customtabs.CustomTabsClient;
 import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.CustomTabsServiceConnection;
+import android.support.customtabs.CustomTabsSession;
 import android.support.customtabs.CustomTabsSessionToken;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
 import org.junit.After;
@@ -26,6 +32,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
@@ -45,7 +52,6 @@
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
 /** Tests for CustomTabsConnection. */
@@ -106,7 +112,7 @@
      */
     @Test
     @SmallTest
-    public void testCanWarmup() throws InterruptedException, TimeoutException {
+    public void testCanWarmup() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         CustomTabsTestUtils.warmUpAndWait();
     }
@@ -114,7 +120,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testCreateSpareRenderer() throws InterruptedException, TimeoutException {
+    public void testCreateSpareRenderer() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         // On UI thread because:
         // 1. takeSpareWebContents needs to be called from the UI thread.
@@ -135,8 +141,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testCreateSpareRendererCanBeRecreated()
-            throws InterruptedException, TimeoutException {
+    public void testCreateSpareRendererCanBeRecreated() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
@@ -157,7 +162,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPrerenderDestroysSpareRenderer() throws InterruptedException, TimeoutException {
+    public void testPrerenderDestroysSpareRenderer() throws Exception {
         CustomTabsConnection.getInstance().setForcePrerender(true);
         final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -181,8 +186,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPrerenderAndDisconnectOnOtherThread()
-            throws InterruptedException, TimeoutException {
+    public void testPrerenderAndDisconnectOnOtherThread() throws Exception {
         final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         final Thread otherThread = new Thread(new Runnable() {
             @Override
@@ -203,8 +207,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering()
-            throws InterruptedException, TimeoutException {
+    public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createMockSessionTokenForTesting();
@@ -225,7 +228,7 @@
 
     @Test
     @SmallTest
-    public void testMayLaunchUrlNullOrEmptyUrl() throws InterruptedException, TimeoutException {
+    public void testMayLaunchUrlNullOrEmptyUrl() throws Exception {
         assertWarmupAndMayLaunchUrl(null, null, true);
         CustomTabsTestUtils.cleanupSessions(mCustomTabsConnection); // Resets throttling.
         assertWarmupAndMayLaunchUrl(null, "", true);
@@ -315,8 +318,7 @@
 
     @Test
     @SmallTest
-    public void testLowConfidenceMayLaunchUrlOnlyAcceptUris()
-            throws InterruptedException, TimeoutException {
+    public void testLowConfidenceMayLaunchUrlOnlyAcceptUris() throws Exception {
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createMockSessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
@@ -343,8 +345,7 @@
 
     @Test
     @SmallTest
-    public void testLowConfidenceMayLaunchUrlDoesntCrash()
-            throws InterruptedException, TimeoutException {
+    public void testLowConfidenceMayLaunchUrlDoesntCrash() throws Exception {
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createMockSessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
@@ -391,8 +392,7 @@
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
-    public void testPrefetchOnlyNoPrerenderHasSpareWebContents()
-            throws InterruptedException, TimeoutException {
+    public void testPrefetchOnlyNoPrerenderHasSpareWebContents() throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createMockSessionTokenForTesting();
@@ -414,7 +414,7 @@
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     @RetryOnFailure
-    public void testCanCancelPrerender() throws InterruptedException, TimeoutException {
+    public void testCanCancelPrerender() throws Exception {
         CustomTabsConnection.getInstance().setForcePrerender(true);
         final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -448,8 +448,8 @@
      * Calls warmup() and mayLaunchUrl(), checks for the expected result
      * (success or failure) and returns the result code.
      */
-    private CustomTabsSessionToken assertWarmupAndMayLaunchUrl(CustomTabsSessionToken token,
-            String url, boolean shouldSucceed) throws InterruptedException, TimeoutException {
+    private CustomTabsSessionToken assertWarmupAndMayLaunchUrl(
+            CustomTabsSessionToken token, String url, boolean shouldSucceed) throws Exception {
         CustomTabsTestUtils.warmUpAndWait();
         if (token == null) {
             token = CustomTabsSessionToken.createMockSessionTokenForTesting();
@@ -469,8 +469,7 @@
      */
     @Test
     @SmallTest
-    public void testNoMayLaunchUrlWithInvalidSessionId()
-            throws InterruptedException, TimeoutException {
+    public void testNoMayLaunchUrlWithInvalidSessionId() throws Exception {
         assertWarmupAndMayLaunchUrl(
                 CustomTabsSessionToken.createMockSessionTokenForTesting(), URL, false);
     }
@@ -482,8 +481,7 @@
      */
     @Test
     @SmallTest
-    public void testNoMayLaunchUrlWithInvalidScheme()
-            throws InterruptedException, TimeoutException {
+    public void testNoMayLaunchUrlWithInvalidScheme() throws Exception {
         assertWarmupAndMayLaunchUrl(null, INVALID_SCHEME_URL, false);
     }
 
@@ -494,7 +492,7 @@
      */
     @Test
     @SmallTest
-    public void testMayLaunchUrl() throws InterruptedException, TimeoutException {
+    public void testMayLaunchUrl() throws Exception {
         assertWarmupAndMayLaunchUrl(null, URL, true);
     }
 
@@ -505,7 +503,7 @@
      */
     @Test
     @SmallTest
-    public void testMultipleMayLaunchUrl() throws InterruptedException, TimeoutException {
+    public void testMultipleMayLaunchUrl() throws Exception {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         mCustomTabsConnection.resetThrottling(Process.myUid());
         assertWarmupAndMayLaunchUrl(token, URL, true);
@@ -518,7 +516,7 @@
      */
     @Test
     @SmallTest
-    public void testForgetsSession() throws InterruptedException, TimeoutException {
+    public void testForgetsSession() throws Exception {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         CustomTabsTestUtils.cleanupSessions(mCustomTabsConnection);
         assertWarmupAndMayLaunchUrl(token, URL, false);
@@ -561,7 +559,7 @@
      */
     @Test
     @SmallTest
-    public void testThrottleMayLaunchUrl() throws InterruptedException, TimeoutException {
+    public void testThrottleMayLaunchUrl() throws Exception {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         int successfulRequests = 0;
         // Send a burst of requests instead of checking for precise delays to avoid flakiness.
@@ -577,7 +575,7 @@
      */
     @Test
     @SmallTest
-    public void testThrottlingIsReset() throws InterruptedException, TimeoutException {
+    public void testThrottlingIsReset() throws Exception {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         // Depending on the timing, the delay should be 100 or 200ms here.
         assertWarmupAndMayLaunchUrl(token, URL, true);
@@ -606,7 +604,7 @@
      */
     @Test
     @SmallTest
-    public void testThrottlingAcrossSessions() throws InterruptedException, TimeoutException {
+    public void testThrottlingAcrossSessions() throws Exception {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
         mCustomTabsConnection.resetThrottling(Process.myUid());
         CustomTabsSessionToken token2 = assertWarmupAndMayLaunchUrl(null, URL, true);
@@ -748,4 +746,49 @@
             }
         });
     }
+
+    @Test
+    @SmallTest
+    public void testWarmupNotificationIsSent() throws Exception {
+        final AtomicReference<CustomTabsClient> clientReference = new AtomicReference<>(null);
+        final CallbackHelper waitForConnection = new CallbackHelper();
+        CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(),
+                InstrumentationRegistry.getTargetContext().getPackageName(),
+                new CustomTabsServiceConnection() {
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {}
+
+                    @Override
+                    public void onCustomTabsServiceConnected(
+                            ComponentName name, CustomTabsClient client) {
+                        clientReference.set(client);
+                        waitForConnection.notifyCalled();
+                    }
+                });
+        waitForConnection.waitForCallback(0);
+        CustomTabsClient client = clientReference.get();
+        final CallbackHelper warmupWaiter = new CallbackHelper();
+        CustomTabsSession session = newSessionWithWarmupWaiter(client, warmupWaiter);
+        CustomTabsSession session2 = newSessionWithWarmupWaiter(client, warmupWaiter);
+
+        // Both sessions should be notified.
+        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        warmupWaiter.waitForCallback(0, 2);
+
+        // Notifications should be sent even if warmup() has already been called.
+        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        warmupWaiter.waitForCallback(2, 2);
+    }
+
+    private static CustomTabsSession newSessionWithWarmupWaiter(
+            CustomTabsClient client, final CallbackHelper waiter) {
+        return client.newSession(new CustomTabsCallback() {
+            @Override
+            public void extraCallback(String callbackName, Bundle args) {
+                if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) {
+                    waiter.notifyCalled();
+                }
+            }
+        });
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
index a42c5b81..9269ae5e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -8,9 +8,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Process;
+import android.support.customtabs.CustomTabsCallback;
+import android.support.customtabs.CustomTabsClient;
 import android.support.customtabs.CustomTabsIntent;
+import android.support.customtabs.CustomTabsServiceConnection;
 import android.support.customtabs.CustomTabsSession;
+import android.support.test.InstrumentationRegistry;
 
 import org.junit.Assert;
 
@@ -19,6 +24,7 @@
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Utility class that contains convenience calls related with custom tabs testing.
@@ -49,31 +55,45 @@
     }
 
     public static void cleanupSessions(final CustomTabsConnection connection) {
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                connection.cleanupAll();
-            }
-        });
+        ThreadUtils.runOnUiThreadBlocking(connection::cleanupAll);
+    }
+
+    public static CustomTabsSession bindWithCallback(final CustomTabsCallback callback)
+            throws InterruptedException, TimeoutException {
+        final AtomicReference<CustomTabsSession> sessionReference = new AtomicReference<>(null);
+        final CallbackHelper waitForConnection = new CallbackHelper();
+        CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(),
+                InstrumentationRegistry.getTargetContext().getPackageName(),
+                new CustomTabsServiceConnection() {
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {}
+
+                    @Override
+                    public void onCustomTabsServiceConnected(
+                            ComponentName name, CustomTabsClient client) {
+                        sessionReference.set(client.newSession(callback));
+                        waitForConnection.notifyCalled();
+                    }
+                });
+        waitForConnection.waitForCallback(0);
+        return sessionReference.get();
     }
 
     /** Calls warmup() and waits for all the tasks to complete. Fails the test otherwise. */
     public static CustomTabsConnection warmUpAndWait()
             throws InterruptedException, TimeoutException {
         CustomTabsConnection connection = setUpConnection();
-        try {
-            final CallbackHelper startupCallbackHelper = new CallbackHelper();
-            connection.setWarmupCompletedCallbackForTesting(new Runnable() {
-                @Override
-                public void run() {
+        final CallbackHelper startupCallbackHelper = new CallbackHelper();
+        CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
+            @Override
+            public void extraCallback(String callbackName, Bundle args) {
+                if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) {
                     startupCallbackHelper.notifyCalled();
                 }
-            });
-            Assert.assertTrue(connection.warmup(0));
-            startupCallbackHelper.waitForCallback(0);
-        } finally {
-            connection.setWarmupCompletedCallbackForTesting(null);
-        }
+            }
+        });
+        Assert.assertTrue(connection.warmup(0));
+        startupCallbackHelper.waitForCallback(0);
         return connection;
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
index 10b4b20..25f05b9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
@@ -119,6 +119,9 @@
         float startX, startY, endX, endY;
         // We need to perform the scroll over a shorter area of the touchpad in order for flinging
         // to work properly.
+        // There's technically nothing that prevents fling scrolling if fling is set to false, but
+        // we have yet to find any combination of steps and speed that results in a fling with the
+        // larger scroll area that setting fling to false uses.
         // TODO(https://crbug.com/820281): Figure out why this is the case - not fling scrolling
         // because we're using more of the touchpad doesn't make sense.
         float offset = fling ? 0.5f : 0.1f;
@@ -144,11 +147,6 @@
                 Assert.fail("Unknown scroll direction enum given");
         }
         performLinearTouchpadMovement(startX, startY, endX, endY, steps, speed);
-        // There's technically nothing that prevents fling scrolling if fling is set to false, but
-        // we have yet to find any combination of steps and speed that results in a fling with the
-        // larger scroll area that setting fling to false uses. As an added precaution, assume that
-        // a fling occurred and cancel it immediately if we're not supposed to be flinging.
-        if (!fling) cancelFlingScroll();
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
index 0f993ab..0c2080ee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
@@ -13,6 +13,7 @@
 
 import android.os.SystemClock;
 import android.support.test.filters.MediumTest;
+import android.support.v7.widget.RecyclerView;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -24,6 +25,7 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.history.HistoryPage;
 import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -214,6 +216,56 @@
                 VrTestFramework.getHtmlTestFile("test_navigation_2d_page"));
     }
 
+    /*
+     * Verifies that swiping up/down on the Daydream controller's touchpad
+     * scrolls a native page while in the VR browser.
+     */
+    @Test
+    @MediumTest
+    public void testControllerScrollingNative() throws InterruptedException {
+        VrTransitionUtils.forceEnterVr();
+        VrTransitionUtils.waitForVrEntry(POLL_TIMEOUT_LONG_MS);
+        // Fill history with enough items to scroll
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_navigation_2d_page"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_controller_scrolling"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("generic_webvr_page"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_navigation_webvr_page"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_webvr_autopresent"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("generic_webxr_page"), PAGE_LOAD_TIMEOUT_S);
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_gamepad_button"), PAGE_LOAD_TIMEOUT_S);
+
+        mVrTestRule.loadUrl("chrome://history", PAGE_LOAD_TIMEOUT_S);
+
+        RecyclerView recyclerView =
+                ((HistoryPage) (mVrTestRule.getActivity().getActivityTab().getNativePage()))
+                        .getHistoryManagerForTesting()
+                        .getRecyclerViewForTests();
+
+        // Test that scrolling down works
+        int startScrollPoint = recyclerView.computeVerticalScrollOffset();
+        // Arbitrary, but valid values to scroll smoothly
+        int scrollSteps = 20;
+        int scrollSpeed = 60;
+        mController.scroll(EmulatedVrController.ScrollDirection.DOWN, scrollSteps, scrollSpeed,
+                /* fling */ false);
+        int endScrollPoint = recyclerView.computeVerticalScrollOffset();
+        Assert.assertTrue("Controller was able to scroll down", startScrollPoint < endScrollPoint);
+
+        // Test that scrolling up works
+        startScrollPoint = endScrollPoint;
+        mController.scroll(EmulatedVrController.ScrollDirection.UP, scrollSteps, scrollSpeed,
+                /* fling */ false);
+        endScrollPoint = recyclerView.computeVerticalScrollOffset();
+        Assert.assertTrue("Controller was able to scroll up", startScrollPoint > endScrollPoint);
+    }
+
     /**
      * Verifies that pressing the Daydream controller's 'app' button causes the user to exit
      * fullscreen
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
index 3ea64842c..6e403292 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -17,6 +17,7 @@
 import android.util.Base64;
 
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -67,6 +68,11 @@
     @Rule
     public final NativeLibraryTestRule mNativeLibraryTestRule = new NativeLibraryTestRule();
 
+    @Before
+    public void setUp() {
+        mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess();
+    }
+
     /**
      * Test that navigating a webapp whose launch intent does not specify a theme colour outside of
      * the webapp scope by tapping a regular link:
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index c9b270d..ec69ef5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -105,7 +105,7 @@
 @DisableFeatures({ChromeFeatureList.NTP_CONDENSED_LAYOUT, ChromeFeatureList.CHROME_HOME,
         ChromeFeatureList.CONTENT_SUGGESTIONS_SCROLL_TO_LOAD,
         ChromeFeatureList.NTP_ARTICLE_SUGGESTIONS_EXPANDABLE_HEADER,
-        ChromeFeatureList.NTP_SHORTCUTS})
+        ChromeFeatureList.NTP_SHORTCUTS, ChromeFeatureList.CHROME_DUPLEX})
 public class NewTabPageAdapterTest {
     @Rule
     public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f910049d..7eb7b50 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2724,10 +2724,6 @@
      flag_descriptions::kFramebustingName,
      flag_descriptions::kFramebustingDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kFramebustingNeedsSameOriginOrUserGesture)},
-    {"vibrate-requires-user-gesture",
-     flag_descriptions::kVibrateRequiresUserGestureName,
-     flag_descriptions::kVibrateRequiresUserGestureDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kVibrateRequiresUserGesture)},
     {"web-payments", flag_descriptions::kWebPaymentsName,
      flag_descriptions::kWebPaymentsDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kWebPayments)},
diff --git a/chrome/browser/devtools/frontend/devtools_discovery_page.html b/chrome/browser/devtools/frontend/devtools_discovery_page.html
index d10b8588..2c45611d 100644
--- a/chrome/browser/devtools/frontend/devtools_discovery_page.html
+++ b/chrome/browser/devtools/frontend/devtools_discovery_page.html
@@ -1,6 +1,7 @@
 <html>
 <head>
 <title>Inspectable pages</title>
+<meta name="referrer" content="no-referrer">
 <style>
 body {
   color: #222;
@@ -144,8 +145,7 @@
   title.className = 'title';
   title.textContent = item_object.description || item_object.title;
   if (item_object.faviconUrl) {
-    title.style.cssText = 'background-image:url(' +
-        item_object.faviconUrl + ')';
+    title.style.backgroundImage = 'url(' + item_object.faviconUrl + ')';
   }
   description.appendChild(title);
 
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
index c1134a2..12254cc 100644
--- a/chrome/browser/extensions/active_tab_permission_granter.cc
+++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -69,7 +69,8 @@
     tab_process->Send(create_message.Run(false));
 }
 
-ActiveTabPermissionGranter::Delegate* g_delegate = nullptr;
+ActiveTabPermissionGranter::Delegate* g_active_tab_permission_granter_delegate =
+    nullptr;
 
 }  // namespace
 
@@ -90,9 +91,9 @@
 ActiveTabPermissionGranter::SetPlatformDelegate(Delegate* delegate) {
   // Disallow setting it twice (but allow resetting - don't forget to free in
   // that case).
-  CHECK(!g_delegate || !delegate);
-  Delegate* previous_delegate = g_delegate;
-  g_delegate = delegate;
+  CHECK(!g_active_tab_permission_granter_delegate || !delegate);
+  Delegate* previous_delegate = g_active_tab_permission_granter_delegate;
+  g_active_tab_permission_granter_delegate = delegate;
   return previous_delegate;
 }
 
@@ -106,8 +107,9 @@
   const PermissionsData* permissions_data = extension->permissions_data();
 
   bool should_grant_active_tab =
-      !g_delegate ||
-      g_delegate->ShouldGrantActiveTab(extension, web_contents());
+      !g_active_tab_permission_granter_delegate ||
+      g_active_tab_permission_granter_delegate->ShouldGrantActiveTab(
+          extension, web_contents());
   // If the extension requested all-hosts but has had it withheld, we grant it
   // active tab-style permissions, even if it doesn't have the activeTab
   // permission in the manifest.
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc
index d36b646..9cc89a5 100644
--- a/chrome/browser/extensions/content_verifier_browsertest.cc
+++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -26,6 +26,7 @@
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/content_verifier.h"
+#include "extensions/browser/content_verifier/test_utils.h"
 #include "extensions/browser/content_verify_job.h"
 #include "extensions/browser/crx_file_info.h"
 #include "extensions/browser/extension_prefs.h"
@@ -43,158 +44,6 @@
 
 namespace {
 
-class JobObserver : public ContentVerifyJob::TestObserver {
- public:
-  JobObserver();
-  virtual ~JobObserver();
-
-  enum class Result { SUCCESS, FAILURE };
-
-  // Call this to add an expected job result.
-  void ExpectJobResult(const std::string& extension_id,
-                       const base::FilePath& relative_path,
-                       Result expected_result);
-
-  // Wait to see expected jobs. Returns true when we've seen all expected jobs
-  // finish, or false if there was an error or timeout.
-  bool WaitForExpectedJobs();
-
-  // ContentVerifyJob::TestObserver interface
-  void JobStarted(const ExtensionId& extension_id,
-                  const base::FilePath& relative_path) override;
-  void JobFinished(const ExtensionId& extension_id,
-                   const base::FilePath& relative_path,
-                   ContentVerifyJob::FailureReason failure_reason) override;
-  void OnHashesReady(const ExtensionId& extension_id,
-                     const base::FilePath& relative_path,
-                     bool success) override {}
-
- private:
-  struct ExpectedResult {
-   public:
-    std::string extension_id;
-    base::FilePath path;
-    Result result;
-
-    ExpectedResult(const ExtensionId& extension_id,
-                   const base::FilePath& path,
-                   Result result)
-        : extension_id(extension_id), path(path), result(result) {}
-  };
-  std::list<ExpectedResult> expectations_;
-  content::BrowserThread::ID creation_thread_;
-  scoped_refptr<content::MessageLoopRunner> loop_runner_;
-};
-
-void JobObserver::ExpectJobResult(const std::string& extension_id,
-                                  const base::FilePath& relative_path,
-                                  Result expected_result) {
-  expectations_.push_back(ExpectedResult(
-      extension_id, relative_path, expected_result));
-}
-
-JobObserver::JobObserver() {
-  EXPECT_TRUE(
-      content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_));
-  ContentVerifyJob::SetObserverForTests(this);
-}
-
-JobObserver::~JobObserver() {
-  ContentVerifyJob::SetObserverForTests(nullptr);
-}
-
-bool JobObserver::WaitForExpectedJobs() {
-  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_));
-  if (!expectations_.empty()) {
-    loop_runner_ = new content::MessageLoopRunner();
-    loop_runner_->Run();
-    loop_runner_ = nullptr;
-  }
-  return expectations_.empty();
-}
-
-void JobObserver::JobStarted(const std::string& extension_id,
-                             const base::FilePath& relative_path) {
-}
-
-void JobObserver::JobFinished(const std::string& extension_id,
-                              const base::FilePath& relative_path,
-                              ContentVerifyJob::FailureReason failure_reason) {
-  if (!content::BrowserThread::CurrentlyOn(creation_thread_)) {
-    content::BrowserThread::PostTask(
-        creation_thread_, FROM_HERE,
-        base::BindOnce(&JobObserver::JobFinished, base::Unretained(this),
-                       extension_id, relative_path, failure_reason));
-    return;
-  }
-  Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS
-                                                           : Result::FAILURE;
-  bool found = false;
-  for (std::list<ExpectedResult>::iterator i = expectations_.begin();
-       i != expectations_.end(); ++i) {
-    if (i->extension_id == extension_id && i->path == relative_path &&
-        i->result == result) {
-      found = true;
-      expectations_.erase(i);
-      break;
-    }
-  }
-  if (found) {
-    if (expectations_.empty() && loop_runner_.get())
-      loop_runner_->Quit();
-  } else {
-    LOG(WARNING) << "Ignoring unexpected JobFinished " << extension_id << "/"
-                 << relative_path.value()
-                 << " failure_reason:" << failure_reason;
-  }
-}
-
-class VerifierObserver : public ContentVerifier::TestObserver {
- public:
-  VerifierObserver();
-  virtual ~VerifierObserver();
-
-  const std::set<std::string>& completed_fetches() {
-    return completed_fetches_;
-  }
-
-  // Returns when we've seen OnFetchComplete for |extension_id|.
-  void WaitForFetchComplete(const std::string& extension_id);
-
-  // ContentVerifier::TestObserver
-  void OnFetchComplete(const std::string& extension_id, bool success) override;
-
- private:
-  std::set<std::string> completed_fetches_;
-  std::string id_to_wait_for_;
-  scoped_refptr<content::MessageLoopRunner> loop_runner_;
-};
-
-VerifierObserver::VerifierObserver() {
-  ContentVerifier::SetObserverForTests(this);
-}
-
-VerifierObserver::~VerifierObserver() {
-  ContentVerifier::SetObserverForTests(nullptr);
-}
-
-void VerifierObserver::WaitForFetchComplete(const std::string& extension_id) {
-  EXPECT_TRUE(id_to_wait_for_.empty());
-  EXPECT_EQ(loop_runner_.get(), nullptr);
-  id_to_wait_for_ = extension_id;
-  loop_runner_ = new content::MessageLoopRunner();
-  loop_runner_->Run();
-  id_to_wait_for_.clear();
-  loop_runner_ = nullptr;
-}
-
-void VerifierObserver::OnFetchComplete(const std::string& extension_id,
-                                       bool success) {
-  completed_fetches_.insert(extension_id);
-  if (extension_id == id_to_wait_for_)
-    loop_runner_->Quit();
-}
-
 // This lets us intercept requests for update checks of extensions, and
 // substitute a local file as a simulated response.
 class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
@@ -365,11 +214,11 @@
     // Now disable the extension, since content scripts are read at enable time,
     // set up our job observer, and re-enable, expecting a success this time.
     DisableExtension(id);
-    JobObserver job_observer;
+    using Result = TestContentVerifyJobObserver::Result;
+    TestContentVerifyJobObserver job_observer;
     base::FilePath script_relfilepath =
         base::FilePath().AppendASCII(script_relpath);
-    job_observer.ExpectJobResult(id, script_relfilepath,
-                                 JobObserver::Result::SUCCESS);
+    job_observer.ExpectJobResult(id, script_relfilepath, Result::SUCCESS);
     EnableExtension(id);
     EXPECT_TRUE(job_observer.WaitForExpectedJobs());
 
@@ -383,35 +232,31 @@
       ASSERT_TRUE(base::AppendToFile(scriptfile, extra.data(), extra.size()));
     }
     DisableExtension(id);
-    job_observer.ExpectJobResult(id, script_relfilepath,
-                                 JobObserver::Result::FAILURE);
+    job_observer.ExpectJobResult(id, script_relfilepath, Result::FAILURE);
     EnableExtension(id);
     EXPECT_TRUE(job_observer.WaitForExpectedJobs());
   }
 };
 
 IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) {
-  JobObserver job_observer;
+  TestContentVerifyJobObserver job_observer;
   std::string id = "hoipipabpcoomfapcecilckodldhmpgl";
 
+  using Result = TestContentVerifyJobObserver::Result;
   job_observer.ExpectJobResult(
-      id, base::FilePath(FILE_PATH_LITERAL("background.js")),
-      JobObserver::Result::SUCCESS);
-  job_observer.ExpectJobResult(id,
-                               base::FilePath(FILE_PATH_LITERAL("page.html")),
-                               JobObserver::Result::SUCCESS);
+      id, base::FilePath(FILE_PATH_LITERAL("background.js")), Result::SUCCESS);
+  job_observer.ExpectJobResult(
+      id, base::FilePath(FILE_PATH_LITERAL("page.html")), Result::SUCCESS);
   job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("page.js")),
-                               JobObserver::Result::SUCCESS);
+                               Result::SUCCESS);
   job_observer.ExpectJobResult(
-      id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")),
-      JobObserver::Result::SUCCESS);
-  job_observer.ExpectJobResult(id,
-                               base::FilePath(FILE_PATH_LITERAL("page2.js")),
-                               JobObserver::Result::SUCCESS);
+      id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")), Result::SUCCESS);
+  job_observer.ExpectJobResult(
+      id, base::FilePath(FILE_PATH_LITERAL("page2.js")), Result::SUCCESS);
   job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs1.js")),
-                               JobObserver::Result::SUCCESS);
+                               Result::SUCCESS);
   job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs2.js")),
-                               JobObserver::Result::SUCCESS);
+                               Result::SUCCESS);
 
   VerifierObserver verifier_observer;
 
diff --git a/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
new file mode 100644
index 0000000..8e1a611
--- /dev/null
+++ b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
@@ -0,0 +1,833 @@
+// 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 <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/extensions/browsertest_util.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/browser/computed_hashes.h"
+#include "extensions/browser/content_verifier/test_utils.h"
+#include "extensions/browser/extension_file_task_runner.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/test_extension_registry_observer.h"
+#include "extensions/common/file_util.h"
+#include "net/url_request/test_url_request_interceptor.h"
+
+namespace extensions {
+
+namespace {
+
+// Specifies the content verification mode.
+enum ContentVerificationMode {
+  // Uses --extension-content-verification=enforce flag.
+  kEnforce,
+  // Uses --extension-content-verification=enforce_strict flag.
+  kEnforceStrict
+};
+
+}  // namespace
+
+// Tests content verification's hash fetch behavior and its implication on
+// verification failure in different verification modes (enforce and
+// enforce_strict).
+// TODO(lazyboy): Add assertions for checking verified_contents.json file's
+// validity after running each test.
+class ContentVerifierHashTest
+    : public ExtensionBrowserTest,
+      public testing::WithParamInterface<ContentVerificationMode> {
+ public:
+  ContentVerifierHashTest() = default;
+  ~ContentVerifierHashTest() override {}
+
+  enum TamperResourceType {
+    kTamperRequestedResource,
+    kTamperNotRequestedResource
+  };
+
+  // ExtensionBrowserTest:
+  bool ShouldEnableContentVerification() override { return true; }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ExtensionBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitchASCII(
+        switches::kExtensionContentVerification,
+        uses_enforce_strict_mode()
+            ? switches::kExtensionContentVerificationEnforceStrict
+            : switches::kExtensionContentVerificationEnforce);
+  }
+
+  bool uses_enforce_strict_mode() {
+    return GetParam() == ContentVerificationMode::kEnforceStrict;
+  }
+  bool uses_enforce_mode() {
+    return GetParam() == ContentVerificationMode::kEnforce;
+  }
+
+  void DisableHashFetching() { hash_fetching_disabled_ = true; }
+
+  testing::AssertionResult InstallDefaultResourceExtension() {
+    LOG(INFO) << "InstallDefaultResourceExtension";
+    return InstallExtension(kHasDefaultResource);
+  }
+  testing::AssertionResult InstallNoDefaultResourceExtension() {
+    LOG(INFO) << "InstallNoDefaultResourceExtension";
+    return InstallExtension(kDoesNotHaveDefaultResource);
+  }
+
+  void DisableExtension() { ExtensionBrowserTest::DisableExtension(id()); }
+
+  testing::AssertionResult DeleteVerifiedContents() {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+
+    base::FilePath verified_contents_path =
+        file_util::GetVerifiedContentsPath(info_->extension_root);
+    if (!base::PathExists(verified_contents_path)) {
+      return testing::AssertionFailure()
+             << "Could not find verified_contents.json.";
+    }
+
+    // Delete verified_contents.json:
+    if (!base::DeleteFile(verified_contents_path, false /* recursive */)) {
+      return testing::AssertionFailure()
+             << "Could not delete verified_contents.json.";
+    }
+    return testing::AssertionSuccess();
+  }
+
+  bool HasComputedHashes() {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    return base::PathExists(
+        file_util::GetComputedHashesPath(info_->extension_root));
+  }
+
+  testing::AssertionResult DeleteComputedHashes() {
+    LOG(INFO) << "Deleting computed_hashes.json";
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    if (!HasComputedHashes()) {
+      return testing::AssertionFailure()
+             << "Could not find computed_hashes.json for deletion. "
+             << "Make sure the previous steps created a "
+             << "computed_hashes.json, otherwise tests might fail/flake";
+    }
+    base::FilePath computed_hashes_path =
+        file_util::GetComputedHashesPath(info_->extension_root);
+    if (!base::DeleteFile(computed_hashes_path, false /* recursive */)) {
+      return testing::AssertionFailure()
+             << "Error deleting computed_hashes.json.";
+    }
+    return testing::AssertionSuccess();
+  }
+
+  testing::AssertionResult TamperComputedHashes() {
+    LOG(INFO) << "Tampering computed_hashes.json";
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    if (!HasComputedHashes()) {
+      return testing::AssertionFailure()
+             << "Could not find computed_hashes.json for tampering.";
+    }
+    base::FilePath computed_hashes_path =
+        file_util::GetComputedHashesPath(info_->extension_root);
+    std::string extra = R"({hello:"world"})";
+    if (!base::AppendToFile(computed_hashes_path, extra.data(), extra.size())) {
+      return testing::AssertionFailure()
+             << "Could not tamper computed_hashes.json";
+    }
+    return testing::AssertionSuccess();
+  }
+
+  testing::AssertionResult TamperResource(TamperResourceType type) {
+    const std::string resource_to_tamper =
+        type == kTamperRequestedResource ? "background.js" : "script.js";
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    // Modify content of a resource if this test requested that, time the
+    // extension loads, hash fetch will discover content verification failure
+    // due to hash mismatch.
+    std::string extra = "some_extra_function_call();";
+    base::FilePath real_path =
+        info_->extension_root.AppendASCII(resource_to_tamper);
+    if (!base::AppendToFile(real_path, extra.data(), extra.size())) {
+      return testing::AssertionFailure()
+             << "Could not tamper " << resource_to_tamper << ".";
+    }
+    return testing::AssertionSuccess();
+  }
+
+  const ExtensionId& id() const { return info_->extension_id; }
+
+  void EnableExtensionAndWaitForCompletion(bool expect_disabled) {
+    LOG(INFO) << "EnableExtensionAndWaitForCompletion: expect_disabled = "
+              << expect_disabled;
+    // Only observe ContentVerifyJob when necessary. This is because
+    // ContentVerifyJob's callback and ContentVerifyJob::OnExtensionLoad's
+    // callbacks can be race-y.
+    std::unique_ptr<TestContentVerifyJobObserver> job_observer;
+    const bool needs_to_observe_content_verify_job =
+        // If the test wouldn't disable the extension, extensions with
+        // default resource(s) will always see at at least one ContentVerifyJob
+        // to a default resource (background.js).
+        info_->type == kHasDefaultResource && !expect_disabled;
+
+    if (needs_to_observe_content_verify_job) {
+      LOG(INFO) << "Observing ContentVerifyJob";
+      job_observer = std::make_unique<TestContentVerifyJobObserver>();
+      using Result = TestContentVerifyJobObserver::Result;
+      job_observer->ExpectJobResult(
+          id(), base::FilePath(FILE_PATH_LITERAL("background.js")),
+          Result::SUCCESS);
+    }
+
+    if (interceptor_) {
+      EXPECT_EQ(0, interceptor_->GetHitCount()) << "Interceptor should not "
+                                                   "have seen any requests "
+                                                   "before enabling extension.";
+    }
+
+    TestExtensionRegistryObserver registry_observer(
+        ExtensionRegistry::Get(profile()), id());
+    VerifierObserver verifier_observer;
+    {
+      EnableExtension(id());
+      registry_observer.WaitForExtensionLoaded();
+    }
+    if (!base::ContainsKey(verifier_observer.completed_fetches(), id()))
+      verifier_observer.WaitForFetchComplete(id());
+    LOG(INFO) << "Verifier observer has seen FetchComplete";
+
+    if (job_observer) {
+      LOG(INFO) << "ContentVerifyJobObserver, wait for expected job";
+      job_observer->WaitForExpectedJobs();
+      LOG(INFO) << "ContentVerifyJobObserver, completed expected job";
+    }
+  }
+
+  bool ExtensionIsDisabledForCorruption() {
+    const Extension* extension = extensions::ExtensionRegistry::Get(profile())
+                                     ->disabled_extensions()
+                                     .GetByID(id());
+    if (!extension)
+      return false;
+
+    ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+    // Make sure the extension got disabled due to corruption (and only due to
+    // corruption).
+    int reasons = prefs->GetDisableReasons(id());
+    return reasons == disable_reason::DISABLE_CORRUPTED;
+  }
+
+  bool ExtensionIsEnabled() {
+    return extensions::ExtensionRegistry::Get(profile())
+        ->enabled_extensions()
+        .Contains(id());
+  }
+
+  bool HasValidComputedHashes() {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ComputedHashes::Reader reader;
+    return reader.InitFromFile(
+        file_util::GetComputedHashesPath(info_->extension_root));
+  }
+
+  bool HasValidVerifiedContents() {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    base::FilePath verified_contents_path =
+        file_util::GetVerifiedContentsPath(info_->extension_root);
+    if (!base::PathExists(verified_contents_path)) {
+      ADD_FAILURE() << "Could not find verified_contents.json.";
+      return false;
+    }
+    std::string contents;
+    if (!base::ReadFileToString(verified_contents_path, &contents)) {
+      ADD_FAILURE() << "Could not read verified_contents.json.";
+      return false;
+    }
+    return verified_contents_contents_ == contents;
+  }
+
+ private:
+  enum ExtensionType {
+    // An extension (has_default_resource.crx) that by default requests a
+    // resource in it during ExtensionLoad.
+    kHasDefaultResource,
+    // An extension (no_default_resources.crx) that doesn't request any
+    // resource during ExtensionLoad.
+    kDoesNotHaveDefaultResource
+  };
+
+  struct ExtensionInfo {
+    ExtensionId extension_id;
+    base::FilePath extension_root;
+    base::Version version;
+    ExtensionType type;
+
+    ExtensionInfo(const ExtensionId& extension_id,
+                  const base::FilePath& extension_root,
+                  const base::Version& version,
+                  ExtensionType type)
+        : extension_id(extension_id),
+          extension_root(extension_root),
+          version(version),
+          type(type) {}
+    ExtensionInfo(const Extension* extension, ExtensionType type)
+        : ExtensionInfo(extension->id(),
+                        extension->path(),
+                        extension->version(),
+                        type) {}
+  };
+
+  // Stores verified_contents.json into a temp file.
+  bool CopyVerifiedContents(base::FilePath* out_path) {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    if (!temp_dir_.CreateUniqueTempDir()) {
+      ADD_FAILURE() << "Could not create temp dir for test.";
+      return false;
+    }
+
+    base::FilePath verified_contents_path =
+        file_util::GetVerifiedContentsPath(info_->extension_root);
+    if (!base::PathExists(verified_contents_path)) {
+      ADD_FAILURE() << "Could not find verified_contents.json for copying.";
+      return false;
+    }
+    base::FilePath destination = temp_dir_.GetPath();
+    *out_path = destination.Append(FILE_PATH_LITERAL("copy.json"));
+    if (!base::CopyFile(verified_contents_path, *out_path)) {
+      ADD_FAILURE() << "Could not copy verified_contents.json to a temp dir.";
+      return false;
+    }
+    if (!base::ReadFileToString(verified_contents_path,
+                                &verified_contents_contents_)) {
+      ADD_FAILURE() << "Could not read verified_contents.json.";
+      return false;
+    }
+    return true;
+  }
+
+  bool AddInterceptor() {
+    if (interceptor_) {
+      ADD_FAILURE() << "Already created interceptor.";
+      return false;
+    }
+
+    // Use stored copy of verified_contents.json as hash fetch response.
+    base::FilePath copied_verified_contents_path;
+    if (!CopyVerifiedContents(&copied_verified_contents_path)) {
+      ADD_FAILURE() << "Could not copy verified_contents.json.";
+      return false;
+    }
+
+    ExtensionSystem* system = ExtensionSystem::Get(profile());
+    GURL fetch_url = system->content_verifier()->GetSignatureFetchUrlForTest(
+        id(), info_->version);
+
+    // Mock serving |copied_verified_contents_path| for content hash, so that
+    // hash fetch succeeds.
+    interceptor_ = std::make_unique<net::TestURLRequestInterceptor>(
+        fetch_url.scheme(), fetch_url.host(),
+        content::BrowserThread::GetTaskRunnerForThread(
+            content::BrowserThread::IO),
+        GetExtensionFileTaskRunner());
+    interceptor_->SetResponse(fetch_url, copied_verified_contents_path);
+    return true;
+  }
+
+  // Installs test extension that is copied from the webstore with actual
+  // signatures.
+  testing::AssertionResult InstallExtension(ExtensionType type) {
+    // This observer will make sure content hash read and computed_hashes.json
+    // writing is complete before we proceed.
+    VerifierObserver verifier_observer;
+
+    const std::string crx_relative_path =
+        type == kHasDefaultResource
+            ? "content_verifier/has_default_resource.crx"
+            : "content_verifier/no_default_resources.crx";
+    // These test extension is copied from the webstore that has actual
+    // signatures.
+    const Extension* extension = InstallExtensionFromWebstore(
+        test_data_dir_.AppendASCII(crx_relative_path), 1);
+    if (!extension) {
+      return testing::AssertionFailure()
+             << "Could not install extension: " << crx_relative_path;
+    }
+
+    const ExtensionId& extension_id = extension->id();
+    if (!base::ContainsKey(verifier_observer.completed_fetches(), extension_id))
+      verifier_observer.WaitForFetchComplete(extension_id);
+
+    info_ = std::make_unique<ExtensionInfo>(extension, type);
+
+    // Interceptor.
+    if (!hash_fetching_disabled_ && !AddInterceptor())
+      return testing::AssertionFailure() << "Failed to install interceptor.";
+
+    return testing::AssertionSuccess();
+  }
+
+  std::unique_ptr<net::TestURLRequestInterceptor> interceptor_;
+  base::ScopedTempDir temp_dir_;
+
+  // Information about the loaded extension.
+  std::unique_ptr<ExtensionInfo> info_;
+
+  // Contents of verified_contents.json (if available).
+  std::string verified_contents_contents_;
+
+  bool hash_fetching_disabled_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentVerifierHashTest);
+};
+
+// Tests that corruption of a requested extension resource always disables the
+// extension.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperRequestedResourceKeepComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json should remain valid.
+  EXPECT_TRUE(HasComputedHashes());
+
+  // Tamper an extension resource that will be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // Since we tampered with the resource, content verification should
+  // disable the extension, both in "enforce_strict" and "enforce" mode.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests that tampering a resource that will be requested by the extension and
+// deleting computed_hashes.json will always disable the extension.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperRequestedResourceDeleteComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Delete computed_hashes.json.
+  EXPECT_TRUE(DeleteComputedHashes());
+
+  // Tamper an extension resource that will be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // Since we tampered with the resource, content verification should
+  // disable the extension, both in "enforce_strict" and "enforce" mode.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid computed_hashes.json file at the end, the verification
+  // failure must have used this file to detect corruption.
+  EXPECT_TRUE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests that tampering a resource that will be requested by the extension and
+// tampering computed_hashes.json will always disable the extension.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperRequestedResourceTamperComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Tamper computed_hashes.json.
+  EXPECT_TRUE(TamperComputedHashes());
+
+  // Tamper an extension resource that will be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // Since we tampered with the resource, content verification should
+  // disable the extension, both in "enforce_strict" and "enforce" mode.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid computed_hashes.json file at the end, the verification
+  // failure must have used this file to detect corruption.
+  EXPECT_TRUE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests hash fetch failure scenario with an extension that requests resource(s)
+// by default.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       FetchFailureWithDefaultResourceExtension) {
+  // Do *not* install any hash fetch interceptor, so that hash fetch after
+  // reload fails.
+  DisableHashFetching();
+
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json and extension resource(s) aren't touched since they do
+  // not matter as hash fetch will fail.
+
+  // In "enforce_strict" mode, hash fetch failures will cause the extension to
+  // be disabled. Implementation-wise, this happens because the requested
+  // resource's ContentVerifyJob will result in failure, not because the hash
+  // fetch failed. See https://crbug.com/819818 for details.
+  //
+  // In "enforce" mode, the extension won't be disabled. However, since we
+  // request a resource (background.js), its corresponding ContentVerifyJob will
+  // attempt to fetch hash and that job will also fail. In order to achieve
+  // determinism in this case, also observe a ContentVerifyJob that will fail.
+  const bool expect_disabled = uses_enforce_strict_mode();
+
+  // Similar to EnableExtensionAndWaitForCompletion, but also forces a
+  // ContentVerifyJob observer in "enforce" mode.
+  // Instead of generalizing this oddball expectation into
+  // EnableExtensionAndWaitForCompletion, provide the implementation right here
+  // in the test body.
+  {
+    LOG(INFO) << "EnableExtensionAndWaitForCompletion: expect_disabled = "
+              << expect_disabled;
+    ExtensionId extension_id = id();
+
+    // Only observe ContentVerifyJob when necessary. This is because
+    // ContentVerifyJob's callback and ContentVerifyJob::OnExtensionLoad's
+    // callbacks can be race-y.
+    std::unique_ptr<TestContentVerifyJobObserver> job_observer;
+    if (uses_enforce_mode()) {
+      // In "enforce" mode, we expect to see a job completion (and its failure).
+      job_observer = std::make_unique<TestContentVerifyJobObserver>();
+      using Result = TestContentVerifyJobObserver::Result;
+      job_observer->ExpectJobResult(
+          extension_id,
+          // This extension has default resource (background.js), so it must
+          // request it.
+          base::FilePath(FILE_PATH_LITERAL("background.js")), Result::FAILURE);
+    }
+
+    TestExtensionRegistryObserver registry_observer(
+        ExtensionRegistry::Get(profile()), extension_id);
+    VerifierObserver verifier_observer;
+    {
+      EnableExtension(extension_id);
+      registry_observer.WaitForExtensionLoaded();
+    }
+    if (!base::ContainsKey(verifier_observer.completed_fetches(), extension_id))
+      verifier_observer.WaitForFetchComplete(extension_id);
+    LOG(INFO) << "Verifier observer has seen FetchComplete";
+
+    if (job_observer) {
+      LOG(INFO) << "ContentVerifyJobObserver, wait for expected job";
+      job_observer->WaitForExpectedJobs();
+      LOG(INFO) << "ContentVerifyJobObserver, completed expected job";
+    }
+
+    if (expect_disabled)
+      EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+  }
+
+  EXPECT_TRUE(expect_disabled ? ExtensionIsDisabledForCorruption()
+                              : ExtensionIsEnabled());
+}
+
+// Tests that hash fetch failure for loading an extension that doesn't request
+// any resource by default will not be disabled.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       FetchFailureWithNoDefaultResourceDoesNotDisable) {
+  // Do *not* install any hash fetch interceptor, so that hash fetch after
+  // reload fails.
+  DisableHashFetching();
+
+  ASSERT_TRUE(InstallNoDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json and extension resource(s) aren't touched since they do
+  // not matter as hash fetch will fail.
+
+  // If the extension didn't explicitly request any resources, then there will
+  // not be any content verification failures.
+  const bool expect_disabled = false;
+  // TODO(lazyboy): https://crbug.com/819818: "enforce_strict" mode should
+  // disable the extension.
+  // const bool expect_disabled = uses_enforce_strict_mode();
+  EnableExtensionAndWaitForCompletion(expect_disabled);
+
+  EXPECT_TRUE(expect_disabled ? ExtensionIsDisabledForCorruption()
+                              : ExtensionIsEnabled());
+}
+
+// Tests the behavior of tampering an extension resource that is not requested
+// by default and without modifying computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperNotRequestedResourceKeepComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json should remain valid.
+  EXPECT_TRUE(HasComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  // We tampered a resource that is not requested by the extension. Keeping
+  // computed_hashes.json will not compute new compute computed_hashes.json, and
+  // we will not discover the tampered hash. So the extension won't be disabled.
+  //
+  // TODO(lazyboy): http://crbug.com/819832: We fetched a new
+  // verified_contents.json in this case. However, if we had recomputed
+  // computed_hashes.json we would have discovered the tampered resource's hash
+  // mismatch. Fix.
+  const bool expect_disabled = false;
+  EnableExtensionAndWaitForCompletion(expect_disabled);
+
+  EXPECT_TRUE(ExtensionIsEnabled());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading an extension without any default resource
+// request and deleting its computed_hashes.json before fetching hashes.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperNoResourceExtensionDeleteComputedHashes) {
+  ASSERT_TRUE(InstallNoDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Delete computed_hashes.json.
+  EXPECT_TRUE(DeleteComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // The deletion of computed_hashes.json forces its recomputation and disables
+  // the extension.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid computed_hashes.json file at the end, the verification
+  // failure must have used this file to detect corruption.
+  EXPECT_TRUE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading an extension without any default resource
+// request and keeping its computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperNoResourceExtensionKeepComputedHashes) {
+  ASSERT_TRUE(InstallNoDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json should remain valid.
+  EXPECT_TRUE(HasComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  // Not modifying computed_hashes.json will not trigger any hash computation
+  // at OnExtensionLoad, so we won't discover any hash mismatches.
+  EnableExtensionAndWaitForCompletion(false /* expect_disabled */);
+
+  EXPECT_TRUE(ExtensionIsEnabled());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading an extension without any default resource
+// request and tampering its computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest,
+                       TamperNoResourceExtensionTamperComputedHashes) {
+  ASSERT_TRUE(InstallNoDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Tamper computed_hashes.json.
+  EXPECT_TRUE(TamperComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  // Tampering computed_hashes.json will not trigger any hash computation
+  // at OnExtensionLoad, so we won't discover any hash mismatches.
+  // TODO(lazyboy): Consider fixing this, see http://crbug.com/819832 for
+  // details.
+  EnableExtensionAndWaitForCompletion(false /* expect_disabled */);
+
+  EXPECT_TRUE(ExtensionIsEnabled());
+
+  // Because we didn't do any hash computation, expect computed_hashes.json to
+  // still remain invalid.
+  EXPECT_FALSE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading a default resource extension with tampering
+// an extension resource that is not requested by default and without modifying
+// computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(
+    ContentVerifierHashTest,
+    DefaultRequestExtensionTamperNotRequestedResourceKeepComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // computed_hashes.json should remain valid.
+  EXPECT_TRUE(HasComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  // TODO(lazyboy): Not modifying the computed_hashes.json file doesn't prompt
+  // a hash recomputation and the requested (not-tampered) resource's
+  // corresponding ContentVerifyJob succeeds because that resource's hash
+  // remains fine. Therefore, the extension remains enabled. Consider disabling
+  // the extension in this case: https://crbug.com/819832.
+  EnableExtensionAndWaitForCompletion(false /* expect_disabled */);
+
+  EXPECT_TRUE(ExtensionIsEnabled());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading a default resource extension with tampering
+// an extension resource that is not requested by default and tampering
+// computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(
+    ContentVerifierHashTest,
+    DefaultRequestExtensionTamperNotRequestedResourceTamperComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Tamper computed_hashes.json.
+  EXPECT_TRUE(TamperComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // Subtle: tampering computed_hashes.json (by itself) will not trigger any
+  // hash computation or failure during OnExtensionLoad. However, the default
+  // resource request (that isn't tampered) will prompt a hash read that will
+  // fail due to the tampered computed_hashes.json.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid computed_hashes.json file at the end, the verification
+  // failure must have used this file to detect corruption.
+  EXPECT_TRUE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+// Tests the behavior of loading a default resource extension with tampering
+// an extension resource that is not requested by default and deleting
+// computed_hashes.json.
+IN_PROC_BROWSER_TEST_P(
+    ContentVerifierHashTest,
+    DefaultRequestExtensionTamperNotRequestedResourceDeleteComputedHashes) {
+  ASSERT_TRUE(InstallDefaultResourceExtension());
+
+  DisableExtension();
+
+  // Delete verified_contents.json to force a hash fetch on next load.
+  EXPECT_TRUE(DeleteVerifiedContents());
+
+  // Delete computed_hashes.json.
+  EXPECT_TRUE(DeleteComputedHashes());
+
+  // Tamper an extension resource that will *not* be requested on next load.
+  EXPECT_TRUE(TamperResource(kTamperNotRequestedResource));
+
+  TestExtensionRegistryObserver registry_observer(
+      ExtensionRegistry::Get(profile()), id());
+  // The deletion of computed_hashes.json will trigger hash recomputation and
+  // the file's regeneration. This will discover the resource tampering and
+  // disable the extension.
+  EnableExtensionAndWaitForCompletion(true /* expect_disabled */);
+  EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded());
+
+  EXPECT_TRUE(ExtensionIsDisabledForCorruption());
+
+  // Expect a valid computed_hashes.json file at the end, the verification
+  // failure must have used this file to detect corruption.
+  EXPECT_TRUE(HasValidComputedHashes());
+
+  // Expect a valid verified_contents.json file at the end.
+  EXPECT_TRUE(HasValidVerifiedContents());
+}
+
+INSTANTIATE_TEST_CASE_P(FetchBehaviorTests,
+                        ContentVerifierHashTest,
+                        testing::Values(kEnforce, kEnforceStrict));
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index 20497429..c49bb9b 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -562,7 +562,7 @@
 
   // Valid and readable 1024.js.
   {
-    TestContentVerifyJobObserver observer(extension_id, kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
 
     content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
     // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
@@ -574,7 +574,7 @@
 
   // chmod -r 1024.js.
   {
-    TestContentVerifyJobObserver observer(extension->id(), kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath);
     base::FilePath file_path = unzipped_path.AppendASCII(kJs);
     ASSERT_TRUE(base::MakeFileUnreadable(file_path));
     EXPECT_EQ(net::ERR_ACCESS_DENIED, DoRequestOrLoad(extension, kJs).result());
@@ -588,7 +588,7 @@
 
   // Delete 1024.js.
   {
-    TestContentVerifyJobObserver observer(extension_id, kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
     base::FilePath file_path = unzipped_path.AppendASCII(kJs);
     ASSERT_TRUE(base::DieFileDie(file_path, false));
     EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
@@ -623,7 +623,7 @@
 
   // Request empty.js.
   {
-    TestContentVerifyJobObserver observer(extension_id, kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
 
     content_verifier_->OnExtensionLoaded(browser_context(), extension.get());
     // Wait for PostTask to ContentVerifierIOData::AddData() to finish.
@@ -638,7 +638,7 @@
   // current behavior of ContentVerifyJob.
   // TODO(lazyboy): The behavior is probably incorrect.
   {
-    TestContentVerifyJobObserver observer(extension->id(), kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath);
     base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
     ASSERT_TRUE(base::MakeFileUnreadable(file_path));
     EXPECT_EQ(net::ERR_ACCESS_DENIED,
@@ -651,7 +651,7 @@
   // current behavior of ContentVerifyJob.
   // TODO(lazyboy): The behavior is probably incorrect.
   {
-    TestContentVerifyJobObserver observer(extension_id, kRelativePath);
+    TestContentVerifySingleJobObserver observer(extension_id, kRelativePath);
     base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs);
     ASSERT_TRUE(base::DieFileDie(file_path, false));
     EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index f7691554..bc0755e 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -104,7 +104,7 @@
   return SessionTabHelper::IdForTab(web_contents);
 }
 
-ExtensionTabUtil::Delegate* g_delegate = nullptr;
+ExtensionTabUtil::Delegate* g_extension_tab_util_delegate = nullptr;
 
 }  // namespace
 
@@ -476,8 +476,8 @@
 void ExtensionTabUtil::SetPlatformDelegate(Delegate* delegate) {
   // Allow setting it only once (also allow reset to nullptr, but then take
   // special care to free it).
-  CHECK(!g_delegate || !delegate);
-  g_delegate = delegate;
+  CHECK(!g_extension_tab_util_delegate || !delegate);
+  g_extension_tab_util_delegate = delegate;
 }
 
 // static
@@ -507,8 +507,9 @@
     tab->title.reset();
     tab->fav_icon_url.reset();
   }
-  if (g_delegate)
-    g_delegate->ScrubTabForExtension(extension, contents, tab);
+  if (g_extension_tab_util_delegate)
+    g_extension_tab_util_delegate->ScrubTabForExtension(extension, contents,
+                                                        tab);
 }
 
 bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents,
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 9bd2997..681b280 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -30,7 +30,8 @@
 // each user gesture. This variable should only be accessed from the UI thread.
 bool g_accept_requests = true;
 
-ExternalProtocolHandler::Delegate* g_delegate = nullptr;
+ExternalProtocolHandler::Delegate* g_external_protocol_handler_delegate =
+    nullptr;
 
 constexpr const char* kDeniedSchemes[] = {
     "afp", "data", "disk", "disks",
@@ -147,7 +148,7 @@
 
 // static
 void ExternalProtocolHandler::SetDelegateForTesting(Delegate* delegate) {
-  g_delegate = delegate;
+  g_external_protocol_handler_delegate = delegate;
 }
 
 // static
@@ -237,11 +238,11 @@
   Profile* profile = nullptr;
   if (web_contents)  // Maybe NULL during testing.
     profile = Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  BlockState block_state =
-      GetBlockStateWithDelegate(escaped_url.scheme(), g_delegate, profile);
+  BlockState block_state = GetBlockStateWithDelegate(
+      escaped_url.scheme(), g_external_protocol_handler_delegate, profile);
   if (block_state == BLOCK) {
-    if (g_delegate)
-      g_delegate->BlockRequest();
+    if (g_external_protocol_handler_delegate)
+      g_external_protocol_handler_delegate->BlockRequest();
     return;
   }
 
@@ -252,12 +253,13 @@
   shell_integration::DefaultWebClientWorkerCallback callback = base::Bind(
       &OnDefaultProtocolClientWorkerFinished, escaped_url,
       render_process_host_id, render_view_routing_id, block_state == UNKNOWN,
-      page_transition, has_user_gesture, g_delegate);
+      page_transition, has_user_gesture, g_external_protocol_handler_delegate);
 
   // Start the check process running. This will send tasks to a worker task
   // runner and when the answer is known will send the result back to
   // OnDefaultProtocolClientWorkerFinished().
-  CreateShellWorker(callback, escaped_url.scheme(), g_delegate)
+  CreateShellWorker(callback, escaped_url.scheme(),
+                    g_external_protocol_handler_delegate)
       ->StartCheckIsDefault();
 }
 
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 9b28b25..3868223 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1640,12 +1640,6 @@
     "This enables upcoming and experimental V8 VM features. "
     "This flag does not enable experimental JavaScript features.";
 
-const char kVibrateRequiresUserGestureName[] =
-    "Requiring user gesture for the Vibration API";
-const char kVibrateRequiresUserGestureDescription[] =
-    "Block the Vibration API if no user gesture has been received on the frame "
-    "or any embedded frame.";
-
 const char kVideoFullscreenOrientationLockName[] =
     "Lock screen orientation when playing a video fullscreen.";
 const char kVideoFullscreenOrientationLockDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 20cab74..4d67f3d 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1002,9 +1002,6 @@
 extern const char kV8VmFutureName[];
 extern const char kV8VmFutureDescription[];
 
-extern const char kVibrateRequiresUserGestureName[];
-extern const char kVibrateRequiresUserGestureDescription[];
-
 extern const char kVideoFullscreenOrientationLockName[];
 extern const char kVideoFullscreenOrientationLockDescription[];
 
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 20b9d28..44d7c88 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -123,6 +123,7 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
+#include "components/safe_browsing/features.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
@@ -3982,6 +3983,9 @@
 // Test that when password protection warning trigger is set by policy, chrome
 // password protection service gets the correct value.
 IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTrigger) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      safe_browsing::kEnterprisePasswordProtectionV1);
   // Without setting up the enterprise policy,
   // |GetPasswordProtectionTriggerPref(..) should return |PHISHING_REUSE|.
   const PrefService* const prefs = browser()->profile()->GetPrefs();
@@ -4019,6 +4023,9 @@
 // Test that when password protection risk trigger is set by policy, chrome
 // password protection service gets the correct value.
 IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionRiskTrigger) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      safe_browsing::kEnterprisePasswordProtectionV1);
   // Without setting up the enterprise policy,
   // |GetPasswordProtectionTriggerPref(..) should return |PHISHING_REUSE|.
   const PrefService* const prefs = browser()->profile()->GetPrefs();
@@ -4056,6 +4063,9 @@
 // Test that when safe browsing whitelist domains are set by policy, safe
 // browsing service gets the correct value.
 IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingWhitelistDomains) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      safe_browsing::kEnterprisePasswordProtectionV1);
   // Without setting up the enterprise policy,
   // |GetSafeBrowsingDomainsPref(..) should return empty list.
   const PrefService* const prefs = browser()->profile()->GetPrefs();
@@ -4101,6 +4111,9 @@
 // Test that when password protection login URLs are set by policy, password
 // protection service gets the correct value.
 IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionLoginURLs) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      safe_browsing::kEnterprisePasswordProtectionV1);
   // Without setting up the enterprise policy,
   // |GetPasswordProtectionLoginURLsPref(..) should return empty list.
   const PrefService* const prefs = browser()->profile()->GetPrefs();
@@ -4144,6 +4157,9 @@
 // Test that when password protection change password URL is set by policy,
 // password protection service gets the correct value.
 IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionChangePasswordURL) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      safe_browsing::kEnterprisePasswordProtectionV1);
   // Without setting up the enterprise policy,
   // |GetChangePasswordURL(..) should return default GAIA change password URL.
   const PrefService* const prefs = browser()->profile()->GetPrefs();
diff --git a/chrome/browser/resources/policy_tool.css b/chrome/browser/resources/policy_tool.css
index 7ddad45a..d62e867 100644
--- a/chrome/browser/resources/policy_tool.css
+++ b/chrome/browser/resources/policy_tool.css
@@ -32,6 +32,13 @@
   display: block;
 }
 
+#session-rename-error {
+  display: block;
+  color: red;
+  margin: 20px;
+  text-align: center;
+}
+
 #session-list {
   background: white;
 }
@@ -43,3 +50,22 @@
 #session-actions {
   float: left;
 }
+
+#session-actions button {
+  display: block;
+  width: 80px;
+}
+
+#rename-dialog {
+  border: 3px black;
+  height: 130px;
+  outline: 2px solid DarkGrey;
+  text-align: center;
+  width: 300px;
+}
+
+#new-session-name-field {
+  display: block;
+  margin: 20px auto;
+  width: 250px
+}
diff --git a/chrome/browser/resources/policy_tool.html b/chrome/browser/resources/policy_tool.html
index 12b6227..e2d27feb 100644
--- a/chrome/browser/resources/policy_tool.html
+++ b/chrome/browser/resources/policy_tool.html
@@ -31,6 +31,8 @@
       <h1>$i18n{title}</h1>
     </header>
     <section class="reload-show-unset-section">
+      <h1 id="session-title">
+      </h1>
       <form id="session-choice">
         <input id="session-name-field" type="text" autocomplete="off"
             placeholder="$i18n{sessionNamePlaceholder}">
@@ -51,8 +53,15 @@
       </span>
     </section>
     <section id="sessions">
+      <dialog id="rename-dialog">
+        <input id="new-session-name-field" type="text">
+        <button id="cancel-rename-button">$i18n{cancelRename}</button>
+        <button id="confirm-rename-button">$i18n{confirmRename}</button>
+        <span id="session-rename-error" hidden></span>
+      </dialog>
       <div id="session-actions">
-        <button id="delete-session-button">-</button>
+        <button id="delete-session-button">$i18n{removeSession}</button>
+        <button id="rename-session-button">$i18n{renameSession}</button>
       </div>
       <select size="4" id="session-list">
       </select>
diff --git a/chrome/browser/resources/policy_tool.js b/chrome/browser/resources/policy_tool.js
index c3e321c..67bcba9d 100644
--- a/chrome/browser/resources/policy_tool.js
+++ b/chrome/browser/resources/policy_tool.js
@@ -21,6 +21,10 @@
   }
 };
 
+policy.Page.setSessionTitle = function(name) {
+  $('session-title').textContent = name;
+};
+
 // Override some methods of policy.Page.
 
 /**
@@ -31,6 +35,23 @@
 };
 
 /**
+ * Shows error message of rename session.
+ */
+policy.Page.showRenameSessionError = function(errorMessage) {
+  $('session-rename-error').hidden = false;
+  $('session-rename-error').textContent = errorMessage;
+};
+
+/**
+ * Close dialog of rename session.
+ */
+policy.Page.closeRenameSessionDialog = function() {
+  $('session-rename-error').textContent = '';
+  $('session-rename-error').hidden = true;
+  $('rename-dialog').close();
+};
+
+/**
  * Disables editing policy values by hiding the main section and shows an
  * error message instead.
  */
@@ -116,6 +137,29 @@
     }
   };
 
+  $('rename-session-button').onclick = () => {
+    $('session-rename-error').hidden = true;
+    var sessionName = $('session-list').value;
+    if (sessionName) {
+      $('rename-dialog').showModal();
+      $('new-session-name-field').value = '';
+      $('new-session-name-field').select();
+    }
+  };
+
+  $('cancel-rename-button').onclick = () => {
+    $('rename-dialog').close();
+  };
+
+  $('confirm-rename-button').onclick = () => {
+    $('session-rename-error').textContent = '';
+    var sessionName = $('session-list').value;
+    var newSessionName = $('new-session-name-field').value;
+    if (sessionName && newSessionName) {
+      chrome.send('renameSession', [sessionName, newSessionName]);
+    }
+  };
+
   // Notify the browser that the page has loaded, causing it to send the
   // list of all known policies and the values from the default session.
   chrome.send('initialized');
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.cc b/chrome/browser/safe_browsing/certificate_reporting_service.cc
index 9725da7..5cad9ff7 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc
@@ -14,7 +14,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace {
 
@@ -321,8 +321,28 @@
   std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter;
   if (server_public_key) {
     // Only used in tests.
-    std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender(
-        url_request_context, TRAFFIC_ANNOTATION_FOR_TESTS));
+    net::NetworkTrafficAnnotationTag traffic_annotation =
+        net::DefineNetworkTrafficAnnotation(
+            "certificate_reporting_service_test", R"(
+        semantics {
+          sender: "Certificate Reporting Service Test"
+          description:
+            "This request is used for testing certificate reporting service."
+          trigger: "Upon request from testing API."
+          data:
+            "No user data."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "This feature is only used for testing."
+          policy_exception_justification:
+            "This feature is only used for testing."
+        }
+    )");
+    std::unique_ptr<net::ReportSender> report_sender(
+        new net::ReportSender(url_request_context, traffic_annotation));
     error_reporter.reset(new certificate_reporting::ErrorReporter(
         GURL(kExtendedReportingUploadUrl), server_public_key,
         server_public_key_version, std::move(report_sender)));
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index a3555999..2a84d57 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -152,28 +152,33 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 // TODO(tangltom): Add a unit test for this function.
 std::vector<AccountInfo> GetAccountsForDicePromos(Profile* profile) {
-  SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile);
-  DCHECK(!signin_manager->IsAuthenticated());
-
   // Fetch account ids for accounts that have a token.
   ProfileOAuth2TokenService* token_service =
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
   std::vector<std::string> account_ids = token_service->GetAccounts();
-  // Fetch accounts in the Gaia cookies.
-  GaiaCookieManagerService* cookie_manager_service =
-      GaiaCookieManagerServiceFactory::GetForProfile(profile);
-  std::vector<gaia::ListedAccount> cookie_accounts;
-  bool gaia_accounts_stale = !cookie_manager_service->ListAccounts(
-      &cookie_accounts, nullptr, "ProfileChooserView");
-  UMA_HISTOGRAM_BOOLEAN("Profile.DiceUI.GaiaAccountsStale",
-                        gaia_accounts_stale);
+
+  // Compute the default account.
+  SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile);
+  std::string default_account_id;
+  if (signin_manager->IsAuthenticated()) {
+    default_account_id = signin_manager->GetAuthenticatedAccountId();
+  } else {
+    // Fetch accounts in the Gaia cookies.
+    GaiaCookieManagerService* cookie_manager_service =
+        GaiaCookieManagerServiceFactory::GetForProfile(profile);
+    std::vector<gaia::ListedAccount> cookie_accounts;
+    bool gaia_accounts_stale = !cookie_manager_service->ListAccounts(
+        &cookie_accounts, nullptr, "ProfileChooserView");
+    UMA_HISTOGRAM_BOOLEAN("Profile.DiceUI.GaiaAccountsStale",
+                          gaia_accounts_stale);
+    if (!cookie_accounts.empty())
+      default_account_id = cookie_accounts[0].id;
+  }
 
   // Fetch account information for each id and make sure that the first account
   // in the list matches the first account in the Gaia cookies (if available).
   AccountTrackerService* account_tracker_service =
       AccountTrackerServiceFactory::GetForProfile(profile);
-  std::string gaia_default_account_id =
-      cookie_accounts.empty() ? "" : cookie_accounts[0].id;
   std::vector<AccountInfo> accounts;
   for (const std::string& account_id : account_ids) {
     DCHECK(!account_id.empty());
@@ -183,7 +188,7 @@
         !signin_manager->IsAllowedUsername(account_info.email)) {
       continue;
     }
-    if (account_id == gaia_default_account_id)
+    if (account_id == default_account_id)
       accounts.insert(accounts.begin(), account_info);
     else
       accounts.push_back(account_info);
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
index 17dd6a3..c1791cf 100644
--- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -441,6 +441,15 @@
   ExpectUIShown(false);
 }
 
+TEST_F(BlockTabUnderTest, SameSiteRedirect_NoBlocking) {
+  EXPECT_TRUE(
+      NavigateAndCommitWithoutGesture(GURL("https://sub1.blah.co.uk/")));
+  SimulatePopup();
+  EXPECT_TRUE(
+      NavigateAndCommitWithoutGesture(GURL("https://sub2.blah.co.uk/path")));
+  ExpectUIShown(false);
+}
+
 TEST_F(BlockTabUnderTest, BrowserInitiatedNavigation_NoBlocking) {
   EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/")));
   SimulatePopup();
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
index 72bc51d..5f8f42f 100644
--- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
+++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
@@ -24,10 +24,10 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/console_message_level.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "url/gurl.h"
-#include "url/origin.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/ui/android/infobars/framebust_block_infobar.h"
@@ -140,9 +140,10 @@
   if (previous_main_frame_url.is_empty())
     return false;
 
-  // Only cross origin navigations are considered tab-unders.
-  if (url::Origin::Create(previous_main_frame_url)
-          .IsSameOriginWith(url::Origin::Create(navigation_handle->GetURL()))) {
+  // Same-site navigations are exempt from tab-under protection.
+  if (net::registry_controlled_domains::SameDomainOrHost(
+          previous_main_frame_url, navigation_handle->GetURL(),
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
     return false;
   }
 
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
index 61403b6..749b72a9 100644
--- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
+++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
@@ -28,7 +28,7 @@
 // 1. It is a navigation that is "suspicious"
 //    a. It has no user gesture.
 //    b. It is renderer-initiated.
-//    c. It is cross origin to the last committed URL in the tab.
+//    c. It is cross site to the last committed URL in the tab.
 // 2. The tab has opened a popup and hasn't received a user gesture since then.
 //    This information is tracked by the PopupOpenerTabHelper.
 class TabUnderNavigationThrottle : public content::NavigationThrottle {
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
index 6afffb4..20842fa 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -24,7 +24,6 @@
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
@@ -200,10 +199,8 @@
   return GetExtension()->short_name();
 }
 
-std::string HostedAppBrowserController::GetDomainAndRegistry() const {
-  return net::registry_controlled_domains::GetDomainAndRegistry(
-      AppLaunchInfo::GetLaunchWebURL(GetExtension()),
-      net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+url::Origin HostedAppBrowserController::GetUrlOrigin() const {
+  return url::Origin::Create(AppLaunchInfo::GetLaunchWebURL(GetExtension()));
 }
 
 void HostedAppBrowserController::OnEngagementEvent(
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
index 3f973040..69c348e 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -63,8 +63,8 @@
   // Gets the short name of the app.
   std::string GetAppShortName() const;
 
-  // Gets the domain and registry of the app start url (e.g example.com.au).
-  std::string GetDomainAndRegistry() const;
+  // Gets the origin of the app start url (e.g www.example.com.au).
+  url::Origin GetUrlOrigin() const;
 
   // Gets the extension for this controller.
   const Extension* GetExtension() const;
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index df78a217..6f33e99 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h"
+#include "chrome/browser/ui/views_mode_controller.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
@@ -78,6 +79,12 @@
                                   Browser* browser) {
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
   views::View* reference_view = nullptr;
+
+#if defined(OS_MACOSX)
+  if (views_mode_controller::IsViewsBrowserCocoa())
+    return nullptr;
+#endif
+
   switch (controller->anchor_position()) {
     case ExtensionInstalledBubble::ANCHOR_ACTION: {
       BrowserActionsContainer* container =
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 8d270c0..b8b40c8 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -12,6 +12,7 @@
 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/frame/default_frame_header.h"
 #include "ash/frame/frame_border_hit_test.h"
+#include "ash/frame/frame_header_origin_text.h"
 #include "ash/frame/frame_header_util.h"
 #include "ash/public/cpp/app_types.h"
 #include "ash/public/cpp/ash_switches.h"
@@ -22,6 +23,10 @@
 #include "ash/wm/overview/window_selector_controller.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
@@ -67,6 +72,10 @@
 constexpr SkColor kMdWebUIFrameColor =
     SkColorSetARGBMacro(0xff, 0x25, 0x4f, 0xae);
 
+// How long to wait before starting the titlebar animation.
+constexpr base::TimeDelta kTitlebarAnimationDelay =
+    base::TimeDelta::FromMilliseconds(750);
+
 bool IsV1AppBackButtonEnabled() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       ash::switches::kAshEnableV1AppBackButton);
@@ -93,6 +102,16 @@
   }
 }
 
+void SetRightSide(gfx::Rect* rect, int x) {
+  rect->set_x(x - rect->width());
+  DCHECK_EQ(rect->right(), x);
+}
+
+void AlignVerticalCenterWith(gfx::Rect* rect, const gfx::Rect& sibling) {
+  rect->set_y(sibling.y() + (sibling.height() - rect->height()) / 2);
+  DCHECK_EQ(rect->CenterPoint().y(), sibling.CenterPoint().y());
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -106,7 +125,8 @@
       back_button_(nullptr),
       window_icon_(nullptr),
       hosted_app_button_container_(nullptr),
-      observer_binding_(this) {
+      observer_binding_(this),
+      weak_factory_(this) {
   ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(),
                                                       nullptr);
   ash::Shell::Get()->AddShellObserver(this);
@@ -332,6 +352,9 @@
   if (hosted_app_button_container_)
     hosted_app_button_container_->SetPaintAsActive(should_paint_as_active);
 
+  if (frame_header_origin_text_)
+    frame_header_origin_text_->SetPaintAsActive(should_paint_as_active);
+
   if (browser_view()->IsToolbarVisible() &&
       !browser_view()->toolbar()->GetPreferredSize().IsEmpty() &&
       browser_view()->IsTabStripVisible()) {
@@ -361,6 +384,21 @@
   const int inset =
       (tab_strip_visible || immersive) ? 0 : GetTopInset(/*restored=*/false);
   frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset);
+
+  if (frame_header_origin_text_) {
+    // Align the right side of the text with the left side of the caption
+    // buttons.
+    gfx::Size origin_text_preferred_size =
+        frame_header_origin_text_->GetPreferredSize();
+    int origin_text_width =
+        std::min(width() - caption_button_container_->width(),
+                 origin_text_preferred_size.width());
+    gfx::Rect text_bounds(origin_text_width,
+                          origin_text_preferred_size.height());
+    SetRightSide(&text_bounds, caption_button_container_->x());
+    AlignVerticalCenterWith(&text_bounds, caption_button_container_->bounds());
+    frame_header_origin_text_->SetBoundsRect(text_bounds);
+  }
 }
 
 const char* BrowserNonClientFrameViewAsh::GetClassName() const {
@@ -557,6 +595,8 @@
   std::unique_ptr<ash::DefaultFrameHeader> default_frame_header =
       std::make_unique<ash::DefaultFrameHeader>(frame(), this,
                                                 caption_button_container_);
+
+  // TODO(alancutter): Move this branch into a new HostedAppFrameHeader class.
   if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
           browser)) {
     // Hosted apps apply a theme color if specified by the extension.
@@ -570,14 +610,33 @@
     }
 
     // Add the container for extra hosted app buttons (e.g app menu button).
-    SkColor button_color = ash::FrameCaptionButton::GetButtonColor(
+    SkColor active_color = ash::FrameCaptionButton::GetButtonColor(
         default_frame_header->ShouldUseLightImages());
     const float inactive_alpha_ratio =
         ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
+    SkColor inactive_color =
+        SkColorSetA(active_color, 255 * inactive_alpha_ratio);
     hosted_app_button_container_ = new HostedAppButtonContainer(
-        browser_view(), button_color,
-        SkColorSetA(button_color, 255 * inactive_alpha_ratio));
+        browser_view(), active_color, inactive_color);
     caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0);
+
+    // Add the origin text.
+    frame_header_origin_text_ =
+        std::make_unique<ash::FrameHeaderOriginText>(
+            base::UTF8ToUTF16(
+                browser->hosted_app_controller()->GetUrlOrigin().host()),
+            active_color, inactive_color,
+            default_frame_header->GetActiveFrameColor(),
+            default_frame_header->GetInactiveFrameColor())
+            .release();
+    AddChildView(frame_header_origin_text_);
+
+    // Schedule the title bar animation.
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation,
+                       weak_factory_.GetWeakPtr()),
+        kTitlebarAnimationDelay);
   } else if (!browser->is_app()) {
     // For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color.
     default_frame_header->SetFrameColors(kMdWebUIFrameColor,
@@ -592,3 +651,9 @@
 
   return default_frame_header;
 }
+
+void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() {
+  frame_header_origin_text_->StartSlideAnimation();
+  hosted_app_button_container_->StartTitlebarAnimation(
+      frame_header_origin_text_->AnimationDuration());
+}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index 4282a506..682ad124 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -24,6 +24,7 @@
 class FrameCaptionButton;
 class FrameCaptionButtonContainerView;
 class FrameHeader;
+class FrameHeaderOriginText;
 }
 
 // Provides the BrowserNonClientFrameView for Chrome OS.
@@ -128,6 +129,10 @@
   // Creates the frame header for the browser window.
   std::unique_ptr<ash::FrameHeader> CreateFrameHeader();
 
+  // Triggers the hosted app origin and icon animations, assumes the hosted app
+  // UI elements exist.
+  void StartHostedAppAnimation();
+
   // View which contains the window controls.
   ash::FrameCaptionButtonContainerView* caption_button_container_;
 
@@ -143,6 +148,10 @@
   // Owned by views hierarchy.
   HostedAppButtonContainer* hosted_app_button_container_;
 
+  // URL origin text for hosted app windows.
+  // Owned by views hierarchy.
+  ash::FrameHeaderOriginText* frame_header_origin_text_ = nullptr;
+
   // Ash's mojom::SplitViewController.
   ash::mojom::SplitViewControllerPtr split_view_controller_;
 
@@ -159,6 +168,8 @@
   ash::mojom::SplitViewState split_view_state_ =
       ash::mojom::SplitViewState::NO_SNAP;
 
+  base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
 };
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index efccea6..fa38d0a 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -568,8 +568,8 @@
   EXPECT_EQ(expected_active_icon_color, button_container->active_icon_color_);
 
   // Show a content setting icon.
-  auto& content_setting_views =
-      frame_view->hosted_app_button_container_->content_setting_views_;
+  auto& content_setting_views = frame_view->hosted_app_button_container_
+                                    ->GetContentSettingViewsForTesting();
 
   for (auto* v : content_setting_views)
     EXPECT_FALSE(v->visible());
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
index 00e129d..e3d70cc 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -18,9 +18,13 @@
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/widget/native_widget_aura.h"
 
@@ -29,6 +33,9 @@
 // Padding around content setting icons.
 constexpr int kContentSettingIconInteriorPadding = 4;
 
+constexpr base::TimeDelta kContentSettingsFadeInDuration =
+    base::TimeDelta::FromMilliseconds(500);
+
 class HostedAppToolbarActionsBar : public ToolbarActionsBar {
  public:
   using ToolbarActionsBar::ToolbarActionsBar;
@@ -45,6 +52,99 @@
 
 }  // namespace
 
+class HostedAppButtonContainer::ContentSettingsContainer
+    : public views::View,
+      public ContentSettingImageView::Delegate {
+ public:
+  ContentSettingsContainer(BrowserView* browser_view, SkColor icon_color);
+  ~ContentSettingsContainer() override = default;
+
+  // Updates the visibility of each content setting.
+  void RefreshContentSettingViews() {
+    for (auto* v : content_setting_views_)
+      v->Update();
+  }
+
+  // Sets the color of the content setting icons.
+  void SetIconColor(SkColor icon_color) {
+    for (auto* v : content_setting_views_)
+      v->SetIconColor(icon_color);
+  }
+
+  void FadeIn() {
+    SetVisible(true);
+    DCHECK_EQ(layer()->opacity(), 0);
+    ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
+    settings.SetTransitionDuration(kContentSettingsFadeInDuration);
+    layer()->SetOpacity(1);
+  }
+
+  const std::vector<ContentSettingImageView*>&
+  GetContentSettingViewsForTesting() const {
+    return content_setting_views_;
+  }
+
+ private:
+  // views::View:
+  void ChildVisibilityChanged(views::View* child) override {
+    PreferredSizeChanged();
+  }
+
+  // ContentSettingsImageView::Delegate:
+  content::WebContents* GetContentSettingWebContents() override {
+    return browser_view_->GetActiveWebContents();
+  }
+  ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
+      override {
+    return browser_view_->browser()->content_setting_bubble_model_delegate();
+  }
+  void OnContentSettingImageBubbleShown(
+      ContentSettingImageModel::ImageType type) const override {
+    UMA_HISTOGRAM_ENUMERATION(
+        "HostedAppFrame.ContentSettings.ImagePressed", type,
+        ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES);
+  }
+
+  // Owned by the views hierarchy.
+  std::vector<ContentSettingImageView*> content_setting_views_;
+
+  BrowserView* browser_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContentSettingsContainer);
+};
+
+const std::vector<ContentSettingImageView*>&
+HostedAppButtonContainer::GetContentSettingViewsForTesting() const {
+  return content_settings_container_->GetContentSettingViewsForTesting();
+}
+
+HostedAppButtonContainer::ContentSettingsContainer::ContentSettingsContainer(
+    BrowserView* browser_view,
+    SkColor icon_color)
+    : browser_view_(browser_view) {
+  SetLayoutManager(
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+
+  SetVisible(false);
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+  layer()->SetOpacity(0);
+
+  std::vector<std::unique_ptr<ContentSettingImageModel>> models =
+      ContentSettingImageModel::GenerateContentSettingImageModels();
+  for (auto& model : models) {
+    auto image_view = std::make_unique<ContentSettingImageView>(
+        std::move(model), this,
+        views::NativeWidgetAura::GetWindowTitleFontList());
+    image_view->SetIconColor(icon_color);
+    image_view->set_next_element_interior_padding(
+        kContentSettingIconInteriorPadding);
+    image_view->disable_animation();
+    content_setting_views_.push_back(image_view.get());
+    AddChildView(image_view.release());
+  }
+}
+
 HostedAppButtonContainer::AppMenuButton::AppMenuButton(
     BrowserView* browser_view)
     : views::MenuButton(base::string16(), this, false),
@@ -81,6 +181,13 @@
   menu_->RunMenu(this);
 }
 
+void HostedAppButtonContainer::StartTitlebarAnimation(
+    base::TimeDelta origin_text_slide_duration) {
+  fade_in_content_setting_buttons_timer_.Start(
+      FROM_HERE, origin_text_slide_duration, content_settings_container_,
+      &ContentSettingsContainer::FadeIn);
+}
+
 HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view,
                                                    SkColor active_icon_color,
                                                    SkColor inactive_icon_color)
@@ -100,20 +207,10 @@
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
   SetLayoutManager(std::move(layout));
 
-  std::vector<std::unique_ptr<ContentSettingImageModel>> models =
-      ContentSettingImageModel::GenerateContentSettingImageModels();
-  for (auto& model : models) {
-    auto image_view = std::make_unique<ContentSettingImageView>(
-        std::move(model), this,
-        views::NativeWidgetAura::GetWindowTitleFontList());
-    image_view->SetIconColor(active_icon_color);
-    image_view->set_next_element_interior_padding(
-        kContentSettingIconInteriorPadding);
-    image_view->SetVisible(false);
-    image_view->disable_animation();
-    content_setting_views_.push_back(image_view.get());
-    AddChildView(image_view.release());
-  }
+  auto content_settings_container = std::make_unique<ContentSettingsContainer>(
+      browser_view, active_icon_color);
+  content_settings_container_ = content_settings_container.get();
+  AddChildView(content_settings_container.release());
 
   AddChildView(browser_actions_container_);
 
@@ -126,37 +223,22 @@
 HostedAppButtonContainer::~HostedAppButtonContainer() {}
 
 void HostedAppButtonContainer::RefreshContentSettingViews() {
-  for (auto* v : content_setting_views_)
-    v->Update();
+  content_settings_container_->RefreshContentSettingViews();
 }
 
 void HostedAppButtonContainer::SetPaintAsActive(bool active) {
-  for (auto* v : content_setting_views_)
-    v->SetIconColor(active ? active_icon_color_ : inactive_icon_color_);
+  content_settings_container_->SetIconColor(active ? active_icon_color_
+                                                   : inactive_icon_color_);
 
   app_menu_button_->SetIconColor(active ? active_icon_color_
                                         : inactive_icon_color_);
 }
 
-content::WebContents* HostedAppButtonContainer::GetContentSettingWebContents() {
-  return browser_view_->GetActiveWebContents();
-}
-
-ContentSettingBubbleModelDelegate*
-HostedAppButtonContainer::GetContentSettingBubbleModelDelegate() {
-  return browser_view_->browser()->content_setting_bubble_model_delegate();
-}
-
-void HostedAppButtonContainer::OnContentSettingImageBubbleShown(
-    ContentSettingImageModel::ImageType type) const {
-  UMA_HISTOGRAM_ENUMERATION(
-      "HostedAppFrame.ContentSettings.ImagePressed", type,
-      ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES);
-}
-
 void HostedAppButtonContainer::ChildPreferredSizeChanged(views::View* child) {
-  if (child != browser_actions_container_)
+  if (child != browser_actions_container_ &&
+      child != content_settings_container_) {
     return;
+  }
 
   PreferredSizeChanged();
 }
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h
index 4187f43..5e2015e 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.h
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -21,7 +21,6 @@
 
 // A container for hosted app buttons in the title bar.
 class HostedAppButtonContainer : public views::View,
-                                 public ContentSettingImageView::Delegate,
                                  public BrowserActionsContainer::Delegate,
                                  public BrowserViewButtonProvider {
  public:
@@ -32,15 +31,24 @@
                            SkColor inactive_icon_color);
   ~HostedAppButtonContainer() override;
 
-  // Updates the visibility of each content setting view.
+  // Updates the visibility of each content setting.
   void RefreshContentSettingViews();
 
   // Sets the container to paints its buttons the active/inactive color.
   void SetPaintAsActive(bool active);
 
+  // Animates the menu button and content setting icons. Intended to run in sync
+  // with a FrameHeaderOriginText slide animation.
+  void StartTitlebarAnimation(base::TimeDelta origin_text_slide_duration);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame);
 
+  class ContentSettingsContainer;
+
+  const std::vector<ContentSettingImageView*>&
+  GetContentSettingViewsForTesting() const;
+
   // The 'app menu' button for the hosted app.
   class AppMenuButton : public views::MenuButton,
                         public views::MenuButtonListener {
@@ -71,12 +79,7 @@
     DISALLOW_COPY_AND_ASSIGN(AppMenuButton);
   };
 
-  // ContentSettingsImageView::Delegate:
-  content::WebContents* GetContentSettingWebContents() override;
-  ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate()
-      override;
-  void OnContentSettingImageBubbleShown(
-      ContentSettingImageModel::ImageType type) const override;
+  void FadeInContentSettingButtons();
 
   // views::View:
   void ChildPreferredSizeChanged(views::View* child) override;
@@ -101,11 +104,15 @@
   const SkColor active_icon_color_;
   const SkColor inactive_icon_color_;
 
+  base::OneShotTimer fade_in_content_setting_buttons_timer_;
+
   // Owned by the views hierarchy.
   AppMenuButton* app_menu_button_;
-  std::vector<ContentSettingImageView*> content_setting_views_;
+  ContentSettingsContainer* content_settings_container_;
   BrowserActionsContainer* browser_actions_container_;
 
+  base::OneShotTimer opening_animation_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer);
 };
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 01d7b65..4177b12 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -569,18 +569,18 @@
     }
   };
 
+  if (star_view_)
+    add_trailing_decoration(star_view_);
+  add_trailing_decoration(zoom_view_);
+  add_trailing_decoration(find_bar_icon_);
 #if defined(OS_CHROMEOS)
   if (intent_picker_view_)
     add_trailing_decoration(intent_picker_view_);
 #endif
-  if (star_view_)
-    add_trailing_decoration(star_view_);
-  add_trailing_decoration(find_bar_icon_);
   add_trailing_decoration(translate_icon_view_);
   if (save_credit_card_icon_view_)
     add_trailing_decoration(save_credit_card_icon_view_);
   add_trailing_decoration(manage_passwords_icon_view_);
-  add_trailing_decoration(zoom_view_);
   for (ContentSettingViews::const_reverse_iterator i(
            content_setting_views_.rbegin());
        i != content_setting_views_.rend(); ++i) {
diff --git a/chrome/browser/ui/views/profiles/dice_accounts_menu.cc b/chrome/browser/ui/views/profiles/dice_accounts_menu.cc
index 6e59c69..5ad7f9e 100644
--- a/chrome/browser/ui/views/profiles/dice_accounts_menu.cc
+++ b/chrome/browser/ui/views/profiles/dice_accounts_menu.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/profiles/dice_accounts_menu.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -92,13 +93,25 @@
   // Calculate custom anchor bounds to position the menu.
   // The menu is aligned along the right edge (left edge in RTL mode) of the
   // anchor, slightly shifted inside by |kAnchorInset| and overlapping
-  // |anchor_view| on the bottom by |kAnchorInset|. |anchor_bounds|' width is
-  // set to 0 so that the menu only is as wide as it needs to be.
+  // |anchor_view| on the bottom by |kAnchorInset|. |anchor_bounds| is collapsed
+  // so the menu only takes the width it needs.
   gfx::Rect anchor_bounds = anchor_view->GetBoundsInScreen();
-  anchor_bounds.Inset(
-      base::i18n::IsRTL() ? kAnchorInset : anchor_bounds.width() - kAnchorInset,
-      kAnchorInset, 0, kAnchorInset);
-  anchor_bounds.set_width(0);
+  anchor_bounds.Inset(kAnchorInset, kAnchorInset);
+#if defined(OS_MACOSX)
+  // On Mac, menus align to the left of the anchor, so collapse the right side
+  // of the rect.
+  bool collapse_right = true;
+#else
+  bool collapse_right = false;
+#endif
+  if (base::i18n::IsRTL())
+    collapse_right = !collapse_right;
+
+  if (collapse_right)
+    anchor_bounds.Inset(0, 0, anchor_bounds.width(), 0);
+  else
+    anchor_bounds.Inset(anchor_bounds.width(), 0, 0, 0);
+
   runner_->RunMenuAt(anchor_view->GetWidget(), nullptr, anchor_bounds,
                      views::MENU_ANCHOR_TOPRIGHT, ui::MENU_SOURCE_MOUSE);
 }
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc
index 7e8a3811..b368fb5 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "components/feature_engagement/buildflags.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
 #include "third_party/skia/include/pathops/SkPathOps.h"
 #include "ui/base/default_theme_provider.h"
@@ -55,8 +55,7 @@
   layer_info.fColorMode = SkBlendMode::kDst;
   layer_info.fOffset.set(0, 1);
   SkPaint* layer_paint = looper_builder.addLayer(layer_info);
-  layer_paint->setMaskFilter(SkBlurMaskFilter::Make(
-      kNormal_SkBlurStyle, 0.5, SkBlurMaskFilter::kHighQuality_BlurFlag));
+  layer_paint->setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 0.5));
   layer_paint->setColorFilter(
       SkColorFilter::MakeModeFilter(color, SkBlendMode::kSrcIn));
   return looper_builder.detach();
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 6c330cd..e0923404 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -38,7 +38,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
 #include "third_party/skia/include/pathops/SkPathOps.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/chrome/browser/ui/webui/policy_tool_ui.cc b/chrome/browser/ui/webui/policy_tool_ui.cc
index 4152ba140..05974ca 100644
--- a/chrome/browser/ui/webui/policy_tool_ui.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui.cc
@@ -29,10 +29,14 @@
   source->AddLocalizedString("hideExpandedValue",
                              IDS_POLICY_HIDE_EXPANDED_VALUE);
   source->AddLocalizedString("loadSession", IDS_POLICY_TOOL_LOAD_SESSION);
+  source->AddLocalizedString("removeSession", IDS_POLICY_TOOL_REMOVE_SESSION);
+  source->AddLocalizedString("renameSession", IDS_POLICY_TOOL_RENAME_SESSION);
   source->AddLocalizedString("sessionNamePlaceholder",
                              IDS_POLICY_TOOL_SESSION_NAME_PLACEHOLDER);
   source->AddLocalizedString("filterPlaceholder",
                              IDS_POLICY_FILTER_PLACEHOLDER);
+  source->AddLocalizedString("cancelRename", IDS_POLICY_TOOL_CANCEL_RENAME);
+  source->AddLocalizedString("confirmRename", IDS_POLICY_TOOL_CONFIRM_RENAME);
   source->AddLocalizedString("edit", IDS_POLICY_TOOL_EDIT);
   source->AddLocalizedString("save", IDS_POLICY_TOOL_SAVE);
   source->AddLocalizedString("errorSavingDisabled",
@@ -42,6 +46,12 @@
   source->AddLocalizedString("errorFileCorrupted",
                              IDS_POLICY_TOOL_CORRUPTED_FILE);
   source->AddLocalizedString("enableEditing", IDS_POLICY_TOOL_ENABLE_EDITING);
+  source->AddLocalizedString("errorRenameFailed",
+                             IDS_POLICY_TOOL_RENAME_FAILED);
+  source->AddLocalizedString("errorSessionExist",
+                             IDS_POLICY_TOOL_SESSION_EXIST);
+  source->AddLocalizedString("errorSessionNotExist",
+                             IDS_POLICY_TOOL_SESSION_NOT_EXIST);
   source->AddLocalizedString("errorDeleteFailed",
                              IDS_POLICY_TOOL_DELETE_FAILED);
   // Overwrite the title value added by PolicyUIHandler.
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
index 6700b11..b7ee406b 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/json/json_writer.h"
 #include "base/macros.h"
 #include "base/path_service.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
@@ -40,10 +41,13 @@
 
   void LoadSession(const std::string& session_name);
   void DeleteSession(const std::string& session_name);
+  void RenameSession(const std::string& session_name,
+                     const std::string& new_session_name);
 
   std::unique_ptr<base::DictionaryValue> ExtractPolicyValues(bool need_status);
 
   bool IsInvalidSessionNameErrorMessageDisplayed();
+  bool IsSessionRenameErrorMessageDisplayed();
 
   std::unique_ptr<base::ListValue> ExtractSessionsList();
 
@@ -114,6 +118,18 @@
   content::RunAllTasksUntilIdle();
 }
 
+void PolicyToolUITest::RenameSession(const std::string& session_name,
+                                     const std::string& new_session_name) {
+  const std::string javascript =
+      base::StrCat({"$('session-list').value = '", session_name, "';",
+                    "$('rename-session-button').click();",
+                    "$('new-session-name-field').value = '", new_session_name,
+                    "';", "$('confirm-rename-button').click();"});
+  EXPECT_TRUE(content::ExecuteScript(
+      browser()->tab_strip_model()->GetActiveWebContents(), javascript));
+  content::RunAllTasksUntilIdle();
+}
+
 std::unique_ptr<base::DictionaryValue> PolicyToolUITest::ExtractPolicyValues(
     bool need_status) {
   std::string javascript =
@@ -170,6 +186,16 @@
   return result;
 }
 
+bool PolicyToolUITest::IsSessionRenameErrorMessageDisplayed() {
+  constexpr char kJavascript[] =
+      "domAutomationController.send($('session-rename-error').hidden == false)";
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  bool result = false;
+  EXPECT_TRUE(ExecuteScriptAndExtractBool(contents, kJavascript, &result));
+  return result;
+}
+
 void PolicyToolUITest::CreateMultipleSessionFiles(int count) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   EXPECT_TRUE(base::CreateDirectory(GetSessionsDir()));
@@ -429,3 +455,54 @@
   expected.GetList().erase(expected.GetList().begin());
   EXPECT_EQ(expected, *ExtractSessionsList());
 }
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSession) {
+  CreateMultipleSessionFiles(3);
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId"));
+
+  // Check that a non-current session is renamed correctly.
+  RenameSession("0", "4");
+  EXPECT_FALSE(IsSessionRenameErrorMessageDisplayed());
+  base::ListValue expected;
+  expected.GetList().push_back(base::Value("2"));
+  expected.GetList().push_back(base::Value("1"));
+  expected.GetList().push_back(base::Value("4"));
+  EXPECT_EQ(expected, *ExtractSessionsList());
+
+  // Check that the current session can be renamed properly.
+  RenameSession("2", "5");
+  EXPECT_FALSE(IsSessionRenameErrorMessageDisplayed());
+  expected.GetList()[0] = base::Value("5");
+  EXPECT_EQ(expected, *ExtractSessionsList());
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionWithExistingSessionName) {
+  CreateMultipleSessionFiles(3);
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId"));
+
+  // Check that a session can not be renamed with a name of another existing
+  // session.
+  RenameSession("2", "1");
+  EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed());
+  base::ListValue expected;
+  expected.GetList().push_back(base::Value("2"));
+  expected.GetList().push_back(base::Value("1"));
+  expected.GetList().push_back(base::Value("0"));
+  EXPECT_EQ(expected, *ExtractSessionsList());
+}
+
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionInvalidName) {
+  CreateMultipleSessionFiles(3);
+  ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
+  EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId"));
+
+  RenameSession("2", "../");
+  EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed());
+  base::ListValue expected;
+  expected.GetList().push_back(base::Value("2"));
+  expected.GetList().push_back(base::Value("1"));
+  expected.GetList().push_back(base::Value("0"));
+  EXPECT_EQ(expected, *ExtractSessionsList());
+}
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.cc b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
index fd437004..03517416 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
@@ -12,6 +12,8 @@
 #include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 // static
 const base::FilePath::CharType PolicyToolUIHandler::kPolicyToolSessionsDir[] =
@@ -37,20 +39,29 @@
       Profile::FromWebUI(web_ui())->GetPath().Append(kPolicyToolSessionsDir);
 
   web_ui()->RegisterMessageCallback(
-      "initialized", base::Bind(&PolicyToolUIHandler::HandleInitializedAdmin,
-                                base::Unretained(this)));
+      "initialized",
+      base::BindRepeating(&PolicyToolUIHandler::HandleInitializedAdmin,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "loadSession", base::Bind(&PolicyToolUIHandler::HandleLoadSession,
-                                base::Unretained(this)));
+      "loadSession",
+      base::BindRepeating(&PolicyToolUIHandler::HandleLoadSession,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "updateSession", base::Bind(&PolicyToolUIHandler::HandleUpdateSession,
-                                  base::Unretained(this)));
+      "renameSession",
+      base::BindRepeating(&PolicyToolUIHandler::HandleRenameSession,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "resetSession", base::Bind(&PolicyToolUIHandler::HandleResetSession,
-                                 base::Unretained(this)));
+      "updateSession",
+      base::BindRepeating(&PolicyToolUIHandler::HandleUpdateSession,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "deleteSession", base::Bind(&PolicyToolUIHandler::HandleDeleteSession,
-                                  base::Unretained(this)));
+      "resetSession",
+      base::BindRepeating(&PolicyToolUIHandler::HandleResetSession,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "deleteSession",
+      base::BindRepeating(&PolicyToolUIHandler::HandleDeleteSession,
+                          base::Unretained(this)));
 }
 
 void PolicyToolUIHandler::OnJavascriptDisallowed() {
@@ -165,6 +176,8 @@
     // TODO(urusant): convert the policy values so that the types are
     // consistent with actual policy types.
     CallJavascriptFunction("policy.Page.setPolicyValues", *value);
+    CallJavascriptFunction("policy.Page.setSessionTitle",
+                           base::Value(session_name_));
     base::PostTaskWithTraitsAndReplyWithResult(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
         base::BindOnce(&PolicyToolUIHandler::GetSessionsList,
@@ -215,6 +228,79 @@
   ImportFile();
 }
 
+PolicyToolUIHandler::SessionErrors PolicyToolUIHandler::DoRenameSession(
+    const base::FilePath::StringType& old_session_name,
+    const base::FilePath::StringType& new_session_name) {
+  const base::FilePath old_session_path = GetSessionPath(old_session_name);
+  const base::FilePath new_session_path = GetSessionPath(new_session_name);
+
+  // Check if the session files exist. If |old_session_name| doesn't exist, it
+  // means that is not a valid session. If |new_session_name| exists, it means
+  // that we can't do the rename because that will cause a file overwrite.
+  if (!PathExists(old_session_path))
+    return SessionErrors::kSessionNameNotExist;
+  if (PathExists(new_session_path))
+    return SessionErrors::kSessionNameExist;
+  if (!base::Move(old_session_path, new_session_path))
+    return SessionErrors::kRenamedSessionError;
+  return SessionErrors::kNone;
+}
+
+void PolicyToolUIHandler::OnSessionRenamed(
+    PolicyToolUIHandler::SessionErrors result) {
+  if (result == SessionErrors::kNone) {
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+        base::BindOnce(&PolicyToolUIHandler::GetSessionsList,
+                       base::Unretained(this)),
+        base::BindOnce(&PolicyToolUIHandler::OnSessionsListReceived,
+                       callback_weak_ptr_factory_.GetWeakPtr()));
+    CallJavascriptFunction("policy.Page.closeRenameSessionDialog");
+    return;
+  }
+  int error_message_id;
+  if (result == SessionErrors::kSessionNameNotExist) {
+    error_message_id = IDS_POLICY_TOOL_SESSION_NOT_EXIST;
+  } else if (result == SessionErrors::kSessionNameExist) {
+    error_message_id = IDS_POLICY_TOOL_SESSION_EXIST;
+  } else {
+    error_message_id = IDS_POLICY_TOOL_RENAME_FAILED;
+  }
+
+  CallJavascriptFunction(
+      "policy.Page.showRenameSessionError",
+      base::Value(l10n_util::GetStringUTF16(error_message_id)));
+}
+
+void PolicyToolUIHandler::HandleRenameSession(const base::ListValue* args) {
+  DCHECK_EQ(2U, args->GetSize());
+  base::FilePath::StringType old_session_name, new_session_name;
+  old_session_name =
+      base::FilePath::FromUTF8Unsafe(args->GetList()[0].GetString()).value();
+  new_session_name =
+      base::FilePath::FromUTF8Unsafe(args->GetList()[1].GetString()).value();
+
+  if (!IsValidSessionName(new_session_name) ||
+      !IsValidSessionName(old_session_name)) {
+    CallJavascriptFunction("policy.Page.showRenameSessionError",
+                           base::Value(l10n_util::GetStringUTF16(
+                               IDS_POLICY_TOOL_INVALID_SESSION_NAME)));
+    return;
+  }
+
+  // This is important in case the user renames the current active session.
+  // If we don't clear the current session name, after the rename, a new file
+  // will be created with the old name and with an empty dictionary in it.
+  session_name_.clear();
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+      base::BindOnce(&PolicyToolUIHandler::DoRenameSession,
+                     base::Unretained(this), old_session_name,
+                     new_session_name),
+      base::BindOnce(&PolicyToolUIHandler::OnSessionRenamed,
+                     callback_weak_ptr_factory_.GetWeakPtr()));
+}
+
 bool PolicyToolUIHandler::DoUpdateSession(const std::string& contents) {
   // Sanity check that contents is not too big. Otherwise, passing it to
   // WriteFile will be int overflow.
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.h b/chrome/browser/ui/webui/policy_tool_ui_handler.h
index c520df0a..8ea81955 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_handler.h
+++ b/chrome/browser/ui/webui/policy_tool_ui_handler.h
@@ -20,6 +20,14 @@
  private:
   friend class PolicyToolUITest;
 
+  enum class SessionErrors {
+    kNone = 0,
+    kInvalidSessionName,
+    kSessionNameExist,
+    kSessionNameNotExist,
+    kRenamedSessionError,
+  };
+
   static const base::FilePath::CharType kPolicyToolSessionsDir[];
   static const base::FilePath::CharType kPolicyToolDefaultSessionName[];
   static const base::FilePath::CharType kPolicyToolSessionExtension[];
@@ -28,9 +36,16 @@
   void ImportFile();
 
   void HandleInitializedAdmin(const base::ListValue* args);
+
   void HandleLoadSession(const base::ListValue* args);
+
+  // Rename a session if the new session name doesn't exist.
+  void HandleRenameSession(const base::ListValue* args);
+
   void HandleUpdateSession(const base::ListValue* args);
+
   void HandleResetSession(const base::ListValue* args);
+
   void HandleDeleteSession(const base::ListValue* args);
 
   void OnSessionDeleted(bool is_successful);
@@ -38,7 +53,14 @@
   std::string ReadOrCreateFileCallback();
   void OnFileRead(const std::string& contents);
 
+  SessionErrors DoRenameSession(
+      const base::FilePath::StringType& old_session_name,
+      const base::FilePath::StringType& new_session_name);
+
+  void OnSessionRenamed(SessionErrors result);
+
   bool DoUpdateSession(const std::string& contents);
+
   void OnSessionUpdated(bool is_successful);
 
   bool IsValidSessionName(const base::FilePath::StringType& name) const;
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
index 707c0a05..c470c3b 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -65,14 +65,21 @@
   DCHECK(delegate_);
   DCHECK(signin::IsDicePrepareMigrationEnabled());
   DCHECK(profile_);
-  DCHECK(!account_info_.gaia.empty());
-  DCHECK(!account_info_.email.empty());
   // Should not start syncing if the profile is already authenticated
   DCHECK(!signin_manager_->IsAuthenticated());
 
   // Force sign-in uses the modal sign-in flow.
   DCHECK(!signin_util::IsForceSigninEnabled());
 
+  if (account_info_.gaia.empty() || account_info_.email.empty()) {
+    LOG(ERROR) << "Cannot turn Sync On for invalid account.";
+    base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+    return;
+  }
+
+  DCHECK(!account_info_.gaia.empty());
+  DCHECK(!account_info_.email.empty());
+
   if (HasCanOfferSigninError()) {
     // Do not self-destruct synchronously in the constructor.
     base::SequencedTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
index 6641331..338f75e 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
@@ -113,6 +113,8 @@
   void SyncStartupFailed() override;
 
  private:
+  friend class base::DeleteHelper<DiceTurnSyncOnHelper>;
+
   enum class ProfileMode {
     // Attempts to sign the user in |profile_|. Note that if the account to be
     // signed in is a managed account, then a profile confirmation dialog is
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
index ec518a4..127f4ef 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -235,6 +235,8 @@
     token_service_->UpdateCredentials(account_id_, "enterprise_refresh_token");
   }
 
+  void UseInvalidAccount() { account_id_ = "invalid_account"; }
+
   void SetExpectationsForSyncStartupCompleted() {
     browser_sync::ProfileSyncServiceMock* sync_service_mock =
         GetProfileSyncServiceMock();
@@ -431,6 +433,15 @@
   test_fixture_->OnShowSigninPageInNewProfile(new_profile, username);
 }
 
+// Check that the invalid account is supported.
+TEST_F(DiceTurnSyncOnHelperTest, InvalidAccount) {
+  UseInvalidAccount();
+  CreateDiceTurnOnSyncHelper(
+      DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT);
+  base::RunLoop().RunUntilIdle();
+  CheckDelegateCalls();
+}
+
 // Tests that the login error is displayed and that the account is kept.
 TEST_F(DiceTurnSyncOnHelperTest, CanOfferSigninErrorKeepAccount) {
   // Set expectations.
diff --git a/chrome/browser/update_client/chrome_update_query_params_delegate.cc b/chrome/browser/update_client/chrome_update_query_params_delegate.cc
index 0475535..1712095b 100644
--- a/chrome/browser/update_client/chrome_update_query_params_delegate.cc
+++ b/chrome/browser/update_client/chrome_update_query_params_delegate.cc
@@ -13,7 +13,7 @@
 namespace {
 
 base::LazyInstance<ChromeUpdateQueryParamsDelegate>::DestructorAtExit
-    g_delegate = LAZY_INSTANCE_INITIALIZER;
+    g_chrome_update_query_params_delegate = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
@@ -26,7 +26,7 @@
 // static
 ChromeUpdateQueryParamsDelegate*
 ChromeUpdateQueryParamsDelegate::GetInstance() {
-  return g_delegate.Pointer();
+  return g_chrome_update_query_params_delegate.Pointer();
 }
 
 std::string ChromeUpdateQueryParamsDelegate::GetExtraParams() {
diff --git a/chrome/browser/win/automation_controller.cc b/chrome/browser/win/automation_controller.cc
index 5797e85..80782657 100644
--- a/chrome/browser/win/automation_controller.cc
+++ b/chrome/browser/win/automation_controller.cc
@@ -16,10 +16,10 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/threading/thread_checker.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/win/scoped_variant.h"
 #include "chrome/browser/win/ui_automation_util.h"
 #include "ui/base/win/atl_module.h"
@@ -96,15 +96,16 @@
 
 }  // namespace
 
-// This class lives on the automation thread and is responsible for initializing
-// the UIAutomation library and installing the event observers.
+// This class lives in the automation sequence and is responsible for
+// initializing the UIAutomation library and installing the event observers.
 class AutomationController::Context {
  public:
-  // Returns a new instance ready for initialization and use on another thread.
+  // Returns a new instance ready for initialization and use in another
+  // sequence.
   static base::WeakPtr<Context> Create();
 
   // Deletes the instance.
-  void DeleteOnAutomationThread();
+  void DeleteInAutomationSequence();
 
   // Initializes the context, invoking the delegate's OnInitialized() method
   // when done. On success, the delegate's other On*() methods will be invoked
@@ -116,7 +117,7 @@
   class EventHandler;
 
   // The one and only method that may be called from outside of the automation
-  // thread.
+  // sequence.
   Context();
   ~Context();
 
@@ -136,7 +137,7 @@
   // Pointer to the delegate. Passed to event handlers.
   scoped_refptr<RefCountedDelegate> ref_counted_delegate_;
 
-  THREAD_CHECKER(thread_checker_);
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // The automation client.
   Microsoft::WRL::ComPtr<IUIAutomation> automation_;
@@ -250,15 +251,15 @@
   return context->weak_ptr_factory_.GetWeakPtr();
 }
 
-void AutomationController::Context::DeleteOnAutomationThread() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+void AutomationController::Context::DeleteInAutomationSequence() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   delete this;
 }
 
 void AutomationController::Context::Initialize(
     std::unique_ptr<Delegate> delegate) {
-  // This and all other methods must be called on the automation thread.
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // This and all other methods must be called in the automation sequence.
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   ref_counted_delegate_ =
       base::MakeRefCounted<RefCountedDelegate>(std::move(delegate));
@@ -279,11 +280,11 @@
 }
 
 AutomationController::Context::Context() : weak_ptr_factory_(this) {
-  DETACH_FROM_THREAD(thread_checker_);
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 AutomationController::Context::~Context() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (event_handler_) {
     event_handler_.Reset();
     automation_->RemoveAllEventHandlers();
@@ -292,7 +293,7 @@
 
 Microsoft::WRL::ComPtr<IUnknown>
 AutomationController::Context::GetEventHandler() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!event_handler_) {
     ATL::CComObject<EventHandler>* obj = nullptr;
     HRESULT result = ATL::CComObject<EventHandler>::CreateInstance(&obj);
@@ -306,7 +307,7 @@
 
 Microsoft::WRL::ComPtr<IUIAutomationEventHandler>
 AutomationController::Context::GetAutomationEventHandler() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Microsoft::WRL::ComPtr<IUIAutomationEventHandler> handler;
   GetEventHandler().CopyTo(handler.GetAddressOf());
   return handler;
@@ -314,14 +315,14 @@
 
 Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler>
 AutomationController::Context::GetFocusChangedEventHandler() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler> handler;
   GetEventHandler().CopyTo(handler.GetAddressOf());
   return handler;
 }
 
 HRESULT AutomationController::Context::InstallObservers() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(automation_);
 
   // Create a cache request so that elements received by way of events contain
@@ -354,25 +355,28 @@
 
 // AutomationController --------------------------------------------------------
 
-AutomationController::AutomationController(std::unique_ptr<Delegate> delegate)
-    : automation_thread_("AutomationControllerThread") {
+AutomationController::AutomationController(std::unique_ptr<Delegate> delegate) {
   ui::win::CreateATLModuleIfNeeded();
-  // Start the automation thread and initialize the automation client on it.
+
+  // Create the task runner on which the automation client lives.
+  automation_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+      {base::TaskPriority::USER_VISIBLE,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
+
+  // Initialize the context on the automation task runner.
   context_ = Context::Create();
-  automation_thread_.init_com_with_mta(true);
-  automation_thread_.Start();
-  automation_thread_.task_runner()->PostTask(
+  automation_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&AutomationController::Context::Initialize,
                                 context_, std::move(delegate)));
 }
 
 AutomationController::~AutomationController() {
   // context_ is still valid when the caller destroys the instance before the
-  // callback(s) have fired. In this case, delete the context on the automation
-  // thread before joining with it. DeleteSoon is not used because the monitor
-  // has only a WeakPtr to the context that is bound to the automation thread.
-  automation_thread_.task_runner()->PostTask(
+  // callback(s) have fired. In this case, delete the context in the automation
+  // sequence before joining with it. DeleteSoon is not used because the monitor
+  // has only a WeakPtr to the context that is bound to the automation sequence.
+  automation_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&AutomationController::Context::DeleteOnAutomationThread,
+      base::BindOnce(&AutomationController::Context::DeleteInAutomationSequence,
                      context_));
 }
diff --git a/chrome/browser/win/automation_controller.h b/chrome/browser/win/automation_controller.h
index d3c37ca..d9c16596 100644
--- a/chrome/browser/win/automation_controller.h
+++ b/chrome/browser/win/automation_controller.h
@@ -13,8 +13,9 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread.h"
+#include "base/sequenced_task_runner.h"
 
 // This is a helper class to facilitate the usage of the UI Automation API in
 // the Chrome codebase. It takes care of initializing the Automation context and
@@ -27,11 +28,11 @@
 // outside of the Task Scheduler's control.
 class AutomationController {
  public:
-  // The delegate is passed to the automation thread and the event handlers,
+  // The delegate is passed to the automation sequence and the event handlers,
   // which runs in the context of a MTA.
   //
   // The call order is as follows:
-  // - OnInitialized() is invoked on the automation thread.
+  // - OnInitialized() is invoked in the automation sequence.
   // If initialization succeeds:
   // - ConfigureCacheRequest() is invoked once per type of event.
   // - OnAutomationEvent() and OnFocusChangedEvent() are invoked as events
@@ -52,20 +53,20 @@
 
     // Used to configure the event handlers so that the event sender element has
     // the required properties cached.
-    // Runs on the context thread.
+    // Runs in the automation sequence.
     virtual void ConfigureCacheRequest(
         IUIAutomationCacheRequest* cache_request) const = 0;
 
     // Invoked when an automation event happens.
-    // This can be invoked on any thread in the automation MTA and so |this|
-    // should be accessed carefully.
+    // This can be invoked on any MTA thread in the process and so |this| should
+    // be accessed carefully.
     virtual void OnAutomationEvent(IUIAutomation* automation,
                                    IUIAutomationElement* sender,
                                    EVENTID event_id) const = 0;
 
     // Invoked when a focus changed event happens.
-    // This can be invoked on any thread in the automation MTA and so |this|
-    // should be accessed carefully.
+    // This can be invoked on any MTA thread in the process and so |this| should
+    // be accessed carefully.
     virtual void OnFocusChangedEvent(IUIAutomation* automation,
                                      IUIAutomationElement* sender) const = 0;
   };
@@ -76,10 +77,10 @@
  private:
   class Context;
 
-  // A thread in the COM MTA in which automation calls are made.
-  base::Thread automation_thread_;
+  // The sequence in which automation calls are made.
+  scoped_refptr<base::SequencedTaskRunner> automation_task_runner_;
 
-  // A pointer to the context object that lives on the automation thread.
+  // A pointer to the context object that lives in the automation sequence.
   base::WeakPtr<Context> context_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationController);
diff --git a/chrome/services/file_util/BUILD.gn b/chrome/services/file_util/BUILD.gn
index bced96a..4f117a49 100644
--- a/chrome/services/file_util/BUILD.gn
+++ b/chrome/services/file_util/BUILD.gn
@@ -28,7 +28,7 @@
       "zip_file_creator.h",
     ]
 
-    deps += [ "//components/filesystem/public/interfaces" ]
+    deps += [ "//components/services/filesystem/public/interfaces" ]
   }
 
   if (safe_browsing_mode == 1) {
diff --git a/chrome/services/file_util/DEPS b/chrome/services/file_util/DEPS
index bde581c..e480585 100644
--- a/chrome/services/file_util/DEPS
+++ b/chrome/services/file_util/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-  "+components/filesystem",
+  "+components/services/filesystem",
   "+chrome/utility/safe_browsing",
   "+third_party/zlib/google",
 ]
diff --git a/chrome/services/file_util/public/cpp/zip_file_creator.cc b/chrome/services/file_util/public/cpp/zip_file_creator.cc
index ca8202b..754ff57 100644
--- a/chrome/services/file_util/public/cpp/zip_file_creator.cc
+++ b/chrome/services/file_util/public/cpp/zip_file_creator.cc
@@ -10,8 +10,8 @@
 #include "base/callback_helpers.h"
 #include "base/task_scheduler/post_task.h"
 #include "chrome/services/file_util/public/mojom/constants.mojom.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/lock_table.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/connector.h"
diff --git a/chrome/services/file_util/public/mojom/BUILD.gn b/chrome/services/file_util/public/mojom/BUILD.gn
index 28d78b2..0ed19564 100644
--- a/chrome/services/file_util/public/mojom/BUILD.gn
+++ b/chrome/services/file_util/public/mojom/BUILD.gn
@@ -20,6 +20,6 @@
 
   if (is_chromeos) {
     sources += [ "zip_file_creator.mojom" ]
-    public_deps += [ "//components/filesystem/public/interfaces" ]
+    public_deps += [ "//components/services/filesystem/public/interfaces" ]
   }
 }
diff --git a/chrome/services/file_util/public/mojom/zip_file_creator.mojom b/chrome/services/file_util/public/mojom/zip_file_creator.mojom
index 0bf85f9d..fae0034 100644
--- a/chrome/services/file_util/public/mojom/zip_file_creator.mojom
+++ b/chrome/services/file_util/public/mojom/zip_file_creator.mojom
@@ -7,7 +7,7 @@
 
 module chrome.mojom;
 
-import "components/filesystem/public/interfaces/directory.mojom";
+import "components/services/filesystem/public/interfaces/directory.mojom";
 import "mojo/common/file.mojom";
 import "mojo/common/file_path.mojom";
 
diff --git a/chrome/services/file_util/zip_file_creator.cc b/chrome/services/file_util/zip_file_creator.cc
index f026e1f..81933d5 100644
--- a/chrome/services/file_util/zip_file_creator.cc
+++ b/chrome/services/file_util/zip_file_creator.cc
@@ -9,7 +9,7 @@
 
 #include "base/files/file.h"
 #include "base/files/file_path.h"
-#include "components/filesystem/public/interfaces/types.mojom-shared.h"
+#include "components/services/filesystem/public/interfaces/types.mojom-shared.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "third_party/zlib/google/zip.h"
 
diff --git a/chrome/services/file_util/zip_file_creator.h b/chrome/services/file_util/zip_file_creator.h
index febd8dcb3..f772f668 100644
--- a/chrome/services/file_util/zip_file_creator.h
+++ b/chrome/services/file_util/zip_file_creator.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "chrome/services/file_util/public/mojom/zip_file_creator.mojom.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "services/service_manager/public/cpp/service_context_ref.h"
 
 namespace base {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index fbd11cd9..770e6330 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1224,6 +1224,7 @@
         "../browser/extensions/content_script_apitest.cc",
         "../browser/extensions/content_security_policy_apitest.cc",
         "../browser/extensions/content_verifier_browsertest.cc",
+        "../browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc",
         "../browser/extensions/cross_origin_xhr_apitest.cc",
         "../browser/extensions/crx_installer_browsertest.cc",
         "../browser/extensions/docs/examples/apps/calculator_browsertest.cc",
@@ -1961,7 +1962,7 @@
     if (enable_library_cdms) {
       # Runtime dependencies.
       data_deps += [
-        "//media/cdm/library_cdm:clearkeycdmadapter",
+        "//media/cdm/library_cdm/clear_key_cdm",
         "//third_party/widevine/cdm:widevinecdmadapter",
       ]
     }
@@ -5432,7 +5433,7 @@
     if (enable_library_cdms) {
       deps += [ "//media/cdm:cdm_paths" ]
       data_deps = [
-        "//media/cdm/library_cdm:clearkeycdmadapter",
+        "//media/cdm/library_cdm/clear_key_cdm",
         "//third_party/widevine/cdm:widevinecdmadapter",
       ]
     }
diff --git a/chrome/test/data/extensions/content_verifier/has_default_resource.crx b/chrome/test/data/extensions/content_verifier/has_default_resource.crx
new file mode 100644
index 0000000..68a5591
--- /dev/null
+++ b/chrome/test/data/extensions/content_verifier/has_default_resource.crx
Binary files differ
diff --git a/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO b/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO
new file mode 100644
index 0000000..28e7ec24
--- /dev/null
+++ b/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO
@@ -0,0 +1,9 @@
+Information about has_default_resource.crx:
+
+A test extension downloaded from webstore.
+extension_id: bbmokfifpjdhnmacojglcoihoagfmcll
+It has background.js as background script. On ExtensionLoad, the extension will
+trigger this resource load.
+There are two other resources inside the extension:
+  - page.html
+  - script.js
diff --git a/chrome/test/data/extensions/content_verifier/no_default_resources.crx b/chrome/test/data/extensions/content_verifier/no_default_resources.crx
new file mode 100644
index 0000000..5a80e02
--- /dev/null
+++ b/chrome/test/data/extensions/content_verifier/no_default_resources.crx
Binary files differ
diff --git a/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO b/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO
new file mode 100644
index 0000000..d8b9a1157d
--- /dev/null
+++ b/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO
@@ -0,0 +1,9 @@
+Information about no_default_resources.crx:
+
+A test extension downloaded from webstore.
+extension_id: lpibhlnkgcbcgdjlaacppnkmmlfpapij
+The extension doesn't have any resource that will be loaded by default on
+ExtensionLoad.
+There are two resources inside the extension:
+  - page.html
+  - script.js
diff --git a/chrome/tools/build/chromeos/FILES.cfg b/chrome/tools/build/chromeos/FILES.cfg
index 7f936fa..891bb23 100644
--- a/chrome/tools/build/chromeos/FILES.cfg
+++ b/chrome/tools/build/chromeos/FILES.cfg
@@ -82,10 +82,6 @@
   },
   # CDM files (each has an adapter and the actual CDM):
   {
-    'filename': 'libclearkeycdmadapter.so',
-    'buildtype': ['dev', 'official'],
-  },
-  {
     'filename': 'libclearkeycdm.so',
     'buildtype': ['dev', 'official'],
   },
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg
index 3a5d6186..afd951a 100644
--- a/chrome/tools/build/linux/FILES.cfg
+++ b/chrome/tools/build/linux/FILES.cfg
@@ -93,10 +93,6 @@
   },
   # CDM files (each has an adapter and the actual CDM):
   {
-    'filename': 'libclearkeycdmadapter.so',
-    'buildtype': ['dev', 'official'],
-  },
-  {
     'filename': 'libclearkeycdm.so',
     'buildtype': ['dev', 'official'],
   },
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc
index 32712b0..17d0af4 100644
--- a/chromecast/browser/extensions/cast_extension_system.cc
+++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -26,6 +26,7 @@
 #include "extensions/browser/renderer_startup_helper.h"
 #include "extensions/browser/runtime_data.h"
 #include "extensions/browser/service_worker_manager.h"
+#include "extensions/browser/shared_user_script_master.h"
 #include "extensions/browser/value_store/value_store_factory_impl.h"
 #include "extensions/common/api/app_runtime.h"
 #include "extensions/common/constants.h"
@@ -193,6 +194,9 @@
   app_sorting_ = std::make_unique<NullAppSorting>();
 
   RendererStartupHelperFactory::GetForBrowserContext(browser_context_);
+
+  shared_user_script_master_ =
+      std::make_unique<SharedUserScriptMaster>(browser_context_);
 }
 
 void CastExtensionSystem::InitForIncognitoProfile() {
@@ -216,7 +220,7 @@
 }
 
 SharedUserScriptMaster* CastExtensionSystem::shared_user_script_master() {
-  return nullptr;
+  return shared_user_script_master_.get();
 }
 
 StateStore* CastExtensionSystem::state_store() {
diff --git a/chromecast/browser/extensions/cast_extension_system.h b/chromecast/browser/extensions/cast_extension_system.h
index 66e0ce2..3026c14 100644
--- a/chromecast/browser/extensions/cast_extension_system.h
+++ b/chromecast/browser/extensions/cast_extension_system.h
@@ -97,6 +97,7 @@
   std::unique_ptr<RuntimeData> runtime_data_;
   std::unique_ptr<QuotaService> quota_service_;
   std::unique_ptr<AppSorting> app_sorting_;
+  std::unique_ptr<SharedUserScriptMaster> shared_user_script_master_;
 
   scoped_refptr<ValueStoreFactory> store_factory_;
 
diff --git a/chromecast/common/cast_extensions_client.cc b/chromecast/common/cast_extensions_client.cc
index 82220380..ee7627f 100644
--- a/chromecast/common/cast_extensions_client.cc
+++ b/chromecast/common/cast_extensions_client.cc
@@ -20,6 +20,7 @@
 #include "extensions/common/features/manifest_feature.h"
 #include "extensions/common/features/simple_feature.h"
 #include "extensions/common/manifest_handler.h"
+#include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/permissions/permission_message_provider.h"
 #include "extensions/common/permissions/permissions_info.h"
 #include "extensions/common/permissions/permissions_provider.h"
@@ -36,6 +37,11 @@
 
 namespace {
 
+void RegisterCastManifestHandlers() {
+  DCHECK(!ManifestHandler::IsRegistrationFinalized());
+  (new ContentScriptsHandler)->Register();
+}
+
 // TODO(jamescook): Refactor ChromePermissionsMessageProvider so we can share
 // code. For now, this implementation does nothing.
 class ShellPermissionMessageProvider : public PermissionMessageProvider {
@@ -81,6 +87,7 @@
 
 void CastExtensionsClient::Initialize() {
   RegisterCommonManifestHandlers();
+  RegisterCastManifestHandlers();
   ManifestHandler::FinalizeRegistration();
   // TODO(jamescook): Do we need to whitelist any extensions?
 
@@ -114,6 +121,14 @@
     feature->set_channel(version_info::Channel::STABLE);
     feature->set_extension_types({extensions::Manifest::TYPE_PLATFORM_APP});
     provider->AddFeature("cast_url", feature);
+
+    feature = new extensions::ManifestFeature();
+    feature->set_name("content_scripts");
+    feature->set_channel(version_info::Channel::STABLE);
+    feature->set_extension_types(
+        {extensions::Manifest::TYPE_EXTENSION,
+         extensions::Manifest::TYPE_LEGACY_PACKAGED_APP});
+    provider->AddFeature("content_scripts", feature);
   } else if (name == "permission") {
     provider = std::make_unique<ShellPermissionFeatureProvider>();
   } else if (name == "behavior") {
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index c67de27..65c058bc 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -860,9 +860,10 @@
     else {
       FormData form;
       FormFieldData field;
-      if (form_util::FindFormAndFieldForFormControlElement(element, &form,
-                                                           &field)) {
-        GetAutofillDriver()->SelectControlDidChange(
+      const mojom::AutofillDriverPtr& driver = GetAutofillDriver();
+      if (driver && form_util::FindFormAndFieldForFormControlElement(
+                        element, &form, &field)) {
+        driver->SelectControlDidChange(
             form, field,
             render_frame()->GetRenderView()->ElementBoundsInWindow(element));
       }
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc
index 0b48cff..d989cf6 100644
--- a/components/autofill/core/browser/autofill_experiments.cc
+++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -222,6 +222,17 @@
     return false;
   }
 
+  // Check if sync is not in a permanent error state.
+  syncer::SyncService::SyncTokenStatus token_status =
+      sync_service->GetSyncTokenStatus();
+  if ((token_status.connection_status ==
+           syncer::ConnectionStatus::CONNECTION_AUTH_ERROR ||
+       token_status.connection_status ==
+           syncer::ConnectionStatus::CONNECTION_SERVER_ERROR) &&
+      token_status.last_get_token_error.IsPersistentError()) {
+    return false;
+  }
+
   // Users who have enabled a passphrase have chosen to not make their sync
   // information accessible to Google. Since upload makes credit card data
   // available to other Google systems, disable it for passphrase users.
diff --git a/components/autofill/core/browser/autofill_experiments_unittest.cc b/components/autofill/core/browser/autofill_experiments_unittest.cc
index ef45b490..bcba1a3 100644
--- a/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -53,11 +53,28 @@
     is_using_secondary_passphrase_ = is_using_secondary_passphrase;
   }
 
+  syncer::SyncService::SyncTokenStatus GetSyncTokenStatus() const override {
+    syncer::SyncService::SyncTokenStatus token;
+
+    if (is_in_auth_error_) {
+      token.connection_status = syncer::ConnectionStatus::CONNECTION_AUTH_ERROR;
+      token.last_get_token_error =
+          GoogleServiceAuthError::FromServiceError("error");
+    }
+
+    return token;
+  }
+
+  void SetInAuthError(bool is_in_auth_error) {
+    is_in_auth_error_ = is_in_auth_error;
+  }
+
  private:
   bool can_sync_start_;
   syncer::ModelTypeSet preferred_data_types_;
   bool is_engine_initialized_;
   bool is_using_secondary_passphrase_;
+  bool is_in_auth_error_ = false;
 };
 
 }  // namespace
@@ -100,6 +117,11 @@
   EXPECT_FALSE(IsCreditCardUploadEnabled());
 }
 
+TEST_F(AutofillExperimentsTest, DenyUpload_AuthError) {
+  sync_service_.SetInAuthError(true);
+  EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
 TEST_F(AutofillExperimentsTest,
        DenyUpload_SyncServiceDoesNotHaveAutofillProfilePreferredDataType) {
   sync_service_.SetPreferredDataTypes(syncer::ModelTypeSet());
diff --git a/components/browser_watcher/postmortem_report_collector.cc b/components/browser_watcher/postmortem_report_collector.cc
index 1155c054..3b83a79 100644
--- a/components/browser_watcher/postmortem_report_collector.cc
+++ b/components/browser_watcher/postmortem_report_collector.cc
@@ -224,19 +224,17 @@
   DCHECK(report_proto);
 
   // Prepare a crashpad report.
-  CrashReportDatabase::NewReport* new_report = nullptr;
+  std::unique_ptr<CrashReportDatabase::NewReport> new_report;
   CrashReportDatabase::OperationStatus database_status =
       report_database_->PrepareNewCrashReport(&new_report);
   if (database_status != CrashReportDatabase::kNoError) {
     LogCollectionStatus(PREPARE_NEW_CRASH_REPORT_FAILED);
     return;
   }
-  CrashReportDatabase::CallErrorWritingCrashReport
-      call_error_writing_crash_report(report_database_, new_report);
 
   // Write the report to a minidump.
-  if (!WriteReportToMinidump(report_proto, client_id, new_report->uuid,
-                             reinterpret_cast<FILE*>(new_report->handle))) {
+  if (!WriteReportToMinidump(report_proto, client_id, new_report->ReportID(),
+                             new_report->Writer())) {
     LogCollectionStatus(WRITE_TO_MINIDUMP_FAILED);
     return;
   }
@@ -244,10 +242,9 @@
   // Finalize the report wrt the report database. Note that this doesn't trigger
   // an immediate upload, but Crashpad will eventually upload the report (as of
   // writing, the delay is on the order of up to 15 minutes).
-  call_error_writing_crash_report.Disarm();
   crashpad::UUID unused_report_id;
   database_status = report_database_->FinishedWritingCrashReport(
-      new_report, &unused_report_id);
+      std::move(new_report), &unused_report_id);
   if (database_status != CrashReportDatabase::kNoError) {
     LogCollectionStatus(FINISHED_WRITING_CRASH_REPORT_FAILED);
     return;
@@ -260,11 +257,9 @@
     StabilityReport* report,
     const crashpad::UUID& client_id,
     const crashpad::UUID& report_id,
-    base::PlatformFile minidump_file) {
+    crashpad::FileWriterInterface* minidump_file) {
   DCHECK(report);
-
-  crashpad::WeakFileHandleFileWriter writer(minidump_file);
-  return WritePostmortemDump(&writer, client_id, report_id, report);
+  return WritePostmortemDump(minidump_file, client_id, report_id, report);
 }
 
 }  // namespace browser_watcher
diff --git a/components/browser_watcher/postmortem_report_collector.h b/components/browser_watcher/postmortem_report_collector.h
index 367250a..c01d0aa 100644
--- a/components/browser_watcher/postmortem_report_collector.h
+++ b/components/browser_watcher/postmortem_report_collector.h
@@ -16,7 +16,6 @@
 #include <vector>
 
 #include "base/debug/activity_analyzer.h"
-#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -25,6 +24,7 @@
 #include "components/browser_watcher/stability_report_extractor.h"
 #include "components/metrics/system_session_analyzer_win.h"
 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
+#include "third_party/crashpad/crashpad/util/file/file_writer.h"
 
 namespace browser_watcher {
 
@@ -94,10 +94,11 @@
   void GenerateCrashReport(const crashpad::UUID& client_id,
                            StabilityReport* report_proto);
 
-  virtual bool WriteReportToMinidump(StabilityReport* report,
-                                     const crashpad::UUID& client_id,
-                                     const crashpad::UUID& report_id,
-                                     base::PlatformFile minidump_file);
+  virtual bool WriteReportToMinidump(
+      StabilityReport* report,
+      const crashpad::UUID& client_id,
+      const crashpad::UUID& report_id,
+      crashpad::FileWriterInterface* minidump_file);
 
   std::string product_name_;
   std::string version_number_;
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc
index eb4a103..fdb11f6c 100644
--- a/components/browser_watcher/postmortem_report_collector_unittest.cc
+++ b/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -75,7 +75,7 @@
                bool(StabilityReport* report,
                     const crashpad::UUID& client_id,
                     const crashpad::UUID& report_id,
-                    base::PlatformFile minidump_file));
+                    crashpad::FileWriterInterface* minidump_file));
 };
 
 class MockSystemSessionAnalyzer : public metrics::SystemSessionAnalyzer {
diff --git a/components/crash/content/app/minidump_with_crashpad_info.cc b/components/crash/content/app/minidump_with_crashpad_info.cc
index a6ee276..cd9726b 100644
--- a/components/crash/content/app/minidump_with_crashpad_info.cc
+++ b/components/crash/content/app/minidump_with_crashpad_info.cc
@@ -279,9 +279,9 @@
 
 // Appends the full contents of |source| to |dest| from the current position
 // of |dest|.
-bool AppendFileContents(base::File* source, base::PlatformFile dest) {
+bool AppendFileContents(base::File* source, crashpad::FileWriter* dest) {
   DCHECK(source && source->IsValid());
-  DCHECK_NE(base::kInvalidPlatformFile, dest);
+  DCHECK(dest);
 
   // Rewind the source.
   if (source->Seek(base::File::FROM_BEGIN, 0) == -1)
@@ -292,16 +292,12 @@
   while (true) {
     int bytes_read =
         source->ReadAtCurrentPos(&buf[0], static_cast<int>(buf.size()));
-    if (bytes_read == -1)
+    if (bytes_read < 0)
       return false;
     if (bytes_read == 0)
       break;
 
-    DWORD bytes_written = 0;
-    // Due to handle instrumentation, the destination can't be wrapped in
-    // a base::File, so we go basic Win32 API here.
-    if (!WriteFile(dest, &buf[0], bytes_read, &bytes_written, nullptr) ||
-        static_cast<int>(bytes_written) != bytes_read) {
+    if (!dest->Write(&buf[0], static_cast<size_t>(bytes_read))) {
       return false;
     }
   }
@@ -323,16 +319,12 @@
   if (!database)
     return false;
 
-  crashpad::CrashReportDatabase::NewReport* report = nullptr;
+  std::unique_ptr<crashpad::CrashReportDatabase::NewReport> report;
   crashpad::CrashReportDatabase::OperationStatus status =
       database->PrepareNewCrashReport(&report);
   if (status != crashpad::CrashReportDatabase::kNoError)
     return false;
 
-  // Make sure we release the report on early exit.
-  crashpad::CrashReportDatabase::CallErrorWritingCrashReport on_error(
-      database.get(), report);
-
   crashpad::UUID client_id;
   crashpad::Settings* settings = database->GetSettings();
   if (settings) {
@@ -357,16 +349,14 @@
   // Write the minidump to the temp file, and then copy the data to the
   // Crashpad-provided handle, as the latter is only open for write.
   if (!MiniDumpWriteDumpWithCrashpadInfo(process, minidump_type, exc_info,
-                                         crash_keys, client_id, report->uuid,
-                                         &dump_file) ||
-      !AppendFileContents(&dump_file, report->handle)) {
+                                         crash_keys, client_id,
+                                         report->ReportID(), &dump_file) ||
+      !AppendFileContents(&dump_file, report->Writer())) {
     return false;
   }
 
-  on_error.Disarm();
-
   crashpad::UUID report_id = {};
-  status = database->FinishedWritingCrashReport(report, &report_id);
+  status = database->FinishedWritingCrashReport(std::move(report), &report_id);
   if (status != crashpad::CrashReportDatabase::kNoError)
     return false;
 
diff --git a/components/crash/core/common/BUILD.gn b/components/crash/core/common/BUILD.gn
index 4f67529f..c8e02ebf 100644
--- a/components/crash/core/common/BUILD.gn
+++ b/components/crash/core/common/BUILD.gn
@@ -2,6 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
+
+declare_args() {
+  # If set to true, this will stub out and disable the entire crash key system.
+  use_crash_key_stubs = is_fuchsia
+}
+
 group("common") {
   public_deps = [
     ":crash_key",
@@ -13,15 +20,22 @@
   }
 }
 
-use_crashpad = is_mac || is_win
-use_stubs = is_fuchsia
+use_crashpad_annotation = (is_mac || is_win) && !use_crash_key_stubs
+
+buildflag_header("crash_buildflags") {
+  header = "crash_buildflags.h"
+  flags = [
+    "USE_CRASHPAD_ANNOTATION=$use_crashpad_annotation",
+    "USE_CRASH_KEY_STUBS=$use_crash_key_stubs",
+  ]
+}
 
 # Crashpad's annotation system can store data on a per-module basis (i.e.,
 # in different shared libraries in the component build) without issue. The
 # Breakpad implementation uses a static global variable, so ensure there is
 # only one instance of the symbol in the component build by making this
 # target a component.
-if (use_stubs || use_crashpad) {
+if (use_crash_key_stubs || use_crashpad_annotation) {
   crash_key_target_type = "static_library"
 } else {
   crash_key_target_type = "component"
@@ -51,14 +65,15 @@
   }
 
   deps = [
+    ":crash_buildflags",
     "//base",
   ]
 
-  if (use_crashpad) {
+  if (use_crash_key_stubs) {
+    sources += [ "crash_key_stubs.cc" ]
+  } else if (use_crashpad_annotation) {
     sources += [ "crash_key_crashpad.cc" ]
     deps += [ "//third_party/crashpad/crashpad/client" ]
-  } else if (use_stubs) {
-    sources += [ "crash_key_stubs.cc" ]
   } else {
     include_dirs = [ "//third_party/breakpad/breakpad/src" ]
 
diff --git a/components/crash/core/common/crash_key.h b/components/crash/core/common/crash_key.h
index 951c7e9..b37987e 100644
--- a/components/crash/core/common/crash_key.h
+++ b/components/crash/core/common/crash_key.h
@@ -13,17 +13,14 @@
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 #include "build/build_config.h"
+#include "components/crash/core/common/crash_buildflags.h"
 #include "components/crash/core/common/crash_export.h"
 
 // The crash key interface exposed by this file is the same as the Crashpad
 // Annotation interface. Because not all platforms use Crashpad yet, a
 // source-compatible interface is provided on top of the older Breakpad
 // storage mechanism.
-#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
-#define USE_CRASHPAD_ANNOTATION 1
-#endif
-
-#if defined(USE_CRASHPAD_ANNOTATION)
+#if BUILDFLAG(USE_CRASHPAD_ANNOTATION)
 #include "third_party/crashpad/crashpad/client/annotation.h"
 #endif
 
@@ -61,7 +58,7 @@
 //      g_operation_id.Clear()
 //    }
 // \endcode
-#if defined(USE_CRASHPAD_ANNOTATION)
+#if BUILDFLAG(USE_CRASHPAD_ANNOTATION)
 
 template <crashpad::Annotation::ValueSizeType MaxLength>
 using CrashKeyString = crashpad::StringAnnotation<MaxLength>;
@@ -175,7 +172,7 @@
 //    }
 class ScopedCrashKeyString {
  public:
-#if defined(USE_CRASHPAD_ANNOTATION)
+#if BUILDFLAG(USE_CRASHPAD_ANNOTATION)
   using CrashKeyType = crashpad::Annotation;
 #else
   using CrashKeyType = internal::CrashKeyStringImpl;
@@ -229,6 +226,4 @@
 
 }  // namespace crash_reporter
 
-#undef USE_CRASHPAD_ANNOTATION
-
 #endif  // COMPONENTS_CRASH_CORE_COMMON_CRASH_KEY_H_
diff --git a/components/crash/core/common/crash_key_stubs.cc b/components/crash/core/common/crash_key_stubs.cc
index f978394..77fe36e7 100644
--- a/components/crash/core/common/crash_key_stubs.cc
+++ b/components/crash/core/common/crash_key_stubs.cc
@@ -8,8 +8,8 @@
 #include "build/build_config.h"
 #include "components/crash/core/common/crash_key.h"
 
-#if !defined(OS_FUCHSIA)
-#error "This file is only for OS_FUCHSIA."
+#if !BUILDFLAG(USE_CRASH_KEY_STUBS)
+#error "This file should only be compiled when using stubs."
 #endif
 
 namespace crash_reporter {
diff --git a/components/patch_service/BUILD.gn b/components/patch_service/BUILD.gn
index ff82f4b..29906df 100644
--- a/components/patch_service/BUILD.gn
+++ b/components/patch_service/BUILD.gn
@@ -15,7 +15,7 @@
 
   deps = [
     "//base",
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
     "//courgette:courgette_lib",
     "//mojo/public/cpp/bindings",
   ]
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 892f7be2..2a42008 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -31,7 +31,6 @@
 #   'main' - a boolean value
 #   'list' - a list of string values
 #   'dict' - a dictionary value, containing other values indexed by strings
-#     NOTE: This type is not supported yet. https://crbug.com/108992
 #   'external' - a policy that references external data.
 #     NOTE: This type is currently supported on Chrome OS only.
 #
@@ -175,11 +174,19 @@
 #   This setting applies to Chrome OS only. If the setting is missing, both
 #   types are assumed. The array must not be empty.
 #
-# Enterprise defaults:
+# Enterprise defaults for user policy:
 #   For managed users on Chrome OS (i.e. users receiving user policy from the
 #   cloud), if the optional key 'default_for_enterprise_users' is set, its value
 #   is applied as mandatory policy unless a different setting is received from
-#   the cloud.
+#   the cloud. This default value handling is automatically enforced by the
+#   policy stack when filling the PolicyMap (specifically, by the generated
+#   function SetEnterpriseUsersDefaults).
+#
+# Enterprise defaults for device policy:
+#   The optional key 'default_for_managed_devices_doc_only' can be used to
+#   document a differing default value for devices enrolled into enterprise
+#   management. This is for documentation only - the enrollment-dependent
+#   handling must be manually implemented.
 
   'risk_tag_definitions' : [
     # All following tags are ordered by severity of their impact.
@@ -8355,6 +8362,7 @@
         'dynamic_refresh': False,
       },
       'example_value': True,
+      'default_for_managed_devices_doc_only': False,
       'id': 219,
       'caption': '''Enable supervised users''',
       'tags': [],
@@ -11358,6 +11366,7 @@
         'dynamic_refresh': True,
       },
       'example_value': True,
+      'default_for_managed_devices_doc_only': False,
       'id': 421,
       'caption': '''Allow devices to run virtual machines on Chrome OS''',
       'tags': ['system-security'],
diff --git a/components/policy/tools/syntax_check_policy_template_json.py b/components/policy/tools/syntax_check_policy_template_json.py
index f6ae6479..02977e8 100755
--- a/components/policy/tools/syntax_check_policy_template_json.py
+++ b/components/policy/tools/syntax_check_policy_template_json.py
@@ -185,8 +185,9 @@
                      'supported_on', 'label', 'policies', 'items',
                      'example_value', 'features', 'deprecated', 'future',
                      'id', 'schema', 'max_size', 'tags',
-                     'default_for_enterprise_users', 'arc_support',
-                     'supported_chrome_os_management'):
+                     'default_for_enterprise_users',
+                     'default_for_managed_devices_doc_only',
+                     'arc_support', 'supported_chrome_os_management'):
         self.warning_count += 1
         print ('In policy %s: Warning: Unknown key: %s' %
                (policy.get('name'), key))
@@ -288,6 +289,28 @@
         self._Error('per_profile attribute should not be set '
                     'for policies with device_only=True')
 
+      # If 'device only' policy is on, 'default_for_enterprise_users' shouldn't
+      # exist.
+      if (policy.get('device_only', False) and
+          'default_for_enterprise_users' in policy):
+        self._Error('default_for_enteprise_users should not be set '
+                    'for policies with device_only=True. Please use '
+                    'default_for_managed_devices_doc_only to document a'
+                    'differing default value for enrolled devices. Please note '
+                    'that default_for_managed_devices_doc_only is for '
+                    'documentation only - it has no side effects, so you will '
+                    ' still have to implement the enrollment-dependent default '
+                    'value handling yourself in all places where the device '
+                    'policy proto is evaluated. This will probably include '
+                    'device_policy_decoder_chromeos.cc for chrome, but could '
+                    'also have to done in other components if they read the '
+                    'proto directly. Details: crbug.com/809653')
+
+      if (not policy.get('device_only', False) and
+          'default_for_managed_devices_doc_only' in policy):
+        self._Error('default_for_managed_devices_doc_only should only be used '
+                    'with policies that have device_only=True.')
+
       # All policies must declare whether they allow changes at runtime.
       self._CheckContains(features, 'dynamic_refresh', bool,
                           container_name='features',
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp
index 38f3d25..b73107b 100644
--- a/components/policy_strings.grdp
+++ b/components/policy_strings.grdp
@@ -228,6 +228,12 @@
   </message>
 
   <!-- chrome://policy-tool -->
+  <message name="IDS_POLICY_TOOL_CANCEL_RENAME" desc="Button to cancel the dialog that appears in rename session.">
+    Cancel
+  </message>
+  <message name="IDS_POLICY_TOOL_CONFIRM_RENAME" desc="Button that confirm a rename session.">
+    Confirm
+  </message>
   <message name="IDS_POLICY_TOOL_TITLE" desc="Admin page title and the title of the section that lists policies.">
     Policy management
   </message>
@@ -240,6 +246,12 @@
   <message name="IDS_POLICY_TOOL_LOAD_SESSION" desc="Label for the button that loads specified session.">
     Load session
   </message>
+  <message name="IDS_POLICY_TOOL_REMOVE_SESSION" desc="Label for the button that removes specified session.">
+    Remove
+  </message>
+  <message name="IDS_POLICY_TOOL_RENAME_SESSION" desc="Label for the button that renames specified session.">
+    Rename
+  </message>
   <message name="IDS_POLICY_TOOL_SESSION_NAME_PLACEHOLDER" desc="Placeholder for the input field that lets the user change policy management sessions.">
     Session name
   </message>
@@ -258,6 +270,18 @@
   <message name="IDS_POLICY_TOOL_DELETE_FAILED" desc="A message that is shown to the user when deleting the session fails because the session name that is sent from Javascript is invalid.">
     The session with this name is not valid for deletion.
   </message>
+  <message name="IDS_POLICY_TOOL_SESSION_NOT_EXIST" desc="A message that is shown to the user when
+    the selected session name does not exist.">
+    The selected session does not exist.
+  </message>
+  <message name="IDS_POLICY_TOOL_SESSION_EXIST" desc="A message that is show to the user when
+    there is another session with the same name in a renaming session.">
+    This session name already exists.
+  </message>
+  <message name="IDS_POLICY_TOOL_RENAME_FAILED" desc="A message that is shown to the user when
+    renaming the session fails because the function that rename the file failed.">
+    Failed to rename the session.
+  </message>
   <!-- chrome://policy -->
   <message name="IDS_POLICY_TITLE" desc="Page title and the title of the section that lists policies.">
     Policies
diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/components/proxy_config/pref_proxy_config_tracker_impl.cc
index 2a740f9..aee58b46b 100644
--- a/components/proxy_config/pref_proxy_config_tracker_impl.cc
+++ b/components/proxy_config/pref_proxy_config_tracker_impl.cc
@@ -22,12 +22,11 @@
 
 namespace {
 
-// TODO(rhalavati): Update annotation.
 constexpr net::NetworkTrafficAnnotationTag
     kSettingsProxyConfigTrafficAnnotation =
         net::DefineNetworkTrafficAnnotation("proxy_config_settings", R"(
       semantics {
-        sender: "Preferences Proxy Config"
+        sender: "Proxy Config"
         description:
           "Creates a proxy based on configuration received from settings."
         trigger:
diff --git a/components/filesystem/BUILD.gn b/components/services/filesystem/BUILD.gn
similarity index 92%
rename from components/filesystem/BUILD.gn
rename to components/services/filesystem/BUILD.gn
index c070209c..638b7ec1 100644
--- a/components/filesystem/BUILD.gn
+++ b/components/services/filesystem/BUILD.gn
@@ -26,7 +26,7 @@
 
   deps = [
     "//base",
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
     "//mojo/common",
     "//mojo/common:common_base",
     "//mojo/public/cpp/system",
@@ -48,7 +48,7 @@
     deps = [
       ":lib",
       "//base",
-      "//components/filesystem/public/interfaces",
+      "//components/services/filesystem/public/interfaces",
       "//mojo/common",
       "//mojo/public/cpp/bindings",
       "//mojo/public/cpp/system",
@@ -73,7 +73,7 @@
 
     deps = [
       "//base",
-      "//components/filesystem/public/interfaces",
+      "//components/services/filesystem/public/interfaces",
       "//mojo/common",
       "//mojo/public/cpp/bindings",
       "//mojo/public/cpp/system",
diff --git a/components/filesystem/DEPS b/components/services/filesystem/DEPS
similarity index 100%
rename from components/filesystem/DEPS
rename to components/services/filesystem/DEPS
diff --git a/components/filesystem/OWNERS b/components/services/filesystem/OWNERS
similarity index 100%
rename from components/filesystem/OWNERS
rename to components/services/filesystem/OWNERS
diff --git a/components/filesystem/directory_impl.cc b/components/services/filesystem/directory_impl.cc
similarity index 98%
rename from components/filesystem/directory_impl.cc
rename to components/services/filesystem/directory_impl.cc
index 21e4adf..7c0b898 100644
--- a/components/filesystem/directory_impl.cc
+++ b/components/services/filesystem/directory_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/directory_impl.h"
+#include "components/services/filesystem/directory_impl.h"
 
 #include <memory>
 #include <string>
@@ -15,9 +15,9 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "build/build_config.h"
-#include "components/filesystem/file_impl.h"
-#include "components/filesystem/lock_table.h"
-#include "components/filesystem/util.h"
+#include "components/services/filesystem/file_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/util.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
 namespace filesystem {
diff --git a/components/filesystem/directory_impl.h b/components/services/filesystem/directory_impl.h
similarity index 89%
rename from components/filesystem/directory_impl.h
rename to components/services/filesystem/directory_impl.h
index afdd30c8..03e56e16 100644
--- a/components/filesystem/directory_impl.h
+++ b/components/services/filesystem/directory_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_
-#define COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_
 
 #include <stdint.h>
 
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
-#include "components/filesystem/shared_temp_dir.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/shared_temp_dir.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
 namespace filesystem {
@@ -78,4 +78,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_
diff --git a/components/filesystem/directory_impl_unittest.cc b/components/services/filesystem/directory_impl_unittest.cc
similarity index 99%
rename from components/filesystem/directory_impl_unittest.cc
rename to components/services/filesystem/directory_impl_unittest.cc
index b129972..0a051df608 100644
--- a/components/filesystem/directory_impl_unittest.cc
+++ b/components/services/filesystem/directory_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/filesystem/files_test_base.h"
+#include "components/services/filesystem/files_test_base.h"
 
 namespace filesystem {
 namespace {
diff --git a/components/filesystem/file_impl.cc b/components/services/filesystem/file_impl.cc
similarity index 96%
rename from components/filesystem/file_impl.cc
rename to components/services/filesystem/file_impl.cc
index 1e726f3..6346501 100644
--- a/components/filesystem/file_impl.cc
+++ b/components/services/filesystem/file_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/file_impl.h"
+#include "components/services/filesystem/file_impl.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -16,9 +16,9 @@
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "build/build_config.h"
-#include "components/filesystem/lock_table.h"
-#include "components/filesystem/shared_temp_dir.h"
-#include "components/filesystem/util.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/shared_temp_dir.h"
+#include "components/services/filesystem/util.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
 static_assert(sizeof(off_t) <= sizeof(int64_t), "off_t too big");
@@ -169,8 +169,8 @@
   const char* buf = (bytes_to_write.size() > 0)
                         ? reinterpret_cast<const char*>(&bytes_to_write.front())
                         : nullptr;
-  int num_bytes_written = file_.WriteAtCurrentPos(
-      buf, static_cast<int>(bytes_to_write.size()));
+  int num_bytes_written =
+      file_.WriteAtCurrentPos(buf, static_cast<int>(bytes_to_write.size()));
   if (num_bytes_written < 0) {
     std::move(callback).Run(base::File::Error::FILE_ERROR_FAILED, 0);
     return;
diff --git a/components/filesystem/file_impl.h b/components/services/filesystem/file_impl.h
similarity index 91%
rename from components/filesystem/file_impl.h
rename to components/services/filesystem/file_impl.h
index 3b7db2ea2..adb1491e 100644
--- a/components/filesystem/file_impl.h
+++ b/components/services/filesystem/file_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_FILE_IMPL_H_
-#define COMPONENTS_FILESYSTEM_FILE_IMPL_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_
 
 #include <stdint.h>
 
@@ -11,7 +11,7 @@
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "build/build_config.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
 namespace base {
@@ -83,4 +83,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_FILE_IMPL_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_
diff --git a/components/filesystem/file_impl_unittest.cc b/components/services/filesystem/file_impl_unittest.cc
similarity index 99%
rename from components/filesystem/file_impl_unittest.cc
rename to components/services/filesystem/file_impl_unittest.cc
index 32410be..1aab2bb3 100644
--- a/components/filesystem/file_impl_unittest.cc
+++ b/components/services/filesystem/file_impl_unittest.cc
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "base/files/file.h"
-#include "components/filesystem/files_test_base.h"
+#include "components/services/filesystem/files_test_base.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 
diff --git a/components/filesystem/file_system_app.cc b/components/services/filesystem/file_system_app.cc
similarity index 90%
rename from components/filesystem/file_system_app.cc
rename to components/services/filesystem/file_system_app.cc
index 69965c4..d5a24f0 100644
--- a/components/filesystem/file_system_app.cc
+++ b/components/services/filesystem/file_system_app.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/file_system_app.h"
+#include "components/services/filesystem/file_system_app.h"
 
 #include <memory>
 
@@ -34,7 +34,7 @@
 
 const char kUserDataDir[] = "user-data-dir";
 
-}  // namespace filesystem
+}  // namespace
 
 FileSystemApp::FileSystemApp() : lock_table_(new LockTable) {
   registry_.AddInterface<mojom::FileSystem>(
@@ -61,7 +61,7 @@
       std::move(request));
 }
 
-//static
+// static
 base::FilePath FileSystemApp::GetUserDataDir() {
   base::FilePath path;
 
@@ -77,9 +77,8 @@
     CHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &path));
 #elif defined(OS_LINUX)
     std::unique_ptr<base::Environment> env(base::Environment::Create());
-    path = base::nix::GetXDGDirectory(env.get(),
-                                      base::nix::kXdgConfigHomeEnvVar,
-                                      base::nix::kDotConfigDir);
+    path = base::nix::GetXDGDirectory(
+        env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir);
 #else
     NOTIMPLEMENTED();
 #endif
diff --git a/components/filesystem/file_system_app.h b/components/services/filesystem/file_system_app.h
similarity index 73%
rename from components/filesystem/file_system_app.h
rename to components/services/filesystem/file_system_app.h
index e91baa5..84d9d9bf 100644
--- a/components/filesystem/file_system_app.h
+++ b/components/services/filesystem/file_system_app.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_
-#define COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
 
 #include "base/macros.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/file_system_impl.h"
-#include "components/filesystem/lock_table.h"
-#include "components/filesystem/public/interfaces/file_system.mojom.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/file_system_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
 
@@ -44,4 +44,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
diff --git a/components/filesystem/file_system_impl.cc b/components/services/filesystem/file_system_impl.cc
similarity index 91%
rename from components/filesystem/file_system_impl.cc
rename to components/services/filesystem/file_system_impl.cc
index 34aa7388..ef857e93 100644
--- a/components/filesystem/file_system_impl.cc
+++ b/components/services/filesystem/file_system_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/file_system_impl.h"
+#include "components/services/filesystem/file_system_impl.h"
 
 #include <stddef.h>
 
@@ -16,8 +16,8 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/lock_table.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/identity.h"
 #include "url/gurl.h"
@@ -31,8 +31,7 @@
       lock_table_(std::move(lock_table)),
       persistent_dir_(persistent_dir) {}
 
-FileSystemImpl::~FileSystemImpl() {
-}
+FileSystemImpl::~FileSystemImpl() {}
 
 void FileSystemImpl::OpenTempDirectory(mojom::DirectoryRequest directory,
                                        OpenTempDirectoryCallback callback) {
diff --git a/components/filesystem/file_system_impl.h b/components/services/filesystem/file_system_impl.h
similarity index 80%
rename from components/filesystem/file_system_impl.h
rename to components/services/filesystem/file_system_impl.h
index 6538077..2b30006c 100644
--- a/components/filesystem/file_system_impl.h
+++ b/components/services/filesystem/file_system_impl.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_
-#define COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "components/filesystem/public/interfaces/file_system.mojom.h"
-#include "components/filesystem/shared_temp_dir.h"
+#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
+#include "components/services/filesystem/shared_temp_dir.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 
 namespace base {
@@ -51,4 +51,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
diff --git a/components/filesystem/files_test_base.cc b/components/services/filesystem/files_test_base.cc
similarity index 68%
rename from components/filesystem/files_test_base.cc
rename to components/services/filesystem/files_test_base.cc
index 5e3b356..a8b0b0f 100644
--- a/components/filesystem/files_test_base.cc
+++ b/components/services/filesystem/files_test_base.cc
@@ -2,22 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/files_test_base.h"
+#include "components/services/filesystem/files_test_base.h"
 
 #include <utility>
 
-#include "components/filesystem/public/interfaces/directory.mojom.h"
-#include "components/filesystem/public/interfaces/types.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace filesystem {
 
-FilesTestBase::FilesTestBase()
-    : ServiceTest("filesystem_service_unittests") {
-}
+FilesTestBase::FilesTestBase() : ServiceTest("filesystem_service_unittests") {}
 
-FilesTestBase::~FilesTestBase() {
-}
+FilesTestBase::~FilesTestBase() {}
 
 void FilesTestBase::SetUp() {
   ServiceTest::SetUp();
diff --git a/components/filesystem/files_test_base.h b/components/services/filesystem/files_test_base.h
similarity index 82%
rename from components/filesystem/files_test_base.h
rename to components/services/filesystem/files_test_base.h
index d77acda..1f896c5 100644
--- a/components/filesystem/files_test_base.h
+++ b/components/services/filesystem/files_test_base.h
@@ -2,20 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_
-#define COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
 
 #include <utility>
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "components/filesystem/public/interfaces/file_system.mojom.h"
+#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/service_manager/public/cpp/service_test.h"
 
 namespace filesystem {
 
-template <typename... Args> void IgnoreAllArgs(Args&&... args) {}
+template <typename... Args>
+void IgnoreAllArgs(Args&&... args) {}
 
 template <typename... Args>
 void DoCaptures(Args*... out_args, Args... in_args) {
@@ -60,4 +61,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
diff --git a/components/filesystem/lock_table.cc b/components/services/filesystem/lock_table.cc
similarity index 94%
rename from components/filesystem/lock_table.cc
rename to components/services/filesystem/lock_table.cc
index badbbad..a3402a9e 100644
--- a/components/filesystem/lock_table.cc
+++ b/components/services/filesystem/lock_table.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/lock_table.h"
+#include "components/services/filesystem/lock_table.h"
 
 #include "build/build_config.h"
-#include "components/filesystem/file_impl.h"
+#include "components/services/filesystem/file_impl.h"
 
 namespace filesystem {
 
diff --git a/components/filesystem/lock_table.h b/components/services/filesystem/lock_table.h
similarity index 88%
rename from components/filesystem/lock_table.h
rename to components/services/filesystem/lock_table.h
index 73674ac2..5248960 100644
--- a/components/filesystem/lock_table.h
+++ b/components/services/filesystem/lock_table.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_LOCK_TABLE_H_
-#define COMPONENTS_FILESYSTEM_LOCK_TABLE_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_
 
 #include <set>
 
@@ -45,4 +45,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_LOCK_TABLE_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_
diff --git a/components/filesystem/main.cc b/components/services/filesystem/main.cc
similarity index 88%
rename from components/filesystem/main.cc
rename to components/services/filesystem/main.cc
index 781dfb64..62359c0 100644
--- a/components/filesystem/main.cc
+++ b/components/services/filesystem/main.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/macros.h"
-#include "components/filesystem/file_system_app.h"
 #include "services/service_manager/public/c/main.h"
+#include "base/macros.h"
+#include "components/services/filesystem/file_system_app.h"
 #include "services/service_manager/public/cpp/service_runner.h"
 
 MojoResult ServiceMain(MojoHandle request) {
diff --git a/components/filesystem/manifest.json b/components/services/filesystem/manifest.json
similarity index 100%
rename from components/filesystem/manifest.json
rename to components/services/filesystem/manifest.json
diff --git a/components/filesystem/public/interfaces/BUILD.gn b/components/services/filesystem/public/interfaces/BUILD.gn
similarity index 100%
rename from components/filesystem/public/interfaces/BUILD.gn
rename to components/services/filesystem/public/interfaces/BUILD.gn
diff --git a/components/filesystem/public/interfaces/OWNERS b/components/services/filesystem/public/interfaces/OWNERS
similarity index 100%
rename from components/filesystem/public/interfaces/OWNERS
rename to components/services/filesystem/public/interfaces/OWNERS
diff --git a/components/filesystem/public/interfaces/directory.mojom b/components/services/filesystem/public/interfaces/directory.mojom
similarity index 96%
rename from components/filesystem/public/interfaces/directory.mojom
rename to components/services/filesystem/public/interfaces/directory.mojom
index 4874ee2c..be8f8d5 100644
--- a/components/filesystem/public/interfaces/directory.mojom
+++ b/components/services/filesystem/public/interfaces/directory.mojom
@@ -4,8 +4,8 @@
 
 module filesystem.mojom;
 
-import "components/filesystem/public/interfaces/file.mojom";
-import "components/filesystem/public/interfaces/types.mojom";
+import "components/services/filesystem/public/interfaces/file.mojom";
+import "components/services/filesystem/public/interfaces/types.mojom";
 import "mojo/common/file.mojom";
 import "mojo/public/mojom/base/file_error.mojom";
 
diff --git a/components/filesystem/public/interfaces/file.mojom b/components/services/filesystem/public/interfaces/file.mojom
similarity index 97%
rename from components/filesystem/public/interfaces/file.mojom
rename to components/services/filesystem/public/interfaces/file.mojom
index 7af8a7cf..7d975db 100644
--- a/components/filesystem/public/interfaces/file.mojom
+++ b/components/services/filesystem/public/interfaces/file.mojom
@@ -9,7 +9,7 @@
 
 module filesystem.mojom;
 
-import "components/filesystem/public/interfaces/types.mojom";
+import "components/services/filesystem/public/interfaces/types.mojom";
 import "mojo/common/file.mojom";
 import "mojo/public/mojom/base/file_error.mojom";
 
diff --git a/components/filesystem/public/interfaces/file_system.mojom b/components/services/filesystem/public/interfaces/file_system.mojom
similarity index 88%
rename from components/filesystem/public/interfaces/file_system.mojom
rename to components/services/filesystem/public/interfaces/file_system.mojom
index 94a023f5..f78793b0 100644
--- a/components/filesystem/public/interfaces/file_system.mojom
+++ b/components/services/filesystem/public/interfaces/file_system.mojom
@@ -4,7 +4,7 @@
 
 module filesystem.mojom;
 
-import "components/filesystem/public/interfaces/directory.mojom";
+import "components/services/filesystem/public/interfaces/directory.mojom";
 import "mojo/public/mojom/base/file_error.mojom";
 
 interface FileSystem {
diff --git a/components/filesystem/public/interfaces/types.mojom b/components/services/filesystem/public/interfaces/types.mojom
similarity index 100%
rename from components/filesystem/public/interfaces/types.mojom
rename to components/services/filesystem/public/interfaces/types.mojom
diff --git a/components/filesystem/shared_temp_dir.cc b/components/services/filesystem/shared_temp_dir.cc
similarity index 87%
rename from components/filesystem/shared_temp_dir.cc
rename to components/services/filesystem/shared_temp_dir.cc
index 375b8b8..6c3f25d 100644
--- a/components/filesystem/shared_temp_dir.cc
+++ b/components/services/filesystem/shared_temp_dir.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/shared_temp_dir.h"
+#include "components/services/filesystem/shared_temp_dir.h"
 
 #include "base/files/scoped_temp_dir.h"
 
diff --git a/components/filesystem/shared_temp_dir.h b/components/services/filesystem/shared_temp_dir.h
similarity index 80%
rename from components/filesystem/shared_temp_dir.h
rename to components/services/filesystem/shared_temp_dir.h
index d403f73..15ee84b 100644
--- a/components/filesystem/shared_temp_dir.h
+++ b/components/services/filesystem/shared_temp_dir.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_
-#define COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_
 
 #include "base/memory/ref_counted.h"
 
@@ -30,4 +30,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_
diff --git a/components/filesystem/test_manifest.json b/components/services/filesystem/test_manifest.json
similarity index 100%
rename from components/filesystem/test_manifest.json
rename to components/services/filesystem/test_manifest.json
diff --git a/components/filesystem/util.cc b/components/services/filesystem/util.cc
similarity index 98%
rename from components/filesystem/util.cc
rename to components/services/filesystem/util.cc
index 659b9bb6..475dd25 100644
--- a/components/filesystem/util.cc
+++ b/components/services/filesystem/util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/filesystem/util.h"
+#include "components/services/filesystem/util.h"
 
 #include <errno.h>
 #include <fcntl.h>
diff --git a/components/filesystem/util.h b/components/services/filesystem/util.h
similarity index 88%
rename from components/filesystem/util.h
rename to components/services/filesystem/util.h
index 8d90847..45ddc933 100644
--- a/components/filesystem/util.h
+++ b/components/services/filesystem/util.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FILESYSTEM_UTIL_H_
-#define COMPONENTS_FILESYSTEM_UTIL_H_
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_
 
 #include <stdint.h>
 
 #include <string>
 
 #include "base/files/file.h"
-#include "components/filesystem/public/interfaces/types.mojom.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
 
 namespace filesystem {
 
@@ -48,4 +48,4 @@
 
 }  // namespace filesystem
 
-#endif  // COMPONENTS_FILESYSTEM_UTIL_H_
+#endif  // COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_
diff --git a/components/leveldb/BUILD.gn b/components/services/leveldb/BUILD.gn
similarity index 80%
rename from components/leveldb/BUILD.gn
rename to components/services/leveldb/BUILD.gn
index 0b0f2cb..e69401ec 100644
--- a/components/leveldb/BUILD.gn
+++ b/components/services/leveldb/BUILD.gn
@@ -21,9 +21,9 @@
   ]
 
   public_deps = [
-    "//components/filesystem/public/interfaces",
-    "//components/leveldb/public/cpp",
-    "//components/leveldb/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
+    "//components/services/leveldb/public/cpp",
+    "//components/services/leveldb/public/interfaces",
   ]
 
   deps = [
@@ -43,7 +43,7 @@
 
   deps = [
     ":lib",
-    "//components/leveldb/public/interfaces",
+    "//components/services/leveldb/public/interfaces",
     "//mojo/common",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
@@ -67,9 +67,9 @@
 
   deps = [
     "//base",
-    "//components/filesystem/public/interfaces",
-    "//components/leveldb/public/cpp",
-    "//components/leveldb/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
+    "//components/services/leveldb/public/cpp",
+    "//components/services/leveldb/public/interfaces",
     "//mojo/common",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
@@ -80,7 +80,7 @@
 
   data_deps = [
     ":leveldb",
-    "//components/filesystem:filesystem",
+    "//components/services/filesystem:filesystem",
   ]
 }
 
@@ -93,6 +93,6 @@
   embedded_services = [ ":test_manifest" ]
   standalone_services = [
     ":manifest",
-    "//components/filesystem:manifest",
+    "//components/services/filesystem:manifest",
   ]
 }
diff --git a/components/leveldb/DEPS b/components/services/leveldb/DEPS
similarity index 71%
rename from components/leveldb/DEPS
rename to components/services/leveldb/DEPS
index 659b133..048eb8af 100644
--- a/components/leveldb/DEPS
+++ b/components/services/leveldb/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-  "+components/filesystem/public/interfaces",
+  "+components/services/filesystem/public/interfaces",
   "+mojo/common",
   "+mojo/public",
   "+mojo/util",
diff --git a/components/leveldb/OWNERS b/components/services/leveldb/OWNERS
similarity index 100%
rename from components/leveldb/OWNERS
rename to components/services/leveldb/OWNERS
diff --git a/components/leveldb/env_mojo.cc b/components/services/leveldb/env_mojo.cc
similarity index 97%
rename from components/leveldb/env_mojo.cc
rename to components/services/leveldb/env_mojo.cc
index e46931f..2985805 100644
--- a/components/leveldb/env_mojo.cc
+++ b/components/services/leveldb/env_mojo.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/env_mojo.h"
+#include "components/services/leveldb/env_mojo.h"
 
 #include <memory>
 #include <string>
@@ -70,9 +70,8 @@
   ~MojoSequentialFile() override {}
 
   Status Read(size_t n, Slice* result, char* scratch) override {
-    int bytes_read = file_.ReadAtCurrentPosNoBestEffort(
-        scratch,
-        static_cast<int>(n));
+    int bytes_read =
+        file_.ReadAtCurrentPosNoBestEffort(scratch, static_cast<int>(n));
     if (bytes_read == -1) {
       base::File::Error error = base::File::GetLastFileError();
       uma_logger_->RecordOSError(leveldb_env::kSequentialFileRead, error);
@@ -348,9 +347,9 @@
 Status MojoEnv::NewWritableFile(const std::string& fname,
                                 WritableFile** result) {
   TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname);
-  base::File f =
-      thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways |
-                                               filesystem::mojom::kFlagWrite);
+  base::File f = thread_->OpenFileHandle(
+      dir_, fname,
+      filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite);
   if (!f.IsValid()) {
     *result = nullptr;
     RecordOSError(leveldb_env::kNewWritableFile, f.error_details());
@@ -365,9 +364,9 @@
 Status MojoEnv::NewAppendableFile(const std::string& fname,
                                   WritableFile** result) {
   TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname);
-  base::File f =
-      thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways |
-                                               filesystem::mojom::kFlagAppend);
+  base::File f = thread_->OpenFileHandle(
+      dir_, fname,
+      filesystem::mojom::kFlagOpenAlways | filesystem::mojom::kFlagAppend);
   if (!f.IsValid()) {
     *result = nullptr;
     RecordOSError(leveldb_env::kNewAppendableFile, f.error_details());
diff --git a/components/leveldb/env_mojo.h b/components/services/leveldb/env_mojo.h
similarity index 92%
rename from components/leveldb/env_mojo.h
rename to components/services/leveldb/env_mojo.h
index a2264d96..9748900cf 100644
--- a/components/leveldb/env_mojo.h
+++ b/components/services/leveldb/env_mojo.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_ENV_MOJO_H_
-#define COMPONENTS_LEVELDB_ENV_MOJO_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_
+#define COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_
 
 #include <string>
 #include <vector>
 
-#include "components/filesystem/public/interfaces/directory.mojom.h"
-#include "components/leveldb/leveldb_mojo_proxy.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/leveldb/leveldb_mojo_proxy.h"
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
 
@@ -87,4 +87,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_ENV_MOJO_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_
diff --git a/components/leveldb/leveldb.typemap b/components/services/leveldb/leveldb.typemap
similarity index 66%
rename from components/leveldb/leveldb.typemap
rename to components/services/leveldb/leveldb.typemap
index 52d2f394..4b95769 100644
--- a/components/leveldb/leveldb.typemap
+++ b/components/services/leveldb/leveldb.typemap
@@ -2,11 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-mojom = "//components/leveldb/public/interfaces/leveldb.mojom"
+mojom = "//components/services/leveldb/public/interfaces/leveldb.mojom"
 public_headers = [ "//third_party/leveldatabase/env_chromium.h" ]
-traits_headers = [ "//components/leveldb/leveldb_struct_traits.h" ]
+traits_headers = [ "//components/services/leveldb/leveldb_struct_traits.h" ]
 sources = [
-  "//components/leveldb/leveldb_struct_traits.cc",
+  "//components/services/leveldb/leveldb_struct_traits.cc",
 ]
 deps = []
 public_deps = [
diff --git a/components/leveldb/leveldb_app.cc b/components/services/leveldb/leveldb_app.cc
similarity index 90%
rename from components/leveldb/leveldb_app.cc
rename to components/services/leveldb/leveldb_app.cc
index 76b48b3..fb98c44 100644
--- a/components/leveldb/leveldb_app.cc
+++ b/components/services/leveldb/leveldb_app.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/leveldb_app.h"
+#include "components/services/leveldb/leveldb_app.h"
 
 #include "base/task_scheduler/post_task.h"
-#include "components/leveldb/leveldb_service_impl.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
 #include "services/service_manager/public/cpp/service_context.h"
 
 namespace leveldb {
diff --git a/components/leveldb/leveldb_app.h b/components/services/leveldb/leveldb_app.h
similarity index 83%
rename from components/leveldb/leveldb_app.h
rename to components/services/leveldb/leveldb_app.h
index f5696a3..06c1b87 100644
--- a/components/leveldb/leveldb_app.h
+++ b/components/services/leveldb/leveldb_app.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_LEVELDB_APP_H_
-#define COMPONENTS_LEVELDB_LEVELDB_APP_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
+#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
 
 #include <memory>
 
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
@@ -43,4 +43,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_LEVELDB_APP_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
diff --git a/components/leveldb/leveldb_database_impl.cc b/components/services/leveldb/leveldb_database_impl.cc
similarity index 98%
rename from components/leveldb/leveldb_database_impl.cc
rename to components/services/leveldb/leveldb_database_impl.cc
index f285c92..15be4ec5 100644
--- a/components/leveldb/leveldb_database_impl.cc
+++ b/components/services/leveldb/leveldb_database_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/leveldb_database_impl.h"
+#include "components/services/leveldb/leveldb_database_impl.h"
 
 #include <inttypes.h>
 #include <algorithm>
@@ -15,8 +15,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/memory_dump_manager.h"
-#include "components/leveldb/env_mojo.h"
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/env_mojo.h"
+#include "components/services/leveldb/public/cpp/util.h"
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
diff --git a/components/leveldb/leveldb_database_impl.h b/components/services/leveldb/leveldb_database_impl.h
similarity index 94%
rename from components/leveldb/leveldb_database_impl.h
rename to components/services/leveldb/leveldb_database_impl.h
index 757c61e1..8a11405 100644
--- a/components/leveldb/leveldb_database_impl.h
+++ b/components/services/leveldb/leveldb_database_impl.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_
-#define COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_
+#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_
 
 #include <memory>
 #include <vector>
 
 #include "base/trace_event/memory_dump_provider.h"
 #include "base/unguessable_token.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "third_party/leveldatabase/src/include/leveldb/cache.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -104,4 +104,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_
diff --git a/components/leveldb/leveldb_mojo_proxy.cc b/components/services/leveldb/leveldb_mojo_proxy.cc
similarity index 92%
rename from components/leveldb/leveldb_mojo_proxy.cc
rename to components/services/leveldb/leveldb_mojo_proxy.cc
index c067719c..5ff7895 100644
--- a/components/leveldb/leveldb_mojo_proxy.cc
+++ b/components/services/leveldb/leveldb_mojo_proxy.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/leveldb_mojo_proxy.h"
+#include "components/services/leveldb/leveldb_mojo_proxy.h"
 
 #include <set>
 
@@ -37,38 +37,37 @@
     filesystem::mojom::DirectoryPtr directory) {
   OpaqueDir* out_dir = nullptr;
   RunInternal(base::Bind(&LevelDBMojoProxy::RegisterDirectoryImpl, this,
-                         base::Passed(directory.PassInterface()),
-                         &out_dir));
+                         base::Passed(directory.PassInterface()), &out_dir));
 
   return out_dir;
 }
 
 void LevelDBMojoProxy::UnregisterDirectory(OpaqueDir* dir) {
-  RunInternal(base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl,
-                         this, dir));
+  RunInternal(
+      base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl, this, dir));
 }
 
 base::File LevelDBMojoProxy::OpenFileHandle(OpaqueDir* dir,
                                             const std::string& name,
                                             uint32_t open_flags) {
   base::File file;
-  RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir,
-                         name, open_flags, &file));
+  RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir, name,
+                         open_flags, &file));
   return file;
 }
 
 base::File::Error LevelDBMojoProxy::SyncDirectory(OpaqueDir* dir,
                                                   const std::string& name) {
   base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
-  RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir,
-                         name, &error));
+  RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir, name,
+                         &error));
   return error;
 }
 
 bool LevelDBMojoProxy::FileExists(OpaqueDir* dir, const std::string& name) {
   bool exists = false;
-  RunInternal(base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir,
-                         name, &exists));
+  RunInternal(
+      base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir, name, &exists));
   return exists;
 }
 
@@ -77,8 +76,8 @@
     const std::string& path,
     std::vector<std::string>* result) {
   base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
-  RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir,
-                         path, result, &error));
+  RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir, path,
+                         result, &error));
   return error;
 }
 
@@ -94,8 +93,8 @@
 base::File::Error LevelDBMojoProxy::CreateDir(OpaqueDir* dir,
                                               const std::string& path) {
   base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
-  RunInternal(base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path,
-                         &error));
+  RunInternal(
+      base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path, &error));
   return error;
 }
 
@@ -103,8 +102,8 @@
                                                 const std::string& path,
                                                 uint64_t* file_size) {
   base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
-  RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir,
-                         path, file_size, &error));
+  RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir, path,
+                         file_size, &error));
   return error;
 }
 
@@ -112,8 +111,8 @@
                                                const std::string& old_path,
                                                const std::string& new_path) {
   base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
-  RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir,
-                         old_path, new_path, &error));
+  RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir, old_path,
+                         new_path, &error));
   return error;
 }
 
@@ -147,11 +146,8 @@
         base::WaitableEvent::ResetPolicy::AUTOMATIC,
         base::WaitableEvent::InitialState::NOT_SIGNALED);
     task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&LevelDBMojoProxy::DoOnOtherThread,
-                   this,
-                   task,
-                   base::Unretained(&done_event)));
+        FROM_HERE, base::Bind(&LevelDBMojoProxy::DoOnOtherThread, this, task,
+                              base::Unretained(&done_event)));
     base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
     done_event.Wait();
   }
@@ -171,8 +167,7 @@
   outstanding_opaque_dirs_++;
 }
 
-void LevelDBMojoProxy::UnregisterDirectoryImpl(
-    OpaqueDir* dir) {
+void LevelDBMojoProxy::UnregisterDirectoryImpl(OpaqueDir* dir) {
   // Only delete the directories on the thread that owns them.
   delete dir;
   outstanding_opaque_dirs_--;
diff --git a/components/leveldb/leveldb_mojo_proxy.h b/components/services/leveldb/leveldb_mojo_proxy.h
similarity index 94%
rename from components/leveldb/leveldb_mojo_proxy.h
rename to components/services/leveldb/leveldb_mojo_proxy.h
index eee605f4b..0ced74a 100644
--- a/components/leveldb/leveldb_mojo_proxy.h
+++ b/components/services/leveldb/leveldb_mojo_proxy.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_
-#define COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_
+#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_
 
 #include <map>
 #include <memory>
@@ -17,7 +17,7 @@
 #include "base/sequenced_task_runner.h"
 
 #include "base/synchronization/waitable_event.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 
 namespace leveldb {
 
@@ -118,9 +118,7 @@
   void SyncDirectoryImpl(OpaqueDir* dir,
                          std::string name,
                          base::File::Error* out_error);
-  void FileExistsImpl(OpaqueDir* dir,
-                      std::string name,
-                      bool* exists);
+  void FileExistsImpl(OpaqueDir* dir, std::string name, bool* exists);
   void GetChildrenImpl(OpaqueDir* dir,
                        std::string name,
                        std::vector<std::string>* contents,
@@ -158,4 +156,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_
diff --git a/components/leveldb/leveldb_mojo_unittest.cc b/components/services/leveldb/leveldb_mojo_unittest.cc
similarity index 95%
rename from components/leveldb/leveldb_mojo_unittest.cc
rename to components/services/leveldb/leveldb_mojo_unittest.cc
index 490fd92..a9cf1f19 100644
--- a/components/leveldb/leveldb_mojo_unittest.cc
+++ b/components/services/leveldb/leveldb_mojo_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-#include "components/leveldb/leveldb_struct_traits.h"
+#include "components/services/leveldb/leveldb_struct_traits.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
diff --git a/components/leveldb/leveldb_service_impl.cc b/components/services/leveldb/leveldb_service_impl.cc
similarity index 94%
rename from components/leveldb/leveldb_service_impl.cc
rename to components/services/leveldb/leveldb_service_impl.cc
index 639c38f9..7e4c6128 100644
--- a/components/leveldb/leveldb_service_impl.cc
+++ b/components/services/leveldb/leveldb_service_impl.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/leveldb_service_impl.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
 
 #include <memory>
 #include <utility>
 
-#include "components/leveldb/env_mojo.h"
-#include "components/leveldb/leveldb_database_impl.h"
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/env_mojo.h"
+#include "components/services/leveldb/leveldb_database_impl.h"
+#include "components/services/leveldb/public/cpp/util.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
diff --git a/components/leveldb/leveldb_service_impl.h b/components/services/leveldb/leveldb_service_impl.h
similarity index 87%
rename from components/leveldb/leveldb_service_impl.h
rename to components/services/leveldb/leveldb_service_impl.h
index bae33e8..8eb0ebf7 100644
--- a/components/leveldb/leveldb_service_impl.h
+++ b/components/services/leveldb/leveldb_service_impl.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_
-#define COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_
+#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_
 
 #include "base/memory/ref_counted.h"
-#include "components/leveldb/leveldb_mojo_proxy.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/leveldb_mojo_proxy.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 
 namespace base {
@@ -60,4 +60,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_
diff --git a/components/leveldb/leveldb_service_unittest.cc b/components/services/leveldb/leveldb_service_unittest.cc
similarity index 98%
rename from components/leveldb/leveldb_service_unittest.cc
rename to components/services/leveldb/leveldb_service_unittest.cc
index f18a375b8..514144e 100644
--- a/components/leveldb/leveldb_service_unittest.cc
+++ b/components/services/leveldb/leveldb_service_unittest.cc
@@ -5,11 +5,11 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
-#include "components/filesystem/public/interfaces/file_system.mojom.h"
-#include "components/filesystem/public/interfaces/types.mojom.h"
-#include "components/leveldb/public/cpp/util.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/cpp/service_test.h"
@@ -17,7 +17,8 @@
 namespace leveldb {
 namespace {
 
-template <typename... Args> void IgnoreAllArgs(Args&&...) {}
+template <typename... Args>
+void IgnoreAllArgs(Args&&...) {}
 
 template <typename... Args>
 void DoCaptures(typename std::decay<Args>::type*... out_args,
diff --git a/components/leveldb/leveldb_struct_traits.cc b/components/services/leveldb/leveldb_struct_traits.cc
similarity index 97%
rename from components/leveldb/leveldb_struct_traits.cc
rename to components/services/leveldb/leveldb_struct_traits.cc
index 866f4d6d..bf720e6 100644
--- a/components/leveldb/leveldb_struct_traits.cc
+++ b/components/services/leveldb/leveldb_struct_traits.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/leveldb_struct_traits.h"
+#include "components/services/leveldb/leveldb_struct_traits.h"
 
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
diff --git a/components/leveldb/leveldb_struct_traits.h b/components/services/leveldb/leveldb_struct_traits.h
similarity index 77%
rename from components/leveldb/leveldb_struct_traits.h
rename to components/services/leveldb/leveldb_struct_traits.h
index 94221096..2d78836 100644
--- a/components/leveldb/leveldb_struct_traits.h
+++ b/components/services/leveldb/leveldb_struct_traits.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
-#define COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
+#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
 
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 
 namespace mojo {
 
@@ -24,4 +24,4 @@
 
 }  // namespace mojo
 
-#endif  // COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
diff --git a/components/leveldb/main.cc b/components/services/leveldb/main.cc
similarity index 89%
rename from components/leveldb/main.cc
rename to components/services/leveldb/main.cc
index 82ad845..6733f1ae 100644
--- a/components/leveldb/main.cc
+++ b/components/services/leveldb/main.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/macros.h"
-#include "components/leveldb/leveldb_app.h"
 #include "services/service_manager/public/c/main.h"
+#include "base/macros.h"
+#include "components/services/leveldb/leveldb_app.h"
 #include "services/service_manager/public/cpp/service_runner.h"
 
 MojoResult ServiceMain(MojoHandle application_request) {
diff --git a/components/leveldb/manifest.json b/components/services/leveldb/manifest.json
similarity index 100%
rename from components/leveldb/manifest.json
rename to components/services/leveldb/manifest.json
diff --git a/components/leveldb/public/cpp/BUILD.gn b/components/services/leveldb/public/cpp/BUILD.gn
similarity index 88%
rename from components/leveldb/public/cpp/BUILD.gn
rename to components/services/leveldb/public/cpp/BUILD.gn
index c729f4c..b43e96d8 100644
--- a/components/leveldb/public/cpp/BUILD.gn
+++ b/components/services/leveldb/public/cpp/BUILD.gn
@@ -12,7 +12,7 @@
 
   deps = [
     "//base",
-    "//components/leveldb/public/interfaces",
+    "//components/services/leveldb/public/interfaces",
     "//mojo/common",
     "//services/service_manager/public/cpp",
     "//third_party/leveldatabase",
diff --git a/components/leveldb/public/cpp/remote_iterator.cc b/components/services/leveldb/public/cpp/remote_iterator.cc
similarity index 92%
rename from components/leveldb/public/cpp/remote_iterator.cc
rename to components/services/leveldb/public/cpp/remote_iterator.cc
index 089928a..0f9b5996 100644
--- a/components/leveldb/public/cpp/remote_iterator.cc
+++ b/components/services/leveldb/public/cpp/remote_iterator.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/public/cpp/remote_iterator.h"
+#include "components/services/leveldb/public/cpp/remote_iterator.h"
 
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/cpp/util.h"
 
 namespace leveldb {
 
diff --git a/components/leveldb/public/cpp/remote_iterator.h b/components/services/leveldb/public/cpp/remote_iterator.h
similarity index 82%
rename from components/leveldb/public/cpp/remote_iterator.h
rename to components/services/leveldb/public/cpp/remote_iterator.h
index 41d2940..723e608 100644
--- a/components/leveldb/public/cpp/remote_iterator.h
+++ b/components/services/leveldb/public/cpp/remote_iterator.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
-#define COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
+#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
 
 #include "base/unguessable_token.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "third_party/leveldatabase/src/include/leveldb/iterator.h"
 
 namespace leveldb {
@@ -46,4 +46,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
diff --git a/components/leveldb/public/cpp/util.cc b/components/services/leveldb/public/cpp/util.cc
similarity index 98%
rename from components/leveldb/public/cpp/util.cc
rename to components/services/leveldb/public/cpp/util.cc
index d20044d..63c36bd1 100644
--- a/components/leveldb/public/cpp/util.cc
+++ b/components/services/leveldb/public/cpp/util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/cpp/util.h"
 
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/src/include/leveldb/status.h"
diff --git a/components/leveldb/public/cpp/util.h b/components/services/leveldb/public/cpp/util.h
similarity index 85%
rename from components/leveldb/public/cpp/util.h
rename to components/services/leveldb/public/cpp/util.h
index 4a5618f..9c1a718 100644
--- a/components/leveldb/public/cpp/util.h
+++ b/components/services/leveldb/public/cpp/util.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_
-#define COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_
+#ifndef COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_
+#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_
 
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "third_party/leveldatabase/env_chromium.h"
 
 namespace leveldb {
@@ -41,4 +41,4 @@
 
 }  // namespace leveldb
 
-#endif  // COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_
+#endif  // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_
diff --git a/components/leveldb/public/interfaces/BUILD.gn b/components/services/leveldb/public/interfaces/BUILD.gn
similarity index 86%
rename from components/leveldb/public/interfaces/BUILD.gn
rename to components/services/leveldb/public/interfaces/BUILD.gn
index 1b3172e6..4e519e6 100644
--- a/components/leveldb/public/interfaces/BUILD.gn
+++ b/components/services/leveldb/public/interfaces/BUILD.gn
@@ -12,7 +12,7 @@
   ]
 
   deps = [
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
   ]
 
   public_deps = [
diff --git a/components/leveldb/public/interfaces/OWNERS b/components/services/leveldb/public/interfaces/OWNERS
similarity index 100%
rename from components/leveldb/public/interfaces/OWNERS
rename to components/services/leveldb/public/interfaces/OWNERS
diff --git a/components/leveldb/public/interfaces/leveldb.mojom b/components/services/leveldb/public/interfaces/leveldb.mojom
similarity index 98%
rename from components/leveldb/public/interfaces/leveldb.mojom
rename to components/services/leveldb/public/interfaces/leveldb.mojom
index 1dcca48..a4144f600 100644
--- a/components/leveldb/public/interfaces/leveldb.mojom
+++ b/components/services/leveldb/public/interfaces/leveldb.mojom
@@ -4,7 +4,7 @@
 
 module leveldb.mojom;
 
-import "components/filesystem/public/interfaces/directory.mojom";
+import "components/services/filesystem/public/interfaces/directory.mojom";
 import "mojo/common/unguessable_token.mojom";
 import "mojo/common/memory_allocator_dump_cross_process_uid.mojom";
 
diff --git a/components/leveldb/remote_iterator_unittest.cc b/components/services/leveldb/remote_iterator_unittest.cc
similarity index 95%
rename from components/leveldb/remote_iterator_unittest.cc
rename to components/services/leveldb/remote_iterator_unittest.cc
index f37bd48..e763736 100644
--- a/components/leveldb/remote_iterator_unittest.cc
+++ b/components/services/leveldb/remote_iterator_unittest.cc
@@ -7,9 +7,9 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "components/leveldb/public/cpp/remote_iterator.h"
-#include "components/leveldb/public/cpp/util.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/cpp/remote_iterator.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/cpp/service_test.h"
 
diff --git a/components/leveldb/test_manifest.json b/components/services/leveldb/test_manifest.json
similarity index 100%
rename from components/leveldb/test_manifest.json
rename to components/services/leveldb/test_manifest.json
diff --git a/components/typemaps.gni b/components/typemaps.gni
index f8256636..f53c803 100644
--- a/components/typemaps.gni
+++ b/components/typemaps.gni
@@ -6,7 +6,7 @@
   "//components/autofill/content/common/autofill_types.typemap",
   "//components/chrome_cleaner/public/typemaps/chrome_prompt.typemap",
   "//components/content_settings/core/common/content_settings.typemap",
-  "//components/leveldb/leveldb.typemap",
+  "//components/services/leveldb/leveldb.typemap",
   "//components/nacl/common/nacl.typemap",
   "//components/password_manager/content/common/credential_manager.typemap",
   "//components/password_manager/public/interfaces/sync_password_data.typemap",
diff --git a/components/unzip_service/BUILD.gn b/components/unzip_service/BUILD.gn
index 67252b0..a5fcf20 100644
--- a/components/unzip_service/BUILD.gn
+++ b/components/unzip_service/BUILD.gn
@@ -20,7 +20,7 @@
   ]
 
   public_deps = [
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
     "//components/unzip_service/public/interfaces",
     "//services/service_manager/public/cpp",
   ]
diff --git a/components/unzip_service/DEPS b/components/unzip_service/DEPS
index 116747a..9a39d2d 100644
--- a/components/unzip_service/DEPS
+++ b/components/unzip_service/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-  "+components/filesystem",
+  "+components/services/filesystem",
   "+mojo/public",
   "+services/service_manager/public",
   "+third_party/zlib/google",
diff --git a/components/unzip_service/public/cpp/BUILD.gn b/components/unzip_service/public/cpp/BUILD.gn
index a11aebd..738158d 100644
--- a/components/unzip_service/public/cpp/BUILD.gn
+++ b/components/unzip_service/public/cpp/BUILD.gn
@@ -11,7 +11,7 @@
   ]
 
   public_deps = [
-    "//components/filesystem:lib",
+    "//components/services/filesystem:lib",
     "//components/unzip_service/public/interfaces",
     "//services/service_manager/public/cpp",
   ]
diff --git a/components/unzip_service/public/cpp/unzip.cc b/components/unzip_service/public/cpp/unzip.cc
index a8ab1f5..35480fa3 100644
--- a/components/unzip_service/public/cpp/unzip.cc
+++ b/components/unzip_service/public/cpp/unzip.cc
@@ -16,8 +16,8 @@
 #include "base/strings/string16.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/lock_table.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
 #include "components/unzip_service/public/interfaces/constants.mojom.h"
 #include "components/unzip_service/public/interfaces/unzipper.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/components/unzip_service/public/interfaces/BUILD.gn b/components/unzip_service/public/interfaces/BUILD.gn
index d048a589..1fc91bd2 100644
--- a/components/unzip_service/public/interfaces/BUILD.gn
+++ b/components/unzip_service/public/interfaces/BUILD.gn
@@ -11,7 +11,7 @@
 
   public_deps = [
     ":constants",
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
     "//mojo/common:common_custom_types",
   ]
 }
diff --git a/components/unzip_service/public/interfaces/unzipper.mojom b/components/unzip_service/public/interfaces/unzipper.mojom
index f8164700..77790e5 100644
--- a/components/unzip_service/public/interfaces/unzipper.mojom
+++ b/components/unzip_service/public/interfaces/unzipper.mojom
@@ -6,7 +6,7 @@
 
 import "mojo/common/file.mojom";
 import "mojo/common/file_path.mojom";
-import "components/filesystem/public/interfaces/directory.mojom";
+import "components/services/filesystem/public/interfaces/directory.mojom";
 
 interface UnzipFilter {
   [Sync]
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 7992ec8..78ab406a 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -48,8 +48,6 @@
     "//components/download/public/common:public",
     "//components/download/quarantine",
     "//components/filename_generation",
-    "//components/filesystem:lib",
-    "//components/leveldb:lib",
     "//components/link_header_util",
     "//components/metrics",
     "//components/metrics:single_sample_metrics",
@@ -57,6 +55,8 @@
     "//components/offline_pages/buildflags",
     "//components/offline_pages/core/request_header",
     "//components/rappor",
+    "//components/services/filesystem:lib",
+    "//components/services/leveldb:lib",
     "//components/tracing",
     "//components/tracing:startup_tracing",
     "//components/url_formatter",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 1679126..4ed4529 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -7,8 +7,8 @@
   "+components/download/public/common",
   "+components/download/quarantine/quarantine.h",
   "+components/filename_generation",
-  "+components/filesystem",
-  "+components/leveldb",
+  "+components/services/filesystem",
+  "+components/services/leveldb",
   "+components/link_header_util",
   "+components/metrics",
   "+components/metrics:single_sample_metrics",
diff --git a/content/browser/accessibility/aom_browsertest.cc b/content/browser/accessibility/aom_browsertest.cc
new file mode 100644
index 0000000..0a614f8
--- /dev/null
+++ b/content/browser/accessibility/aom_browsertest.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/base/data_url.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+class AccessibilityObjectModelBrowserTest : public ContentBrowserTest {
+ public:
+  AccessibilityObjectModelBrowserTest() {}
+  ~AccessibilityObjectModelBrowserTest() override {}
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ContentBrowserTest::SetUpCommandLine(command_line);
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kEnableBlinkFeatures, "AccessibilityObjectModel");
+  }
+
+ protected:
+  BrowserAccessibility* FindNode(ax::mojom::Role role,
+                                 const std::string& name) {
+    BrowserAccessibility* root = GetManager()->GetRoot();
+    CHECK(root);
+    return FindNodeInSubtree(*root, role, name);
+  }
+
+  BrowserAccessibilityManager* GetManager() {
+    WebContentsImpl* web_contents =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    return web_contents->GetRootBrowserAccessibilityManager();
+  }
+
+ private:
+  BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
+                                          ax::mojom::Role role,
+                                          const std::string& name) {
+    if (node.GetRole() == role &&
+        node.GetStringAttribute(ax::mojom::StringAttribute::kName) == name)
+      return &node;
+    for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
+      BrowserAccessibility* result =
+          FindNodeInSubtree(*node.PlatformGetChild(i), role, name);
+      if (result)
+        return result;
+    }
+    return nullptr;
+  }
+};
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(AccessibilityObjectModelBrowserTest,
+                       EventListenerOnVirtualNode) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kLoadComplete);
+  GURL url(embedded_test_server()->GetURL(
+      "/accessibility/aom/event-listener-on-virtual-node.html"));
+  NavigateToURL(shell(), url);
+  waiter.WaitForNotification();
+
+  BrowserAccessibility* button = FindNode(ax::mojom::Role::kButton, "FocusMe");
+  ASSERT_NE(nullptr, button);
+
+  BrowserAccessibility* link = FindNode(ax::mojom::Role::kLink, "ClickMe");
+  ASSERT_NE(nullptr, link);
+
+  AccessibilityNotificationWaiter waiter2(
+      shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus);
+  GetManager()->DoDefaultAction(*link);
+  waiter2.WaitForNotification();
+
+  BrowserAccessibility* focus = GetManager()->GetFocus();
+  EXPECT_EQ(focus->GetId(), button->GetId());
+}
+
+}  // namespace content
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc
index 4a88ace..53e38c9d1 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -22,8 +22,8 @@
 #include "base/sys_info.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "build/build_config.h"
-#include "components/leveldb/public/cpp/util.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "content/browser/dom_storage/dom_storage_area.h"
 #include "content/browser/dom_storage/dom_storage_database.h"
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 4687ad5d4..1603bdb 100644
--- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -11,8 +11,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "components/filesystem/public/interfaces/file_system.mojom.h"
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/filesystem/public/interfaces/file_system.mojom.h"
+#include "components/services/leveldb/public/cpp/util.h"
 #include "content/browser/dom_storage/dom_storage_area.h"
 #include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/browser/dom_storage/dom_storage_database.h"
diff --git a/content/browser/leveldb_wrapper_impl.cc b/content/browser/leveldb_wrapper_impl.cc
index d5173bf1..0ff7b32 100644
--- a/content/browser/leveldb_wrapper_impl.cc
+++ b/content/browser/leveldb_wrapper_impl.cc
@@ -11,7 +11,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/process_memory_dump.h"
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/cpp/util.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace content {
diff --git a/content/browser/leveldb_wrapper_impl_unittest.cc b/content/browser/leveldb_wrapper_impl_unittest.cc
index 59624ee1..5e63e99 100644
--- a/content/browser/leveldb_wrapper_impl_unittest.cc
+++ b/content/browser/leveldb_wrapper_impl_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/task_scheduler/post_task.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread.h"
-#include "components/leveldb/public/cpp/util.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/fake_leveldb_database.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/content/browser/service_worker/service_worker_handle.cc b/content/browser/service_worker/service_worker_handle.cc
index f73b082..0aee7f2 100644
--- a/content/browser/service_worker/service_worker_handle.cc
+++ b/content/browser/service_worker/service_worker_handle.cc
@@ -175,6 +175,7 @@
     : dispatcher_host_(dispatcher_host),
       context_(context),
       provider_host_(provider_host),
+      provider_origin_(url::Origin::Create(provider_host->document_url())),
       provider_id_(provider_host->provider_id()),
       handle_id_(context->GetNewServiceWorkerHandleId()),
       version_(version),
@@ -222,16 +223,15 @@
   dispatcher_host_->RegisterServiceWorkerHandle(base::WrapUnique(this));
 }
 
-void ServiceWorkerHandle::PostMessage(::blink::TransferableMessage message,
-                                      const url::Origin& source_origin) {
+void ServiceWorkerHandle::PostMessageToServiceWorker(
+    ::blink::TransferableMessage message) {
   // When this method is called the encoded_message inside message could just
   // point to the IPC message's buffer. But that buffer can become invalid
   // before the message is passed on to the service worker, so make sure
   // message owns its data.
   message.EnsureDataIsOwned();
 
-  DispatchExtendableMessageEvent(std::move(message), source_origin,
-                                 base::DoNothing());
+  DispatchExtendableMessageEvent(std::move(message), base::DoNothing());
 }
 
 void ServiceWorkerHandle::TerminateForTesting(
@@ -241,18 +241,19 @@
 
 void ServiceWorkerHandle::DispatchExtendableMessageEvent(
     ::blink::TransferableMessage message,
-    const url::Origin& source_origin,
     StatusCallback callback) {
   if (!context_ || !provider_host_) {
     std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED);
     return;
   }
+  DCHECK_EQ(provider_origin_,
+            url::Origin::Create(provider_host_->document_url()));
   switch (provider_host_->provider_type()) {
     case blink::mojom::ServiceWorkerProviderType::kForWindow:
       service_worker_client_utils::GetClient(
           provider_host_.get(),
           base::BindOnce(&DispatchExtendableMessageEventFromClient, version_,
-                         std::move(message), source_origin,
+                         std::move(message), provider_origin_,
                          std::move(callback)));
       return;
     case blink::mojom::ServiceWorkerProviderType::kForServiceWorker: {
@@ -264,7 +265,7 @@
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
           base::BindOnce(&DispatchExtendableMessageEventFromServiceWorker,
-                         version_, std::move(message), source_origin,
+                         version_, std::move(message), provider_origin_,
                          base::make_optional(timeout), std::move(callback),
                          provider_host_));
       return;
diff --git a/content/browser/service_worker/service_worker_handle.h b/content/browser/service_worker/service_worker_handle.h
index b5037d8..f9bfb06 100644
--- a/content/browser/service_worker/service_worker_handle.h
+++ b/content/browser/service_worker/service_worker_handle.h
@@ -10,23 +10,12 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom.h"
-
-#if defined(OS_WIN)
-// Since PostMessage is a Win32 macro, ensure that it has the same
-// value every time this header is parsed. This avoids strange
-// compilation and linking errors.
-#include "base/win/windows_types.h"
-#endif
-
-namespace url {
-class Origin;
-}  // namespace url
+#include "url/origin.h"
 
 namespace content {
 
@@ -91,13 +80,15 @@
                       ServiceWorkerVersion* version);
 
   // Implements blink::mojom::ServiceWorkerObjectHost.
-  void PostMessage(::blink::TransferableMessage message,
-                   const url::Origin& source_origin) override;
+  void PostMessageToServiceWorker(
+      ::blink::TransferableMessage message) override;
   void TerminateForTesting(TerminateForTestingCallback callback) override;
 
+  // TODO(leonhsl): Remove |callback| parameter because it's just for unit tests
+  // and production code does not use it. We need to figure out another way to
+  // observe the dispatch result in unit tests.
   void DispatchExtendableMessageEvent(
       ::blink::TransferableMessage message,
-      const url::Origin& source_origin,
       base::OnceCallback<void(ServiceWorkerStatusCode)> callback);
 
   base::WeakPtr<ServiceWorkerHandle> AsWeakPtr();
@@ -111,6 +102,11 @@
   ServiceWorkerDispatcherHost* dispatcher_host_;
   base::WeakPtr<ServiceWorkerContextCore> context_;
   base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+  // The origin of the |provider_host_|. Note that this is const because once a
+  // JavaScript ServiceWorker object is created for an execution context, we
+  // don't expect that context to change origins and still hold on to the
+  // object.
+  const url::Origin provider_origin_;
   const int provider_id_;
   const int handle_id_;
   scoped_refptr<ServiceWorkerVersion> version_;
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc
index 18f49d5..519152a 100644
--- a/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -183,9 +183,8 @@
   void CallDispatchExtendableMessageEvent(
       ServiceWorkerHandle* handle,
       ::blink::TransferableMessage message,
-      const url::Origin& source_origin,
       base::OnceCallback<void(ServiceWorkerStatusCode)> callback) {
-    handle->DispatchExtendableMessageEvent(std::move(message), source_origin,
+    handle->DispatchExtendableMessageEvent(std::move(message),
                                            std::move(callback));
   }
 
@@ -302,7 +301,6 @@
   status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
       sender_worker_handle.get(), std::move(message),
-      url::Origin::Create(version_->scope().GetOrigin()),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
@@ -349,6 +347,7 @@
       ServiceWorkerProviderHost::Create(
           frame_host->GetProcess()->GetID(), std::move(provider_host_info),
           helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
+  provider_host->SetDocumentUrl(pattern);
   // Prepare a ServiceWorkerHandle for the above |provider_host|.
   blink::mojom::ServiceWorkerObjectInfoPtr info;
   // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
@@ -364,7 +363,6 @@
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
       handle.get(), std::move(message),
-      url::Origin::Create(version_->scope().GetOrigin()),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
@@ -406,6 +404,7 @@
       ServiceWorkerProviderHost::Create(
           frame_host->GetProcess()->GetID(), std::move(provider_host_info),
           helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr());
+  provider_host->SetDocumentUrl(pattern);
   // Prepare a ServiceWorkerHandle for the above |provider_host|.
   blink::mojom::ServiceWorkerObjectInfoPtr info;
   // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by
@@ -422,7 +421,6 @@
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
   CallDispatchExtendableMessageEvent(
       handle.get(), std::move(message),
-      url::Origin::Create(version_->scope().GetOrigin()),
       base::BindOnce(&SaveStatusCallback, &called, &status));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 35ec729..e3838b8 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -643,6 +643,7 @@
   DCHECK(dispatcher_host);
   render_process_id_ = process_id;
   dispatcher_host_ = dispatcher_host->AsWeakPtr();
+  SetDocumentUrl(running_hosted_version()->script_url());
 
   // Retrieve the registration associated with |version|. The registration
   // must be alive because the version keeps it during starting worker.
@@ -677,10 +678,6 @@
       mojom::kNavigation_ServiceWorkerSpec, process_id,
       mojo::MakeRequest(&provider_info->interface_provider)));
 
-  // Set the document URL to the script url in order to allow
-  // register/unregister/getRegistration on ServiceWorkerGlobalScope.
-  SetDocumentUrl(running_hosted_version()->script_url());
-
   return provider_info;
 }
 
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index fdbe5b5..3e0a0e7 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -232,6 +232,12 @@
   // Sets the |document_url_|.  When this object is for a client,
   // |matching_registrations_| gets also updated to ensure that |document_url_|
   // is in scope of all |matching_registrations_|.
+  // |document_url_| is the service worker script URL if this is hosting a
+  // running service worker, it will be used when creating ServiceWorkerHandle
+  // or handling ServiceWorkerRegistration#{*} calls etc.
+  // TODO(leonhsl): We should rename |document_url_| to something more
+  // appropriate and/or split this class into one for clients vs one for service
+  // workers.
   void SetDocumentUrl(const GURL& url);
   const GURL& document_url() const { return document_url_; }
 
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 6783df6a..a37840a 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1120,6 +1120,10 @@
   if (!provider_host ||
       provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) {
     // The promise will be resolved to 'undefined'.
+    // Note that we don't BadMessage here since Clients#get() can be passed an
+    // arbitrary UUID. The BadMessages for the origin mismatches below are
+    // appropriate because the UUID is taken directly from a Client object so we
+    // expect it to be valid.
     std::move(callback).Run(nullptr);
     return;
   }
@@ -1166,15 +1170,16 @@
     return;
   }
   if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) {
-    // The client does not belong to the same origin as this ServiceWorker,
-    // possibly due to timing issue or bad message.
-    std::move(callback).Run(nullptr /* client */);
+    mojo::ReportBadMessage(
+        "Received WindowClient#focus() request for a cross-origin client.");
+    binding_.Close();
     return;
   }
   if (provider_host->client_type() !=
       blink::mojom::ServiceWorkerClientType::kWindow) {
     // focus() should be called only for WindowClient.
-    mojo::ReportBadMessage("Received focus() request for a non-window client.");
+    mojo::ReportBadMessage(
+        "Received WindowClient#focus() request for a non-window client.");
     binding_.Close();
     return;
   }
@@ -1219,6 +1224,20 @@
                             std::string("The client was not found."));
     return;
   }
+  if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) {
+    mojo::ReportBadMessage(
+        "Received WindowClient#navigate() request for a cross-origin client.");
+    binding_.Close();
+    return;
+  }
+  if (provider_host->client_type() !=
+      blink::mojom::ServiceWorkerClientType::kWindow) {
+    // navigate() should be called only for WindowClient.
+    mojo::ReportBadMessage(
+        "Received WindowClient#navigate() request for a non-window client.");
+    binding_.Close();
+    return;
+  }
   if (provider_host->active_version() != this) {
     std::move(callback).Run(
         false /* success */, nullptr /* client */,
@@ -1372,8 +1391,7 @@
         message) {
   if (!context_)
     return;
-  TRACE_EVENT1("ServiceWorker",
-               "ServiceWorkerVersion::OnPostMessageToDocument",
+  TRACE_EVENT1("ServiceWorker", "ServiceWorkerVersion::OnPostMessageToClient",
                "Client id", client_uuid);
   ServiceWorkerProviderHost* provider_host =
       context_->GetProviderHostByClientID(client_uuid);
@@ -1382,8 +1400,9 @@
     return;
   }
   if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) {
-    // The client does not belong to the same origin as this ServiceWorker,
-    // possibly due to timing issue or bad message.
+    mojo::ReportBadMessage(
+        "Received Client#postMessage() request for a cross-origin client.");
+    binding_.Close();
     return;
   }
   provider_host->PostMessageToClient(this, std::move(message->data));
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index cfb2f80..c856ca4 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/leveldb/public/cpp/util.h"
+#include "components/services/leveldb/public/cpp/util.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/dom_storage/local_storage_database.pb.h"
 #include "content/browser/gpu/shader_cache_factory.h"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index da45e08a..330c1f7 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -254,10 +254,6 @@
       base::FeatureList::IsEnabled(
           features::kFramebustingNeedsSameOriginOrUserGesture));
 
-  WebRuntimeFeatures::EnableFeatureFromString(
-      "VibrateRequiresUserGesture",
-      base::FeatureList::IsEnabled(features::kVibrateRequiresUserGesture));
-
   if (command_line.HasSwitch(switches::kDisableBackgroundTimerThrottling))
     WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(false);
 
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 322e8736..0dde314c 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -608,7 +608,7 @@
   import_dirs = [ "//mojo/services" ]
 
   public_deps = [
-    "//components/leveldb/public/interfaces",
+    "//components/services/leveldb/public/interfaces",
     "//content/public/common:interfaces",
     "//content/public/common:resource_type_bindings",
     "//ipc:mojom_constants",
diff --git a/content/common/leveldb_wrapper.mojom b/content/common/leveldb_wrapper.mojom
index 8640584e..4b03843 100644
--- a/content/common/leveldb_wrapper.mojom
+++ b/content/common/leveldb_wrapper.mojom
@@ -4,7 +4,7 @@
 
 module content.mojom;
 
-import "components/leveldb/public/interfaces/leveldb.mojom";
+import "components/services/leveldb/public/interfaces/leveldb.mojom";
 
 // Gives information about changes to a LevelDB database.
 // Note that observer methods are called before the callbacks for the
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index bbf8311..e390c3a 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -424,10 +424,6 @@
 const base::Feature kV8VmFuture{"V8VmFuture",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether vibrate requires user gesture.
-const base::Feature kVibrateRequiresUserGesture{
-    "VibrateRequiresUserGesture", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Controls whether editing web input fields is enabled in VR.
 const base::Feature kVrWebInputEditing{"VrWebInputEditing",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index f115485..2c400ac 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -102,7 +102,6 @@
 CONTENT_EXPORT extern const base::Feature kUserActivationV2;
 CONTENT_EXPORT extern const base::Feature kV8ContextSnapshot;
 CONTENT_EXPORT extern const base::Feature kV8VmFuture;
-CONTENT_EXPORT extern const base::Feature kVibrateRequiresUserGesture;
 CONTENT_EXPORT extern const base::Feature kVrWebInputEditing;
 CONTENT_EXPORT extern const base::Feature kWebAssembly;
 CONTENT_EXPORT extern const base::Feature kWebAssemblyStreaming;
diff --git a/content/renderer/dom_storage/DEPS b/content/renderer/dom_storage/DEPS
index b1259df..f57963b8 100644
--- a/content/renderer/dom_storage/DEPS
+++ b/content/renderer/dom_storage/DEPS
@@ -1,7 +1,7 @@
 specific_include_rules = {
   'local_storage\.*': [
     "-content/renderer",
-    "+components/leveldb/public/interfaces",
+    "+components/services/leveldb/public/interfaces",
     "+content/common/dom_storage/dom_storage_map.h",
     "+content/renderer/dom_storage/local_storage_cached_area.h",
     "+content/renderer/dom_storage/local_storage_cached_areas.h",
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.cc b/content/renderer/media/webrtc/rtc_certificate_generator.cc
index 0c29b6de..3daabb6f 100644
--- a/content/renderer/media/webrtc/rtc_certificate_generator.cc
+++ b/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -93,7 +93,9 @@
         FROM_HERE,
         base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
                        this, std::move(observer),
-                       std::make_unique<RTCCertificate>(certificate)));
+                       certificate
+                           ? std::make_unique<RTCCertificate>(certificate)
+                           : nullptr));
   }
 
   void DoCallbackOnMainThread(
diff --git a/content/renderer/service_worker/service_worker_dispatcher_unittest.cc b/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
index 372f41f..e30bc92 100644
--- a/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
+++ b/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
@@ -38,8 +38,8 @@
 
  private:
   // Implements blink::mojom::ServiceWorkerObjectHost.
-  void PostMessage(::blink::TransferableMessage message,
-                   const url::Origin& source_origin) override {
+  void PostMessageToServiceWorker(
+      ::blink::TransferableMessage message) override {
     NOTREACHED();
   }
   void TerminateForTesting(TerminateForTestingCallback callback) override {
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index 2b769d32..6006ef77d 100644
--- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -61,8 +61,8 @@
 
  private:
   // Implements blink::mojom::ServiceWorkerObjectHost.
-  void PostMessage(::blink::TransferableMessage message,
-                   const url::Origin& source_origin) override {
+  void PostMessageToServiceWorker(
+      ::blink::TransferableMessage message) override {
     NOTREACHED();
   }
   void TerminateForTesting(TerminateForTestingCallback callback) override {
diff --git a/content/renderer/service_worker/web_service_worker_impl.cc b/content/renderer/service_worker/web_service_worker_impl.cc
index 94037ab..8217a951 100644
--- a/content/renderer/service_worker/web_service_worker_impl.cc
+++ b/content/renderer/service_worker/web_service_worker_impl.cc
@@ -13,11 +13,9 @@
 #include "content/renderer/service_worker/service_worker_dispatcher.h"
 #include "content/renderer/service_worker/web_service_worker_provider_impl.h"
 #include "third_party/WebKit/public/platform/WebRuntimeFeatures.h"
-#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProxy.h"
 
-using blink::WebSecurityOrigin;
 using blink::WebString;
 
 namespace content {
@@ -97,9 +95,9 @@
   return state_;
 }
 
-void WebServiceWorkerImpl::PostMessage(blink::TransferableMessage message,
-                                       const WebSecurityOrigin& source_origin) {
-  GetObjectHost()->PostMessage(std::move(message), url::Origin(source_origin));
+void WebServiceWorkerImpl::PostMessageToServiceWorker(
+    blink::TransferableMessage message) {
+  GetObjectHost()->PostMessageToServiceWorker(std::move(message));
 }
 
 void WebServiceWorkerImpl::TerminateForTesting(
diff --git a/content/renderer/service_worker/web_service_worker_impl.h b/content/renderer/service_worker/web_service_worker_impl.h
index 9368828..28036b3 100644
--- a/content/renderer/service_worker/web_service_worker_impl.h
+++ b/content/renderer/service_worker/web_service_worker_impl.h
@@ -59,8 +59,7 @@
   blink::WebServiceWorkerProxy* Proxy() override;
   blink::WebURL Url() const override;
   blink::mojom::ServiceWorkerState GetState() const override;
-  void PostMessage(blink::TransferableMessage message,
-                   const blink::WebSecurityOrigin& source_origin) override;
+  void PostMessageToServiceWorker(blink::TransferableMessage message) override;
   void TerminateForTesting(
       std::unique_ptr<TerminateForTestingCallback> callback) override;
 
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc
index b445d63d..25036ee 100644
--- a/content/shell/browser/shell_permission_manager.cc
+++ b/content/shell/browser/shell_permission_manager.cc
@@ -25,7 +25,8 @@
          // default.
          // TODO(nsatragno): add a command line flag so that it's only granted
          // for tests.
-         permission == PermissionType::BACKGROUND_SYNC;
+         permission == PermissionType::BACKGROUND_SYNC ||
+         permission == PermissionType::ACCESSIBILITY_EVENTS;
 }
 
 }  // namespace
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 3b66518..85fa1458 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -99,7 +99,7 @@
   static void Install(base::WeakPtr<TestRunner> test_runner,
                       base::WeakPtr<TestRunnerForSpecificView> view_test_runner,
                       WebLocalFrame* frame,
-                      bool is_web_platform_tests_mode);
+                      bool is_wpt_reftest);
 
  private:
   explicit TestRunnerBindings(
@@ -292,7 +292,7 @@
     base::WeakPtr<TestRunner> test_runner,
     base::WeakPtr<TestRunnerForSpecificView> view_test_runner,
     WebLocalFrame* frame,
-    bool is_web_platform_tests_mode) {
+    bool is_wpt_reftest) {
   v8::Isolate* isolate = blink::MainThreadIsolate();
   v8::HandleScope handle_scope(isolate);
   v8::Local<v8::Context> context = frame->MainWorldScriptContext();
@@ -312,33 +312,44 @@
 
   global->Set(gin::StringToV8(isolate, "testRunner"), v8_bindings);
 
-  // The web-platform-tests suite require that reference comparison is delayed
-  // for any test with a 'reftest-wait' class on the root element, until that
-  // class attribute is removed. To support this approach, we inject some
-  // JavaScript that implements the same behavior using TestRunner.
+  // Inject some JavaScript to the top-level frame of a reftest in the
+  // web-platform-tests suite to have the same reftest screenshot timing as
+  // upstream WPT:
   //
-  // See http://web-platform-tests.org/writing-tests/reftests.html for more
-  // details about reference tests in the web-platform-tests suite.
-  if (is_web_platform_tests_mode) {
+  // 1. For normal reftest, we would like to take screenshots after web fonts
+  //    are loaded, i.e. replicate the behavior of this injected script:
+  //    https://github.com/w3c/web-platform-tests/blob/master/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js
+  // 2. For reftests with a 'reftest-wait' class on the root element, reference
+  //    comparison is delayed until that class attribute is removed. To support
+  //    this feature, we use a mutation observer.
+  //    http://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs
+  //
+  // Note that this method may be called multiple times on a frame, so we put
+  // the code behind a flag. The flag is safe to be installed on testRunner
+  // because WPT reftests never access this object.
+  if (is_wpt_reftest && !frame->Parent()) {
     frame->ExecuteScript(blink::WebString(
-        R"(window.addEventListener('load', function() {
-          if (!window.testRunner) {
-            return;
-          }
-          const target = document.documentElement;
-          if (target != null && target.classList.contains('reftest-wait')) {
+        R"(if (!window.testRunner._wpt_reftest_setup) {
+          window.testRunner._wpt_reftest_setup = true;
+
+          window.addEventListener('load', function() {
             window.testRunner.waitUntilDone();
-            const observer = new MutationObserver(function(mutations) {
-              mutations.forEach(function(mutation) {
-                if (!target.classList.contains('reftest-wait')) {
-                  window.testRunner.notifyDone();
-                }
+            const target = document.documentElement;
+            if (target != null && target.classList.contains('reftest-wait')) {
+              const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                  if (!target.classList.contains('reftest-wait')) {
+                    window.testRunner.notifyDone();
+                  }
+                });
               });
-            });
-            const config = {attributes: true};
-            observer.observe(target, config);
-          }
-        });)"));
+              const config = {attributes: true};
+              observer.observe(target, config);
+            } else {
+              document.fonts.ready.then(() => window.testRunner.notifyDone());
+            }
+          });
+        })"));
   }
 }
 
@@ -1583,8 +1594,11 @@
 void TestRunner::Install(
     WebLocalFrame* frame,
     base::WeakPtr<TestRunnerForSpecificView> view_test_runner) {
+  // In WPT, only reftests generate pixel results.
+  bool is_wpt_reftest =
+      is_web_platform_tests_mode() && ShouldGeneratePixelResults();
   TestRunnerBindings::Install(weak_factory_.GetWeakPtr(), view_test_runner,
-                              frame, is_web_platform_tests_mode());
+                              frame, is_wpt_reftest);
   mock_screen_orientation_client_->OverrideAssociatedInterfaceProviderForFrame(
       frame);
 }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 61e1a95..f478948 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -219,8 +219,6 @@
     "mock_render_widget_host_delegate.h",
     "mock_ssl_host_state_delegate.cc",
     "mock_ssl_host_state_delegate.h",
-    "mock_webassociatedurlloader.cc",
-    "mock_webassociatedurlloader.h",
     "mock_webblob_registry_impl.cc",
     "mock_webblob_registry_impl.h",
     "mock_webclipboard_impl.cc",
@@ -301,7 +299,7 @@
     "//cc/blink",
     "//cc/ipc",
     "//components/download/public/common:public",
-    "//components/leveldb/public/interfaces",
+    "//components/services/leveldb/public/interfaces",
     "//components/viz/host",
     "//components/viz/service",
     "//content/app:both_for_content_tests",
@@ -693,6 +691,7 @@
     "../browser/accessibility/accessibility_action_browsertest.cc",
     "../browser/accessibility/accessibility_ipc_error_browsertest.cc",
     "../browser/accessibility/accessibility_mode_browsertest.cc",
+    "../browser/accessibility/aom_browsertest.cc",
     "../browser/accessibility/cross_platform_accessibility_browsertest.cc",
     "../browser/accessibility/dump_accessibility_browsertest_base.cc",
     "../browser/accessibility/dump_accessibility_browsertest_base.h",
@@ -1659,12 +1658,12 @@
     "//cc",
     "//cc:test_support",
     "//cc/ipc",
-    "//components/leveldb/public/cpp",
     "//components/network_session_configurator/browser",
     "//components/network_session_configurator/common",
     "//components/offline_pages/buildflags",
     "//components/payments/mojom",
     "//components/rappor:test_support",
+    "//components/services/leveldb/public/cpp",
     "//components/ukm:test_support",
     "//components/viz/client",
     "//components/viz/common",
@@ -1760,7 +1759,7 @@
   ]
 
   data_deps = [
-    "//components/filesystem:filesystem",
+    "//components/services/filesystem:filesystem",
     "//testing/buildbot/filters:content_unittests_filters",
     "//third_party/mesa:osmesa",
   ]
diff --git a/content/test/DEPS b/content/test/DEPS
index 8b65cb3..87aa8cbf 100644
--- a/content/test/DEPS
+++ b/content/test/DEPS
@@ -1,7 +1,7 @@
 include_rules = [
   # Allow inclusion of specific components that we depend on.
   # See comment in content/DEPS for which components are allowed.
-  "+components/leveldb",
+  "+components/services/leveldb",
   "+components/network_session_configurator/common",
   "+components/scheduler/renderer",
   "+components/scheduler/test",
diff --git a/content/test/data/accessibility/aom/event-listener-on-virtual-node.html b/content/test/data/accessibility/aom/event-listener-on-virtual-node.html
new file mode 100644
index 0000000..5920a13
--- /dev/null
+++ b/content/test/data/accessibility/aom/event-listener-on-virtual-node.html
@@ -0,0 +1,12 @@
+<body>
+<button aria-label='FocusMe'></button>
+<script>
+  var virtualNode = new AccessibleNode();
+  virtualNode.role = 'link';
+  virtualNode.label = 'ClickMe';
+  virtualNode.onaccessibleclick = function() {
+    document.querySelector('button').focus();
+  };
+  document.body.accessibleNode.appendChild(virtualNode);
+</script>
+</body>
diff --git a/content/test/fake_leveldb_database.h b/content/test/fake_leveldb_database.h
index 913b2b1..8c77d6a 100644
--- a/content/test/fake_leveldb_database.h
+++ b/content/test/fake_leveldb_database.h
@@ -6,7 +6,7 @@
 #define CONTENT_TEST_FAKE_LEVELDB_DATABASE_H_
 
 #include "base/memory/ref_counted.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 
 namespace content {
diff --git a/content/test/mock_webassociatedurlloader.cc b/content/test/mock_webassociatedurlloader.cc
deleted file mode 100644
index e458fb4..0000000
--- a/content/test/mock_webassociatedurlloader.cc
+++ /dev/null
@@ -1,18 +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/test/mock_webassociatedurlloader.h"
-
-#include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-namespace content {
-
-MockWebAssociatedURLLoader::MockWebAssociatedURLLoader() {}
-
-MockWebAssociatedURLLoader::~MockWebAssociatedURLLoader() {}
-
-}  // namespace content
diff --git a/content/test/mock_webassociatedurlloader.h b/content/test/mock_webassociatedurlloader.h
deleted file mode 100644
index 413ce32..0000000
--- a/content/test/mock_webassociatedurlloader.h
+++ /dev/null
@@ -1,34 +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_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_
-#define CONTENT_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_
-
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/WebKit/public/web/WebAssociatedURLLoader.h"
-
-namespace content {
-
-class MockWebAssociatedURLLoader : public blink::WebAssociatedURLLoader {
- public:
-  MockWebAssociatedURLLoader();
-  virtual ~MockWebAssociatedURLLoader();
-
-  MOCK_METHOD2(LoadAsynchronously,
-               void(const blink::WebURLRequest& request,
-                    blink::WebAssociatedURLLoaderClient* client));
-  MOCK_METHOD0(Cancel, void());
-  MOCK_METHOD1(SetDefersLoading, void(bool value));
-  MOCK_METHOD1(SetLoadingTaskRunner,
-               void(base::SingleThreadTaskRunner* loading_task_runner));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockWebAssociatedURLLoader);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index 8f5bf66..027023a 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -88,6 +88,8 @@
     "u2f_sign.cc",
     "u2f_sign.h",
     "u2f_transport_protocol.h",
+    "virtual_u2f_device.cc",
+    "virtual_u2f_device.h",
   ]
 
   defines = [ "IS_DEVICE_FIDO_IMPL" ]
@@ -215,8 +217,6 @@
 source_set("test_support") {
   testonly = true
   sources = [
-    "fake_u2f_device.cc",
-    "fake_u2f_device.h",
     "fake_u2f_discovery.cc",
     "fake_u2f_discovery.h",
     "test_callback_receiver.h",
diff --git a/device/fido/u2f_apdu_command.h b/device/fido/u2f_apdu_command.h
index 76973dca..d9ade7b 100644
--- a/device/fido/u2f_apdu_command.h
+++ b/device/fido/u2f_apdu_command.h
@@ -14,9 +14,7 @@
 
 namespace device {
 
-namespace test {
-class FakeU2fDevice;
-}
+class VirtualU2fDevice;
 
 // APDU commands are defined as part of ISO 7816-4. Commands can be serialized
 // into either short length encodings, where the maximum data length is 256
@@ -78,7 +76,7 @@
   FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestCreateLegacyVersion);
 
   // Built-in software key for testing.
-  friend class test::FakeU2fDevice;
+  friend class VirtualU2fDevice;
 
   static constexpr size_t kApduMinHeader = 4;
   static constexpr size_t kApduMaxHeader = 7;
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
index 5355779..0ce22e8 100644
--- a/device/fido/u2f_register_unittest.cc
+++ b/device/fido/u2f_register_unittest.cc
@@ -14,7 +14,6 @@
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/ec_public_key.h"
-#include "device/fido/fake_u2f_device.h"
 #include "device/fido/fake_u2f_discovery.h"
 #include "device/fido/fido_attestation_statement.h"
 #include "device/fido/mock_u2f_device.h"
@@ -22,6 +21,7 @@
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
 #include "device/fido/u2f_response_test_data.h"
+#include "device/fido/virtual_u2f_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -403,7 +403,7 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<test::FakeU2fDevice>();
+  auto device = std::make_unique<VirtualU2fDevice>();
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
index 7c32ade..6317785 100644
--- a/device/fido/u2f_sign_unittest.cc
+++ b/device/fido/u2f_sign_unittest.cc
@@ -11,12 +11,12 @@
 #include "crypto/ec_private_key.h"
 #include "crypto/sha2.h"
 #include "device/fido/authenticator_data.h"
-#include "device/fido/fake_u2f_device.h"
 #include "device/fido/fake_u2f_discovery.h"
 #include "device/fido/mock_u2f_device.h"
 #include "device/fido/sign_response_data.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_response_test_data.h"
+#include "device/fido/virtual_u2f_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -253,7 +253,7 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<test::FakeU2fDevice>();
+  auto device = std::make_unique<VirtualU2fDevice>();
   device->AddRegistration(key_handle, std::move(private_key),
                           GetTestRelyingPartyIdSHA256(), 42);
   discovery()->AddDevice(std::move(device));
diff --git a/device/fido/fake_u2f_device.cc b/device/fido/virtual_u2f_device.cc
similarity index 89%
rename from device/fido/fake_u2f_device.cc
rename to device/fido/virtual_u2f_device.cc
index 67ece10..c3c84be4 100644
--- a/device/fido/fake_u2f_device.cc
+++ b/device/fido/virtual_u2f_device.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 "device/fido/fake_u2f_device.h"
+#include "device/fido/virtual_u2f_device.h"
 
 #include <utility>
 
@@ -12,7 +12,6 @@
 #include "device/fido/u2f_apdu_command.h"
 
 namespace device {
-namespace test {
 
 namespace {
 
@@ -81,9 +80,9 @@
 
 }  // namespace
 
-FakeU2fDevice::RegistrationData::RegistrationData() = default;
+VirtualU2fDevice::RegistrationData::RegistrationData() = default;
 
-FakeU2fDevice::RegistrationData::RegistrationData(
+VirtualU2fDevice::RegistrationData::RegistrationData(
     std::unique_ptr<crypto::ECPrivateKey> private_key,
     std::vector<uint8_t> app_id_hash,
     uint32_t counter)
@@ -91,13 +90,13 @@
       app_id_hash(std::move(app_id_hash)),
       counter(counter) {}
 
-FakeU2fDevice::RegistrationData::RegistrationData(RegistrationData&& data) =
+VirtualU2fDevice::RegistrationData::RegistrationData(RegistrationData&& data) =
     default;
-FakeU2fDevice::RegistrationData& FakeU2fDevice::RegistrationData::operator=(
-    RegistrationData&& other) = default;
-FakeU2fDevice::RegistrationData::~RegistrationData() = default;
+VirtualU2fDevice::RegistrationData& VirtualU2fDevice::RegistrationData::
+operator=(RegistrationData&& other) = default;
+VirtualU2fDevice::RegistrationData::~RegistrationData() = default;
 
-FakeU2fDevice::FakeU2fDevice()
+VirtualU2fDevice::VirtualU2fDevice()
     : attestation_private_key_(
           crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey())),
       attestation_cert_(std::begin(kAttestationCert),
@@ -106,18 +105,18 @@
   DCHECK(attestation_private_key_);
 }
 
-FakeU2fDevice::~FakeU2fDevice() = default;
+VirtualU2fDevice::~VirtualU2fDevice() = default;
 
-void FakeU2fDevice::TryWink(WinkCallback cb) {
+void VirtualU2fDevice::TryWink(WinkCallback cb) {
   std::move(cb).Run();
 }
 
-std::string FakeU2fDevice::GetId() const {
+std::string VirtualU2fDevice::GetId() const {
   // Use our heap address to get a unique-ish number. (0xffe1 is a prime).
-  return "FakeU2fDevice-" + std::to_string((size_t)this % 0xffe1);
+  return "VirtualU2fDevice-" + std::to_string((size_t)this % 0xffe1);
 }
 
-void FakeU2fDevice::AddRegistration(
+void VirtualU2fDevice::AddRegistration(
     std::vector<uint8_t> key_handle,
     std::unique_ptr<crypto::ECPrivateKey> private_key,
     std::vector<uint8_t> app_id_hash,
@@ -126,8 +125,8 @@
       RegistrationData(std::move(private_key), std::move(app_id_hash), counter);
 }
 
-void FakeU2fDevice::DeviceTransact(std::vector<uint8_t> command,
-                                   DeviceCallback cb) {
+void VirtualU2fDevice::DeviceTransact(std::vector<uint8_t> command,
+                                      DeviceCallback cb) {
   // Note, here we are using the code-under-test in this fake.
   auto parsed_command = U2fApduCommand::CreateFromMessage(command);
   switch (parsed_command->ins_) {
@@ -149,15 +148,15 @@
   }
 }
 
-base::WeakPtr<U2fDevice> FakeU2fDevice::GetWeakPtr() {
+base::WeakPtr<U2fDevice> VirtualU2fDevice::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
-void FakeU2fDevice::DoRegister(uint8_t ins,
-                               uint8_t p1,
-                               uint8_t p2,
-                               base::span<const uint8_t> data,
-                               DeviceCallback cb) {
+void VirtualU2fDevice::DoRegister(uint8_t ins,
+                                  uint8_t p1,
+                                  uint8_t p2,
+                                  base::span<const uint8_t> data,
+                                  DeviceCallback cb) {
   if (data.size() != 64) {
     std::move(cb).Run(true, std::make_unique<U2fApduResponse>(
                                 std::vector<uint8_t>(),
@@ -226,11 +225,11 @@
                 std::move(response), U2fApduResponse::Status::SW_NO_ERROR));
 }
 
-void FakeU2fDevice::DoSign(uint8_t ins,
-                           uint8_t p1,
-                           uint8_t p2,
-                           base::span<const uint8_t> data,
-                           DeviceCallback cb) {
+void VirtualU2fDevice::DoSign(uint8_t ins,
+                              uint8_t p1,
+                              uint8_t p2,
+                              base::span<const uint8_t> data,
+                              DeviceCallback cb) {
   if (!(p1 == U2fApduCommand::kP1CheckOnly ||
         p1 == U2fApduCommand::kP1TupRequiredConsumed ||
         p1 == U2fApduCommand::kP1IndividualAttestation) ||
@@ -315,5 +314,4 @@
                 std::move(response), U2fApduResponse::Status::SW_NO_ERROR));
 }
 
-}  // namespace test
 }  // namespace device
diff --git a/device/fido/fake_u2f_device.h b/device/fido/virtual_u2f_device.h
similarity index 86%
rename from device/fido/fake_u2f_device.h
rename to device/fido/virtual_u2f_device.h
index 6c86d47ec..b6e3a774 100644
--- a/device/fido/fake_u2f_device.h
+++ b/device/fido/virtual_u2f_device.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 DEVICE_FIDO_FAKE_U2F_DEVICE_H_
-#define DEVICE_FIDO_FAKE_U2F_DEVICE_H_
+#ifndef DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
+#define DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
 
 #include <stdint.h>
 
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "base/component_export.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
 #include "device/fido/u2f_device.h"
@@ -21,12 +22,11 @@
 }  // namespace crypto
 
 namespace device {
-namespace test {
 
-class FakeU2fDevice : public U2fDevice {
+class COMPONENT_EXPORT(DEVICE_FIDO) VirtualU2fDevice : public U2fDevice {
  public:
-  FakeU2fDevice();
-  ~FakeU2fDevice() override;
+  VirtualU2fDevice();
+  ~VirtualU2fDevice() override;
 
   void AddRegistration(std::vector<uint8_t> key_handle,
                        std::unique_ptr<crypto::ECPrivateKey> private_key,
@@ -77,10 +77,9 @@
   std::map<std::vector<uint8_t>, RegistrationData> registrations_;
   base::WeakPtrFactory<U2fDevice> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(FakeU2fDevice);
+  DISALLOW_COPY_AND_ASSIGN(VirtualU2fDevice);
 };
 
-}  // namespace test
 }  // namespace device
 
-#endif  // DEVICE_FIDO_FAKE_U2F_DEVICE_H_
+#endif  // DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc
index 790137f..41defa93 100644
--- a/extensions/browser/content_verifier.cc
+++ b/extensions/browser/content_verifier.cc
@@ -206,6 +206,12 @@
     fetcher_->ExtensionUnloaded(extension);
 }
 
+GURL ContentVerifier::GetSignatureFetchUrlForTest(
+    const ExtensionId& extension_id,
+    const base::Version& extension_version) {
+  return delegate_->GetSignatureFetchUrl(extension_id, extension_version);
+}
+
 void ContentVerifier::OnFetchCompleteHelper(
     const std::string& extension_id,
     bool should_verify_any_paths_result) {
diff --git a/extensions/browser/content_verifier.h b/extensions/browser/content_verifier.h
index 1a41c80..d89c5a9e 100644
--- a/extensions/browser/content_verifier.h
+++ b/extensions/browser/content_verifier.h
@@ -74,6 +74,9 @@
                            const Extension* extension,
                            UnloadedExtensionReason reason) override;
 
+  GURL GetSignatureFetchUrlForTest(const ExtensionId& extension_id,
+                                   const base::Version& extension_version);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ContentVerifier);
 
diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc
index 906d1a1..30a5faf 100644
--- a/extensions/browser/content_verifier/test_utils.cc
+++ b/extensions/browser/content_verifier/test_utils.cc
@@ -13,18 +13,19 @@
 
 namespace extensions {
 
-TestContentVerifyJobObserver::TestContentVerifyJobObserver(
+// TestContentVerifySingleJobObserver ------------------------------------------
+TestContentVerifySingleJobObserver::TestContentVerifySingleJobObserver(
     const ExtensionId& extension_id,
     const base::FilePath& relative_path)
     : extension_id_(extension_id), relative_path_(relative_path) {
   ContentVerifyJob::SetObserverForTests(this);
 }
 
-TestContentVerifyJobObserver::~TestContentVerifyJobObserver() {
+TestContentVerifySingleJobObserver::~TestContentVerifySingleJobObserver() {
   ContentVerifyJob::SetObserverForTests(nullptr);
 }
 
-void TestContentVerifyJobObserver::JobFinished(
+void TestContentVerifySingleJobObserver::JobFinished(
     const ExtensionId& extension_id,
     const base::FilePath& relative_path,
     ContentVerifyJob::FailureReason reason) {
@@ -35,7 +36,7 @@
   job_finished_run_loop_.Quit();
 }
 
-void TestContentVerifyJobObserver::OnHashesReady(
+void TestContentVerifySingleJobObserver::OnHashesReady(
     const ExtensionId& extension_id,
     const base::FilePath& relative_path,
     bool success) {
@@ -47,18 +48,86 @@
 }
 
 ContentVerifyJob::FailureReason
-TestContentVerifyJobObserver::WaitForJobFinished() {
+TestContentVerifySingleJobObserver::WaitForJobFinished() {
   // Run() returns immediately if Quit() has already been called.
   job_finished_run_loop_.Run();
   EXPECT_TRUE(failure_reason_.has_value());
   return failure_reason_.value_or(ContentVerifyJob::FAILURE_REASON_MAX);
 }
 
-void TestContentVerifyJobObserver::WaitForOnHashesReady() {
+void TestContentVerifySingleJobObserver::WaitForOnHashesReady() {
   // Run() returns immediately if Quit() has already been called.
   on_hashes_ready_run_loop_.Run();
 }
 
+// TestContentVerifyJobObserver ------------------------------------------------
+void TestContentVerifyJobObserver::ExpectJobResult(
+    const ExtensionId& extension_id,
+    const base::FilePath& relative_path,
+    Result expected_result) {
+  expectations_.push_back(
+      ExpectedResult(extension_id, relative_path, expected_result));
+}
+
+TestContentVerifyJobObserver::TestContentVerifyJobObserver() {
+  EXPECT_TRUE(
+      content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_));
+  ContentVerifyJob::SetObserverForTests(this);
+}
+
+TestContentVerifyJobObserver::~TestContentVerifyJobObserver() {
+  ContentVerifyJob::SetObserverForTests(nullptr);
+}
+
+bool TestContentVerifyJobObserver::WaitForExpectedJobs() {
+  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_));
+  if (!expectations_.empty()) {
+    base::RunLoop run_loop;
+    job_quit_closure_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+  return expectations_.empty();
+}
+
+void TestContentVerifyJobObserver::JobStarted(
+    const ExtensionId& extension_id,
+    const base::FilePath& relative_path) {}
+
+void TestContentVerifyJobObserver::JobFinished(
+    const ExtensionId& extension_id,
+    const base::FilePath& relative_path,
+    ContentVerifyJob::FailureReason failure_reason) {
+  if (!content::BrowserThread::CurrentlyOn(creation_thread_)) {
+    content::BrowserThread::PostTask(
+        creation_thread_, FROM_HERE,
+        base::BindOnce(&TestContentVerifyJobObserver::JobFinished,
+                       base::Unretained(this), extension_id, relative_path,
+                       failure_reason));
+    return;
+  }
+  Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS
+                                                           : Result::FAILURE;
+  bool found = false;
+  for (std::list<ExpectedResult>::iterator i = expectations_.begin();
+       i != expectations_.end(); ++i) {
+    if (i->extension_id == extension_id && i->path == relative_path &&
+        i->result == result) {
+      found = true;
+      expectations_.erase(i);
+      break;
+    }
+  }
+  if (found) {
+    if (expectations_.empty() && job_quit_closure_)
+      std::move(job_quit_closure_).Run();
+  } else {
+    LOG(WARNING) << "Ignoring unexpected JobFinished " << extension_id << "/"
+                 << relative_path.value()
+                 << " failure_reason:" << failure_reason;
+  }
+}
+
+// MockContentVerifierDelegate ------------------------------------------------
 MockContentVerifierDelegate::MockContentVerifierDelegate() = default;
 MockContentVerifierDelegate::~MockContentVerifierDelegate() = default;
 
@@ -95,6 +164,32 @@
 
 void MockContentVerifierDelegate::Shutdown() {}
 
+// VerifierObserver -----------------------------------------------------------
+VerifierObserver::VerifierObserver() {
+  ContentVerifier::SetObserverForTests(this);
+}
+
+VerifierObserver::~VerifierObserver() {
+  ContentVerifier::SetObserverForTests(nullptr);
+}
+
+void VerifierObserver::WaitForFetchComplete(const ExtensionId& extension_id) {
+  EXPECT_TRUE(id_to_wait_for_.empty());
+  EXPECT_EQ(loop_runner_.get(), nullptr);
+  id_to_wait_for_ = extension_id;
+  loop_runner_ = new content::MessageLoopRunner();
+  loop_runner_->Run();
+  id_to_wait_for_.clear();
+  loop_runner_ = nullptr;
+}
+
+void VerifierObserver::OnFetchComplete(const ExtensionId& extension_id,
+                                       bool success) {
+  completed_fetches_.insert(extension_id);
+  if (extension_id == id_to_wait_for_)
+    loop_runner_->Quit();
+}
+
 namespace content_verifier_test_utils {
 
 scoped_refptr<Extension> UnzipToDirAndLoadExtension(
diff --git a/extensions/browser/content_verifier/test_utils.h b/extensions/browser/content_verifier/test_utils.h
index 93c3a5bb4..1797d3a 100644
--- a/extensions/browser/content_verifier/test_utils.h
+++ b/extensions/browser/content_verifier/test_utils.h
@@ -8,6 +8,9 @@
 #include "base/files/file_path.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/browser/content_verifier.h"
 #include "extensions/browser/content_verifier_delegate.h"
 #include "extensions/browser/content_verify_job.h"
 #include "extensions/common/extension_id.h"
@@ -16,14 +19,14 @@
 
 class Extension;
 
-// Test class to observe a particular extension resource's ContentVerifyJob
+// Test class to observe *a particular* extension resource's ContentVerifyJob
 // lifetime.  Provides a way to wait for a job to finish and return
 // the job's result.
-class TestContentVerifyJobObserver : ContentVerifyJob::TestObserver {
+class TestContentVerifySingleJobObserver : ContentVerifyJob::TestObserver {
  public:
-  TestContentVerifyJobObserver(const ExtensionId& extension_id,
-                               const base::FilePath& relative_path);
-  ~TestContentVerifyJobObserver();
+  TestContentVerifySingleJobObserver(const ExtensionId& extension_id,
+                                     const base::FilePath& relative_path);
+  ~TestContentVerifySingleJobObserver();
 
   // ContentVerifyJob::TestObserver:
   void JobStarted(const ExtensionId& extension_id,
@@ -50,6 +53,53 @@
   base::Optional<ContentVerifyJob::FailureReason> failure_reason_;
   bool seen_on_hashes_ready_ = false;
 
+  DISALLOW_COPY_AND_ASSIGN(TestContentVerifySingleJobObserver);
+};
+
+// Test class to observe expected set of ContentVerifyJobs.
+class TestContentVerifyJobObserver : public ContentVerifyJob::TestObserver {
+ public:
+  TestContentVerifyJobObserver();
+  virtual ~TestContentVerifyJobObserver();
+
+  enum class Result { SUCCESS, FAILURE };
+
+  // Call this to add an expected job result.
+  void ExpectJobResult(const ExtensionId& extension_id,
+                       const base::FilePath& relative_path,
+                       Result expected_result);
+
+  // Wait to see expected jobs. Returns true when we've seen all expected jobs
+  // finish, or false if there was an error or timeout.
+  bool WaitForExpectedJobs();
+
+  // ContentVerifyJob::TestObserver interface
+  void JobStarted(const ExtensionId& extension_id,
+                  const base::FilePath& relative_path) override;
+  void JobFinished(const ExtensionId& extension_id,
+                   const base::FilePath& relative_path,
+                   ContentVerifyJob::FailureReason failure_reason) override;
+  void OnHashesReady(const ExtensionId& extension_id,
+                     const base::FilePath& relative_path,
+                     bool success) override {}
+
+ private:
+  struct ExpectedResult {
+   public:
+    ExtensionId extension_id;
+    base::FilePath path;
+    Result result;
+
+    ExpectedResult(const ExtensionId& extension_id,
+                   const base::FilePath& path,
+                   Result result)
+        : extension_id(extension_id), path(path), result(result) {}
+  };
+  std::list<ExpectedResult> expectations_;
+  content::BrowserThread::ID creation_thread_;
+  // Accessed on |creation_thread_|.
+  base::OnceClosure job_quit_closure_;
+
   DISALLOW_COPY_AND_ASSIGN(TestContentVerifyJobObserver);
 };
 
@@ -76,6 +126,28 @@
   DISALLOW_COPY_AND_ASSIGN(MockContentVerifierDelegate);
 };
 
+// Observes ContentVerifier::OnFetchComplete of a particular extension.
+class VerifierObserver : public ContentVerifier::TestObserver {
+ public:
+  VerifierObserver();
+  virtual ~VerifierObserver();
+
+  const std::set<ExtensionId>& completed_fetches() {
+    return completed_fetches_;
+  }
+
+  // Returns when we've seen OnFetchComplete for |extension_id|.
+  void WaitForFetchComplete(const ExtensionId& extension_id);
+
+  // ContentVerifier::TestObserver
+  void OnFetchComplete(const ExtensionId& extension_id, bool success) override;
+
+ private:
+  std::set<ExtensionId> completed_fetches_;
+  ExtensionId id_to_wait_for_;
+  scoped_refptr<content::MessageLoopRunner> loop_runner_;
+};
+
 namespace content_verifier_test_utils {
 
 // Unzips the extension source from |extension_zip| into |unzip_dir|
diff --git a/extensions/browser/content_verify_job_unittest.cc b/extensions/browser/content_verify_job_unittest.cc
index cf4fa54..d43f0fc 100644
--- a/extensions/browser/content_verify_job_unittest.cc
+++ b/extensions/browser/content_verify_job_unittest.cc
@@ -61,7 +61,7 @@
       const base::FilePath& resource_path,
       std::string& resource_contents,
       ContentVerifyJobAsyncRunMode run_mode) {
-    TestContentVerifyJobObserver observer(extension.id(), resource_path);
+    TestContentVerifySingleJobObserver observer(extension.id(), resource_path);
     scoped_refptr<ContentVerifyJob> verify_job = new ContentVerifyJob(
         extension.id(), extension.version(), extension.path(), resource_path,
         ContentVerifierKey(kWebstoreSignaturesPublicKey,
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index c2342794..d4cd9741 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -157,10 +157,10 @@
 }  // namespace
 
 const char ExtensionDownloader::kUpdateInteractivityHeader[] =
-    "X-GoogleUpdate-Interactivity";
-const char ExtensionDownloader::kUpdateAppIdHeader[] = "X-GoogleUpdate-AppId";
+    "X-Goog-Update-Interactivity";
+const char ExtensionDownloader::kUpdateAppIdHeader[] = "X-Goog-Update-AppId";
 const char ExtensionDownloader::kUpdateUpdaterHeader[] =
-    "X-GoogleUpdate-Updater";
+    "X-Goog-Update-Updater";
 
 const char ExtensionDownloader::kUpdateInteractivityForeground[] = "fg";
 const char ExtensionDownloader::kUpdateInteractivityBackground[] = "bg";
diff --git a/gin/test/run_all_unittests.cc b/gin/test/run_all_unittests.cc
index 25500a6..b6a86bdd 100644
--- a/gin/test/run_all_unittests.cc
+++ b/gin/test/run_all_unittests.cc
@@ -10,6 +10,6 @@
   base::TestSuite test_suite(argc, argv);
 
   return base::LaunchUnitTests(
-      argc, argv, base::Bind(&base::TestSuite::Run,
-                             base::Unretained(&test_suite)));
+      argc, argv,
+      base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
 }
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index ea2eabd4..a24ae19b 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -147,11 +147,33 @@
     builder.set_data_enabled(true);
     builder.set_file_enabled(true);
     if (proxy_config_) {
-      // TODO(https://crbug.com/656607): Add proper traffic annotation.
+      net::NetworkTrafficAnnotationTag traffic_annotation =
+          net::DefineNetworkTrafficAnnotation("proxy_config_headless", R"(
+        semantics {
+          sender: "Proxy Config"
+          description:
+            "Creates a proxy based on configuration received from headless "
+            "command prompt."
+          trigger:
+            "User starts headless with proxy config."
+          data:
+            "Proxy configurations."
+          destination: OTHER
+          destination_other:
+            "The proxy server specified in the configuration."
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "This config is only used for headless mode and provided by user."
+          policy_exception_justification:
+            "This config is only used for headless mode and provided by user."
+        })");
+
       builder.set_proxy_resolution_service(
           net::ProxyResolutionService::CreateFixed(
-              net::ProxyConfigWithAnnotation(
-                  *proxy_config_, NO_TRAFFIC_ANNOTATION_BUG_656607)));
+              net::ProxyConfigWithAnnotation(*proxy_config_,
+                                             traffic_annotation)));
     } else {
       builder.set_proxy_config_service(std::move(proxy_config_service_));
     }
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index d45380a..0560ebb 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -618,9 +618,21 @@
       <message name="IDS_IOS_DOWNLOAD_MANAGER_UNABLE_TO_OPEN_FILE" desc="Title of dialog displayed when the user attempts to open a downloaded file and no app on the device can open the file. [Length: 25em] [iOS only]">
         Unable to Open File
       </message>
+      <message name="IDS_IOS_DOWNLOAD_MANAGER_FAILED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the download has failed. [Length: unlimited] [iOS only]">
+        Download failed
+      </message>
+      <message name="IDS_IOS_DOWNLOAD_MANAGER_SUCCEEDED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the download has sucessfully finished. [Length: unlimited] [iOS only]">
+        Download successfully finished
+      </message>
+      <message name="IDS_IOS_DOWNLOAD_MANAGER_REQUESTED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the Download Manager UI is shown to the user. [Length: unlimited] [iOS only]">
+        File download is available
+      </message>
       <message name="IDS_IOS_DOWNLOAD_MANAGER_UPLOAD_TO_GOOGLE_DRIVE" desc="Button for uploading a downloaded file to Google Drive. It's displayed on the dialog presented when no app on the device can open the file. [Length: 25em] [iOS only]">
         Upload to Google Drive
       </message>
+      <message name="IDS_IOS_DOWNLOAD_MANAGER_GOOGLE_DRIVE" desc="Button for installing Google Drive app. Google Drive is a product name and should use the correct localized version of the product name. [Length: 25em] [iOS only]">
+        Google Drive
+      </message>
       <message name="IDS_IOS_FACETIME_BUTTON" desc="Text in the confirmation dialog button that will initiate a FaceTime call for the presented number. [Length: 10em] [iOS only]">
         FaceTime
       </message>
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 0d64d617..df719f7 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -4778,15 +4778,13 @@
 
 - (id<ToolbarSnapshotProviding>)toolbarSnapshotProvider {
   id<ToolbarSnapshotProviding> toolbarSnapshotProvider = nil;
-  if (_toolbarCoordinator.viewController.view.hidden) {
-    Tab* currentTab = [_model currentTab];
-    if (currentTab.webState &&
-        UrlHasChromeScheme(currentTab.webState->GetLastCommittedURL())) {
-      // Use the native content controller's toolbar when the BVC's is hidden.
-      id nativeController = [self nativeControllerForTab:currentTab];
-      if ([nativeController conformsToProtocol:@protocol(ToolbarOwner)]) {
-        toolbarSnapshotProvider = [nativeController toolbarSnapshotProvider];
-      }
+  Tab* currentTab = [_model currentTab];
+  if (_toolbarCoordinator.viewController.view.hidden && currentTab.webState &&
+      UrlHasChromeScheme(currentTab.webState->GetLastCommittedURL())) {
+    // Use the native content controller's toolbar when the BVC's is hidden.
+    id nativeController = [self nativeControllerForTab:currentTab];
+    if ([nativeController conformsToProtocol:@protocol(ToolbarOwner)]) {
+      toolbarSnapshotProvider = [nativeController toolbarSnapshotProvider];
     }
   } else {
     toolbarSnapshotProvider = _toolbarCoordinator;
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn
index fa0f462..c0c8813e 100644
--- a/ios/chrome/browser/ui/download/BUILD.gn
+++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -44,6 +44,8 @@
     "//ios/chrome/browser/ui/presenters",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/web:web_internal",
+    "//ios/public/provider/chrome/browser",
+    "//ios/public/provider/chrome/browser/images",
     "//ios/third_party/material_components_ios",
     "//ios/third_party/material_roboto_font_loader_ios",
     "//ios/web",
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
index 13144709..3705f5f 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -69,7 +69,6 @@
   }
   [_confirmationDialog dismissViewControllerAnimated:YES completion:nil];
   _confirmationDialog = nil;
-  _mediator.SetDownloadTask(nullptr);
   _downloadTask = nullptr;
 
   [_storeKitCoordinator stop];
@@ -108,14 +107,9 @@
       l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_REPLACE_CONFIRMATION);
   NSString* message = l10n_util::GetNSString(
       IDS_IOS_DOWNLOAD_MANAGER_REPLACE_CONFIRMATION_MESSAGE);
-  __weak DownloadManagerCoordinator* weakSelf = self;
   [self runConfirmationDialogWithTitle:title
                                message:message
                      completionHandler:^(BOOL confirmed) {
-                       DownloadManagerCoordinator* strongSelf = weakSelf;
-                       if (strongSelf) {
-                         strongSelf->_mediator.SetDownloadTask(nullptr);
-                       }
                        handler(confirmed ? kNewDownloadPolicyReplace
                                          : kNewDownloadPolicyDiscard);
                      }];
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.h b/ios/chrome/browser/ui/download/download_manager_mediator.h
index f68b538..a6e618e5 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator.h
+++ b/ios/chrome/browser/ui/download/download_manager_mediator.h
@@ -60,8 +60,13 @@
   // Converts DownloadTask progress [0;100] to float progress [0.0f;1.0f].
   float GetDownloadManagerProgress() const;
 
+  // Returns accessibility announcement for download state change. -1 if there
+  // is no announcement.
+  int GetDownloadManagerA11yAnnouncement() const;
+
   // web::DownloadTaskObserver overrides:
   void OnDownloadUpdated(web::DownloadTask* task) override;
+  void OnDownloadDestroyed(web::DownloadTask* task) override;
 
   web::DownloadTask* task_ = nullptr;
   __weak id<DownloadManagerConsumer> consumer_ = nil;
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.mm b/ios/chrome/browser/ui/download/download_manager_mediator.mm
index 6ab8290..48117b8 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_mediator.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/download/download_manager_mediator.h"
 
+#include <UIKit/UIKit.h>
+
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -11,16 +13,20 @@
 #include "base/task_scheduler/post_task.h"
 #include "ios/chrome/browser/download/download_directory_util.h"
 #import "ios/chrome/browser/download/google_drive_app_util.h"
+#include "ios/chrome/grit/ios_strings.h"
 #import "ios/web/public/download/download_task.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_fetcher_response_writer.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
 DownloadManagerMediator::DownloadManagerMediator() : weak_ptr_factory_(this) {}
-DownloadManagerMediator::~DownloadManagerMediator() {}
+DownloadManagerMediator::~DownloadManagerMediator() {
+  SetDownloadTask(nullptr);
+}
 
 void DownloadManagerMediator::SetConsumer(
     id<DownloadManagerConsumer> consumer) {
@@ -90,6 +96,10 @@
   UpdateConsumer();
 }
 
+void DownloadManagerMediator::OnDownloadDestroyed(web::DownloadTask* task) {
+  SetDownloadTask(nullptr);
+}
+
 void DownloadManagerMediator::UpdateConsumer() {
   DownloadManagerState state = GetDownloadManagerState();
   if (state == kDownloadManagerStateSucceeded && !IsGoogleDriveAppInstalled()) {
@@ -102,6 +112,12 @@
   [consumer_ setProgress:GetDownloadManagerProgress()];
   [consumer_
       setFileName:base::SysUTF16ToNSString(task_->GetSuggestedFilename())];
+
+  int a11y_announcement = GetDownloadManagerA11yAnnouncement();
+  if (a11y_announcement != -1) {
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    l10n_util::GetNSString(a11y_announcement));
+  }
 }
 
 DownloadManagerState DownloadManagerMediator::GetDownloadManagerState() const {
@@ -119,6 +135,20 @@
   }
 }
 
+int DownloadManagerMediator::GetDownloadManagerA11yAnnouncement() const {
+  switch (task_->GetState()) {
+    case web::DownloadTask::State::kNotStarted:
+      return IDS_IOS_DOWNLOAD_MANAGER_REQUESTED_ACCESSIBILITY_ANNOUNCEMENT;
+    case web::DownloadTask::State::kComplete:
+      return task_->GetErrorCode()
+                 ? IDS_IOS_DOWNLOAD_MANAGER_FAILED_ACCESSIBILITY_ANNOUNCEMENT
+                 : IDS_IOS_DOWNLOAD_MANAGER_SUCCEEDED_ACCESSIBILITY_ANNOUNCEMENT;
+    case web::DownloadTask::State::kCancelled:
+    case web::DownloadTask::State::kInProgress:
+      return -1;
+  }
+}
+
 float DownloadManagerMediator::GetDownloadManagerProgress() const {
   if (task_->GetPercentComplete() == -1)
     return 0.0f;
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
index 51441ed..fd62498c 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
@@ -82,8 +82,6 @@
   base::FilePath download_dir;
   ASSERT_TRUE(GetDownloadsDirectory(&download_dir));
   EXPECT_TRUE(download_dir.IsParent(file));
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests starting and failing the download. Simulates download failure from
@@ -100,8 +98,6 @@
     return consumer_.state == kDownloadManagerStateFailed;
   }));
   EXPECT_FALSE(consumer_.installDriveButtonVisible);
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests that consumer is updated right after it's set.
@@ -124,8 +120,6 @@
   EXPECT_EQ(kTestTotalBytes, consumer_.countOfBytesExpectedToReceive);
   EXPECT_EQ(kTestReceivedBytes, consumer_.countOfBytesReceived);
   EXPECT_FLOAT_EQ(0.8f, consumer_.progress);
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests that consumer changes the state to kDownloadManagerStateFailed if task
@@ -138,8 +132,6 @@
   task()->SetDone(true);
   EXPECT_EQ(kDownloadManagerStateFailed, consumer_.state);
   EXPECT_FALSE(consumer_.installDriveButtonVisible);
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests that consumer changes the state to kDownloadManagerStateSucceeded if
@@ -153,8 +145,6 @@
   task()->SetDone(true);
   EXPECT_EQ(kDownloadManagerStateSucceeded, consumer_.state);
   EXPECT_FALSE(consumer_.installDriveButtonVisible);
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests that consumer changes the state to kDownloadManagerStateSucceeded if
@@ -169,8 +159,6 @@
   task()->SetDone(true);
   EXPECT_EQ(kDownloadManagerStateSucceeded, consumer_.state);
   EXPECT_TRUE(consumer_.installDriveButtonVisible);
-
-  mediator_.SetDownloadTask(nullptr);
 }
 
 // Tests that consumer changes the state to kDownloadManagerStateInProgress if
@@ -183,6 +171,4 @@
   EXPECT_EQ(kDownloadManagerStateInProgress, consumer_.state);
   EXPECT_FALSE(consumer_.installDriveButtonVisible);
   EXPECT_EQ(0.0, consumer_.progress);
-
-  mediator_.SetDownloadTask(nullptr);
 }
diff --git a/ios/chrome/browser/ui/download/download_manager_view_controller.h b/ios/chrome/browser/ui/download/download_manager_view_controller.h
index b9db9cc..e5a23a8 100644
--- a/ios/chrome/browser/ui/download/download_manager_view_controller.h
+++ b/ios/chrome/browser/ui/download/download_manager_view_controller.h
@@ -68,6 +68,14 @@
 // setInstallGoogleDriveButtonVisible:animated: was called with YES.
 @property(nonatomic, readonly) UIButton* installDriveButton;
 
+// Install Google Drive app icon. Only visible if
+// setInstallGoogleDriveButtonVisible:animated: was called with YES.
+@property(nonatomic, readonly) UIImageView* installDriveIcon;
+
+// Install Google Drive label. Only visible if
+// setInstallGoogleDriveButtonVisible:animated: was called with YES.
+@property(nonatomic, readonly) UILabel* installDriveLabel;
+
 // View that represents download progress.
 @property(nonatomic, readonly) RadialProgressView* progressView;
 
diff --git a/ios/chrome/browser/ui/download/download_manager_view_controller.mm b/ios/chrome/browser/ui/download/download_manager_view_controller.mm
index f8c57230..51a7d1e2 100644
--- a/ios/chrome/browser/ui/download/download_manager_view_controller.mm
+++ b/ios/chrome/browser/ui/download/download_manager_view_controller.mm
@@ -10,6 +10,8 @@
 #import "ios/chrome/browser/ui/download/radial_progress_view.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #include "ios/chrome/grit/ios_strings.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#import "ios/public/provider/chrome/browser/images/branded_image_provider.h"
 #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -45,6 +47,8 @@
   UILabel* _statusLabel;
   UIButton* _actionButton;
   UIButton* _installDriveButton;
+  UIImageView* _installDriveIcon;
+  UILabel* _installDriveLabel;
   RadialProgressView* _progressView;
 
   NSString* _fileName;
@@ -107,6 +111,8 @@
   [self.downloadControlsRow addSubview:self.progressView];
   [self.downloadControlsRow addSubview:self.actionButton];
   [self.installDriveControlsRow addSubview:self.installDriveButton];
+  [self.installDriveControlsRow addSubview:self.installDriveIcon];
+  [self.installDriveControlsRow addSubview:self.installDriveLabel];
   [self.installDriveControlsRow addSubview:self.horizontalLine];
 
   NamedGuide* actionButtonGuide =
@@ -225,6 +231,29 @@
                        constant:-kElementMargin],
   ]];
 
+  // install google drive icon constraints.
+  UIImageView* installDriveIcon = self.installDriveIcon;
+  [NSLayoutConstraint activateConstraints:@[
+    [installDriveIcon.centerYAnchor
+        constraintEqualToAnchor:installDriveRow.centerYAnchor],
+    [installDriveIcon.leadingAnchor
+        constraintEqualToAnchor:installDriveRow.layoutMarginsGuide
+                                    .leadingAnchor],
+  ]];
+
+  // install google drive label constraints.
+  UILabel* installDriveLabel = self.installDriveLabel;
+  [NSLayoutConstraint activateConstraints:@[
+    [installDriveLabel.centerYAnchor
+        constraintEqualToAnchor:installDriveRow.centerYAnchor],
+    [installDriveLabel.leadingAnchor
+        constraintEqualToAnchor:installDriveIcon.trailingAnchor
+                       constant:kElementMargin],
+    [installDriveLabel.trailingAnchor
+        constraintLessThanOrEqualToAnchor:installDriveButton.leadingAnchor
+                                 constant:-kElementMargin],
+  ]];
+
   // constraint line which separates download controls and install drive rows.
   UIView* horizontalLine = self.horizontalLine;
   [NSLayoutConstraint activateConstraints:@[
@@ -401,6 +430,29 @@
   return _installDriveButton;
 }
 
+- (UIImageView*)installDriveIcon {
+  if (!_installDriveIcon) {
+    _installDriveIcon = [[UIImageView alloc] initWithFrame:CGRectZero];
+    _installDriveIcon.translatesAutoresizingMaskIntoConstraints = NO;
+    _installDriveIcon.image = ios::GetChromeBrowserProvider()
+                                  ->GetBrandedImageProvider()
+                                  ->GetDownloadGoogleDriveImage();
+  }
+  return _installDriveIcon;
+}
+
+- (UILabel*)installDriveLabel {
+  if (!_installDriveLabel) {
+    _installDriveLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    _installDriveLabel.translatesAutoresizingMaskIntoConstraints = NO;
+    _installDriveLabel.font = [MDCTypography subheadFont];
+    _installDriveLabel.text =
+        l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_GOOGLE_DRIVE);
+    [_installDriveLabel sizeToFit];
+  }
+  return _installDriveLabel;
+}
+
 - (RadialProgressView*)progressView {
   if (!_progressView) {
     _progressView = [[RadialProgressView alloc] initWithFrame:CGRectZero];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h
index 3b6c10f9..446e4d1 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h
@@ -12,6 +12,9 @@
 // text and the cursor position.
 - (void)updateOmniboxState;
 
+// Notifies consumer to defocus the omnibox (for example on tab change).
+- (void)defocusOmnibox;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index a228f0d..3384e3d 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -142,16 +142,6 @@
   return self.omniboxPopupCoordinator.hasResults;
 }
 
-#pragma mark - LocationBarConsumer
-
-- (void)updateOmniboxState {
-  if (!_locationBarController)
-    return;
-  _locationBarController->SetShouldShowHintText(
-      [self.delegate shouldDisplayHintText]);
-  _locationBarController->OnToolbarUpdated();
-}
-
 - (BOOL)showingOmniboxPopup {
   OmniboxViewIOS* omniboxViewIOS = static_cast<OmniboxViewIOS*>(
       _locationBarController.get()->GetLocationEntry());
@@ -178,6 +168,20 @@
   [self.locationBarView addContractOmniboxAnimations:animator];
 }
 
+#pragma mark - LocationBarConsumer
+
+- (void)updateOmniboxState {
+  if (!_locationBarController)
+    return;
+  _locationBarController->SetShouldShowHintText(
+      [self.delegate shouldDisplayHintText]);
+  _locationBarController->OnToolbarUpdated();
+}
+
+- (void)defocusOmnibox {
+  [self cancelOmniboxEdit];
+}
+
 #pragma mark - VoiceSearchControllerDelegate
 
 - (void)receiveVoiceSearchResult:(NSString*)result {
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
index 35f6b12..75211757 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -115,6 +115,7 @@
                      reason:(int)reason {
   DCHECK_EQ(_webStateList, webStateList);
   self.webState = newWebState;
+  [self.consumer defocusOmnibox];
 }
 
 #pragma mark - Setters
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm
index 2fd0fe8..df4e714 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm
@@ -213,3 +213,15 @@
 
   EXPECT_OCMOCK_VERIFY(consumer_);
 }
+
+// Test the omnibox is defocused when the active webstate is changed.
+TEST_F(LocationBarMediatorTest, TestChangeActiveWebState) {
+  mediator_.webStateList = web_state_list_.get();
+  SetUpActiveWebState();
+  mediator_.consumer = consumer_;
+
+  OCMExpect([consumer_ defocusOmnibox]);
+  web_state_list_->ActivateWebStateAt(1);
+
+  EXPECT_OCMOCK_VERIFY(consumer_);
+}
diff --git a/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm
index 26e907d..54c011ad 100644
--- a/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm
+++ b/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm
@@ -132,14 +132,7 @@
 // Tests that a bookmark added on the client (before Sync is enabled) is
 // uploaded to the Sync server once Sync is turned on.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncUploadBookmarkOnFirstSync \
-  FLAKY_testSyncUploadBookmarkOnFirstSync
-#else
-#define MAYBE_testSyncUploadBookmarkOnFirstSync \
-  testSyncUploadBookmarkOnFirstSync
-#endif
-- (void)MAYBE_testSyncUploadBookmarkOnFirstSync {
+- (void)FLAKY_testSyncUploadBookmarkOnFirstSync {
   [self addBookmark:GURL("https://www.foo.com") withTitle:@"foo"];
 
   // Sign in to sync, after a bookmark has been added.
@@ -155,12 +148,7 @@
 
 // Tests that a bookmark added on the client is uploaded to the Sync server.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncUploadBookmark FLAKY_testSyncUploadBookmark
-#else
-#define MAYBE_testSyncUploadBookmark testSyncUploadBookmark
-#endif
-- (void)MAYBE_testSyncUploadBookmark {
+- (void)FLAKY_testSyncUploadBookmark {
   ChromeIdentity* identity = [SigninEarlGreyUtils fakeIdentity1];
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
       identity);
@@ -175,12 +163,7 @@
 // Tests that a bookmark injected in the FakeServer is synced down to the
 // client.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncDownloadBookmark FLAKY_testSyncDownloadBookmark
-#else
-#define MAYBE_testSyncDownloadBookmark testSyncDownloadBookmark
-#endif
-- (void)MAYBE_testSyncDownloadBookmark {
+- (void)FLAKY_testSyncDownloadBookmark {
   [[self class] assertBookmarksWithTitle:@"hoo" expectedCount:0];
   chrome_test_util::InjectBookmarkOnFakeSyncServer("http://www.hoo.com", "hoo");
 
@@ -282,7 +265,14 @@
 }
 
 // Tests that autofill profile injected in FakeServer gets synced to client.
-- (void)testSyncDownloadAutofillProfile {
+// TODO(crbug.com/814990): Reenable the test.
+#if TARGET_IPHONE_SIMULATOR
+#define MAYBE_testSyncDownloadAutofillProfile testSyncDownloadAutofillProfile
+#else
+#define MAYBE_testSyncDownloadAutofillProfile \
+  FLAKY_testSyncDownloadAutofillProfile
+#endif
+- (void)MAYBE_testSyncDownloadAutofillProfile {
   const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E";
   const std::string kFullName = "Peter Pan";
   GREYAssertFalse(chrome_test_util::IsAutofillProfilePresent(kGuid, kFullName),
@@ -308,12 +298,7 @@
 // Test that update to autofill profile injected in FakeServer gets synced to
 // client.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncUpdateAutofillProfile FLAKY_testSyncUpdateAutofillProfile
-#else
-#define MAYBE_testSyncUpdateAutofillProfile testSyncUpdateAutofillProfile
-#endif
-- (void)MAYBE_testSyncUpdateAutofillProfile {
+- (void)FLAKY_testSyncUpdateAutofillProfile {
   const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E";
   const std::string kFullName = "Peter Pan";
   const std::string kUpdatedFullName = "Roger Rabbit";
@@ -358,12 +343,7 @@
 // Test that autofill profile deleted from FakeServer gets deleted from client
 // as well.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncDeleteAutofillProfile FLAKY_testSyncDeleteAutofillProfile
-#else
-#define MAYBE_testSyncDeleteAutofillProfile testSyncDeleteAutofillProfile
-#endif
-- (void)MAYBE_testSyncDeleteAutofillProfile {
+- (void)FLAKY_testSyncDeleteAutofillProfile {
   const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E";
   const std::string kFullName = "Peter Pan";
   GREYAssertFalse(chrome_test_util::IsAutofillProfilePresent(kGuid, kFullName),
@@ -398,12 +378,7 @@
 // Tests that tabs opened on this client are committed to the Sync server and
 // that the created sessions entities are correct.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncUploadOpenTabs FLAKY_testSyncUploadOpenTabs
-#else
-#define MAYBE_testSyncUploadOpenTabs testSyncUploadOpenTabs
-#endif
-- (void)MAYBE_testSyncUploadOpenTabs {
+- (void)FLAKY_testSyncUploadOpenTabs {
   // Create map of canned responses and set up the test HTML server.
   const GURL URL1 = web::test::HttpServer::MakeUrl("http://page1");
   const GURL URL2 = web::test::HttpServer::MakeUrl("http://page2");
@@ -438,12 +413,7 @@
 // Tests that a typed URL (after Sync is enabled) is uploaded to the Sync
 // server.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncTypedURLUpload FLAKY_testSyncTypedURLUpload
-#else
-#define MAYBE_testSyncTypedURLUpload testSyncTypedURLUpload
-#endif
-- (void)MAYBE_testSyncTypedURLUpload {
+- (void)FLAKY_testSyncTypedURLUpload {
   const GURL mockURL("http://not-a-real-site/");
 
   GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
@@ -483,12 +453,7 @@
 
 // Tests that typed url is downloaded from sync server.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncTypedUrlDownload FLAKY_testSyncTypedUrlDownload
-#else
-#define MAYBE_testSyncTypedUrlDownload testSyncTypedUrlDownload
-#endif
-- (void)MAYBE_testSyncTypedUrlDownload {
+- (void)FLAKY_testSyncTypedUrlDownload {
   const GURL mockURL("http://not-a-real-site/");
 
   GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
@@ -526,13 +491,7 @@
 // Tests that when typed url is deleted on the client, sync the change gets
 // propagated to server.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncTypedURLDeleteFromClient \
-  FLAKY_testSyncTypedURLDeleteFromClient
-#else
-#define MAYBE_testSyncTypedURLDeleteFromClient testSyncTypedURLDeleteFromClient
-#endif
-- (void)MAYBE_testSyncTypedURLDeleteFromClient {
+- (void)FLAKY_testSyncTypedURLDeleteFromClient {
   const GURL mockURL("http://not-a-real-site/");
 
   GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
@@ -581,13 +540,7 @@
 // Test that typed url is deleted from client after server sends tombstone for
 // that typed url.
 // TODO(crbug.com/814990): Reenable the test.
-#if TARGET_IPHONE_SIMULATOR
-#define MAYBE_testSyncTypedURLDeleteFromServer \
-  FLAKY_testSyncTypedURLDeleteFromServer
-#else
-#define MAYBE_testSyncTypedURLDeleteFromServer testSyncTypedURLDeleteFromServer
-#endif
-- (void)MAYBE_testSyncTypedURLDeleteFromServer {
+- (void)FLAKY_testSyncTypedURLDeleteFromServer {
   const GURL mockURL("http://not-a-real-site/");
 
   GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn
index cf1daa40..d2526ab 100644
--- a/ios/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -58,7 +58,6 @@
     "tab_grid_top_toolbar.mm",
     "tab_grid_transition_handler.h",
     "tab_grid_transition_handler.mm",
-    "tab_grid_transition_state_provider.h",
     "tab_grid_view_controller.h",
     "tab_grid_view_controller.mm",
     "top_aligned_image_view.h",
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.h b/ios/chrome/browser/ui/tab_grid/grid_cell.h
index 0399e21..9778ed2 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_cell.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_cell.h
@@ -30,6 +30,11 @@
 @property(nonatomic, weak) UIImage* icon;
 @property(nonatomic, weak) UIImage* snapshot;
 @property(nonatomic, copy) NSString* title;
+
+// Returns a cell with the same theme, icon, snapshot, and title as the reciever
+// (but no delegate or identifier) for use in animated transitions.
+- (GridCell*)proxyForTransitions;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CELL_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
index 86db00e..0b5a891 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_cell.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
@@ -176,6 +176,16 @@
   _title = title;
 }
 
+- (GridCell*)proxyForTransitions {
+  GridCell* proxy = [[[self class] alloc] initWithFrame:self.bounds];
+  proxy.selected = NO;
+  proxy.theme = self.theme;
+  proxy.icon = self.icon;
+  proxy.snapshot = self.snapshot;
+  proxy.title = self.title;
+  return proxy;
+}
+
 #pragma mark - Private
 
 // Sets up the top bar with icon, title, and close button.
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
index f34e714..7f2bb0b37 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/tab_grid/grid_theme.h"
 
 @protocol GridImageDataSource;
+@class GridTransitionLayout;
 @class GridViewController;
 
 // Protocol used to relay relevant user interactions from a grid UI.
@@ -45,6 +46,13 @@
 @property(nonatomic, weak) id<GridViewControllerDelegate> delegate;
 // Data source for images.
 @property(nonatomic, weak) id<GridImageDataSource> imageDataSource;
+// YES if the selected cell is visible in the grid.
+@property(nonatomic, readonly, getter=isSelectedCellVisible)
+    BOOL selectedCellVisible;
+
+// Returns the layout of the grid for use in an animated transition.
+- (GridTransitionLayout*)transitionLayout;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
index 3f9a9e53..b32d0e5c 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
@@ -4,15 +4,14 @@
 
 #import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h"
 
-#import "base/ios/block_types.h"
 #import "base/mac/foundation_util.h"
 #import "base/numerics/safe_conversions.h"
-#include "ios/chrome/browser/procedural_block_types.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_cell.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_item.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_layout.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -106,6 +105,39 @@
   return self.items.count == 0;
 }
 
+- (BOOL)isSelectedCellVisible {
+  if (self.collectionView.indexPathsForSelectedItems.count == 0)
+    return NO;
+  return [self.collectionView.indexPathsForVisibleItems
+      containsObject:self.collectionView.indexPathsForSelectedItems
+                         .firstObject];
+}
+
+- (GridTransitionLayout*)transitionLayout {
+  [self.collectionView layoutIfNeeded];
+  NSMutableArray<GridTransitionLayoutItem*>* items =
+      [[NSMutableArray alloc] init];
+  GridTransitionLayoutItem* selectedItem;
+  for (NSIndexPath* path in self.collectionView.indexPathsForVisibleItems) {
+    GridCell* cell = base::mac::ObjCCastStrict<GridCell>(
+        [self.collectionView cellForItemAtIndexPath:path]);
+    UICollectionViewLayoutAttributes* attributes =
+        [self.collectionView layoutAttributesForItemAtIndexPath:path];
+    // Normalize frame to window coordinates. The attributes class applies this
+    // change to the other properties such as center, bounds, etc.
+    attributes.frame =
+        [self.collectionView convertRect:attributes.frame toView:nil];
+    GridTransitionLayoutItem* item =
+        [GridTransitionLayoutItem itemWithCell:[cell proxyForTransitions]
+                                    attributes:attributes];
+    [items addObject:item];
+    if (cell.selected) {
+      selectedItem = item;
+    }
+  }
+  return [GridTransitionLayout layoutWithItems:items selectedItem:selectedItem];
+}
+
 #pragma mark - UICollectionViewDataSource
 
 - (NSInteger)collectionView:(UICollectionView*)collectionView
@@ -174,7 +206,7 @@
 - (void)insertItem:(GridItem*)item
            atIndex:(NSUInteger)index
      selectedIndex:(NSUInteger)selectedIndex {
-  ProceduralBlock performDataSourceUpdates = ^{
+  auto performDataSourceUpdates = ^{
     [self.items insertObject:item atIndex:index];
     self.selectedIndex = selectedIndex;
   };
@@ -182,16 +214,16 @@
     performDataSourceUpdates();
     return;
   }
-  ProceduralBlock performAllUpdates = ^{
+  auto performAllUpdates = ^{
     performDataSourceUpdates();
     self.collectionView.backgroundView.hidden = YES;
     [self.collectionView insertItemsAtIndexPaths:@[ CreateIndexPath(index) ]];
+  };
+  auto completion = ^(BOOL finished) {
     [self.collectionView
         selectItemAtIndexPath:CreateIndexPath(selectedIndex)
                      animated:YES
                scrollPosition:UICollectionViewScrollPositionNone];
-  };
-  ProceduralBlockWithBool completion = ^(BOOL finished) {
     if (self.items.count == 1) {
       [self.delegate firstItemWasAddedInGridViewController:self];
     }
@@ -202,7 +234,7 @@
 
 - (void)removeItemAtIndex:(NSUInteger)index
             selectedIndex:(NSUInteger)selectedIndex {
-  ProceduralBlock performDataSourceUpdates = ^{
+  auto performDataSourceUpdates = ^{
     [self.items removeObjectAtIndex:index];
     self.selectedIndex = selectedIndex;
   };
@@ -210,18 +242,17 @@
     performDataSourceUpdates();
     return;
   }
-  ProceduralBlock performAllUpdates = ^{
+  auto performAllUpdates = ^{
     performDataSourceUpdates();
     [self.collectionView deleteItemsAtIndexPaths:@[ CreateIndexPath(index) ]];
+  };
+  auto completion = ^(BOOL finished) {
     if (self.items.count > 0) {
       [self.collectionView
           selectItemAtIndexPath:CreateIndexPath(selectedIndex)
                        animated:YES
                  scrollPosition:UICollectionViewScrollPositionNone];
-    }
-  };
-  ProceduralBlockWithBool completion = ^(BOOL finished) {
-    if (self.items.count == 0) {
+    } else {
       self.collectionView.backgroundView.hidden = NO;
       [self.delegate lastItemWasClosedInGridViewController:self];
     }
@@ -250,7 +281,7 @@
 - (void)moveItemFromIndex:(NSUInteger)fromIndex
                   toIndex:(NSUInteger)toIndex
             selectedIndex:(NSUInteger)selectedIndex {
-  ProceduralBlock performDataSourceUpdates = ^{
+  auto performDataSourceUpdates = ^{
     GridItem* item = self.items[fromIndex];
     [self.items removeObjectAtIndex:fromIndex];
     [self.items insertObject:item atIndex:toIndex];
@@ -260,16 +291,19 @@
     performDataSourceUpdates();
     return;
   }
-  ProceduralBlock performAllUpdates = ^{
+  auto performAllUpdates = ^{
     performDataSourceUpdates();
     [self.collectionView moveItemAtIndexPath:CreateIndexPath(fromIndex)
                                  toIndexPath:CreateIndexPath(toIndex)];
+  };
+  auto completion = ^(BOOL finished) {
     [self.collectionView
         selectItemAtIndexPath:CreateIndexPath(selectedIndex)
                      animated:YES
                scrollPosition:UICollectionViewScrollPositionNone];
   };
-  [self.collectionView performBatchUpdates:performAllUpdates completion:nil];
+  [self.collectionView performBatchUpdates:performAllUpdates
+                                completion:completion];
 }
 
 #pragma mark - Private
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index 36125dc..1057c34 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -85,6 +85,7 @@
       [[TabGridViewController alloc] init];
   self.transitionHandler = [[TabGridTransitionHandler alloc] init];
   self.transitionHandler.provider = mainViewController;
+  mainViewController.modalPresentationStyle = UIModalPresentationCustom;
   mainViewController.transitioningDelegate = self.transitionHandler;
   mainViewController.tabPresentationDelegate = self;
   _mainViewController = mainViewController;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h
index bc04bb1..38b57dca 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h
@@ -7,12 +7,12 @@
 
 #import <UIKit/UIKit.h>
 
-@protocol TabGridTransitionStateProvider;
+@protocol GridTransitionStateProviding;
 
 @interface TabGridTransitionHandler
     : NSObject<UIViewControllerTransitioningDelegate>
 
-@property(nonatomic, weak) id<TabGridTransitionStateProvider> provider;
+@property(nonatomic, weak) id<GridTransitionStateProviding> provider;
 
 @end
 
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
index 6582ec35..b1b15d9 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
@@ -4,9 +4,9 @@
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h"
 
-#import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h"
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_hidden_tab_animator.h"
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h"
 #import "ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -24,7 +24,7 @@
                      presentingController:(UIViewController*)presenting
                          sourceController:(UIViewController*)source {
   id<UIViewControllerAnimatedTransitioning> animator;
-  if (self.provider.selectedTabVisible) {
+  if (self.provider.selectedCellVisible) {
     // This will be a GridToVisibleTabAnimator eventually.
     animator = [[GridToHiddenTabAnimator alloc] init];
   } else {
@@ -35,8 +35,7 @@
 
 - (id<UIViewControllerAnimatedTransitioning>)
 animationControllerForDismissedController:(UIViewController*)dismissed {
-  // This will be a TabToGridAnimator eventually.
-  return nil;
+  return [[TabToGridAnimator alloc] initWithStateProvider:self.provider];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h
deleted file mode 100644
index 7ee09fb..0000000
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h
+++ /dev/null
@@ -1,19 +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 IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_
-#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_
-
-#import <Foundation/Foundation.h>
-
-// Objects conforming to this protocol can provide state information to
-// transition delegates and animators for the tab grid.
-@protocol TabGridTransitionStateProvider
-
-// YES if the currently selected tab is visible in the tab grid.
-@property(nonatomic, readonly) BOOL selectedTabVisible;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
index 0f9882f7..50d4734c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -8,7 +8,7 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h"
-#import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h"
 
 @protocol GridConsumer;
 @protocol GridCommands;
@@ -25,10 +25,10 @@
 - (void)showActiveTab;
 @end
 
-// View controller representing a tab switcher.  The tab switcher has an
+// View controller representing a tab switcher. The tab switcher has an
 // incognito tab grid, regular tab grid, and remote tabs.
 @interface TabGridViewController
-    : UIViewController<TabGridPaging, TabGridTransitionStateProvider>
+    : UIViewController<TabGridPaging, GridTransitionStateProviding>
 
 // Delegate for this view controller to handle presenting tab UI.
 @property(nonatomic, weak) id<TabPresentationDelegate> tabPresentationDelegate;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 6c8bfe3..ab798ea 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -33,6 +33,7 @@
 @property(nonatomic, weak) TabGridBottomToolbar* bottomToolbar;
 @property(nonatomic, weak) UIButton* closeAllButton;
 @property(nonatomic, weak) UIButton* doneButton;
+@property(nonatomic, weak) UIButton* createTabButton;
 @property(nonatomic, weak) UIButton* floatingButton;
 @end
 
@@ -55,6 +56,7 @@
 @synthesize bottomToolbar = _bottomToolbar;
 @synthesize closeAllButton = _closeAllButton;
 @synthesize doneButton = _doneButton;
+@synthesize createTabButton = _createTabButton;
 @synthesize floatingButton = _floatingButton;
 
 - (instancetype)init {
@@ -75,16 +77,16 @@
   [self setupRegularTabsViewController];
   [self setupRemoteTabsViewController];
   [self setupTopToolbar];
-  [self setupTopToolbarButtons];
   [self setupBottomToolbar];
-  [self setupBottomToolbarButtons];
+  [self setupFloatingButton];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
   // Call the current page setter to sync the scroll view offset to the current
   // page value.
   self.currentPage = _currentPage;
-  [self updateDoneAndCloseAllButtons];
+  [self updateToolbarsForCurrentSizeClass];
+  [self enableButtonsForCurrentPage];
   if (animated && self.transitionCoordinator) {
     [self animateToolbarsForAppearance];
   }
@@ -124,7 +126,7 @@
   float fractionalPage = scrollView.contentOffset.x / pageWidth;
   NSUInteger page = lround(fractionalPage);
   _currentPage = static_cast<TabGridPage>(page);
-  [self updateDoneAndCloseAllButtons];
+  [self enableButtonsForCurrentPage];
 }
 
 #pragma mark - UIScrollViewAccessibilityDelegate
@@ -142,10 +144,39 @@
   }
 }
 
-#pragma mark - TabGridTransitionStateProvider properties
+#pragma mark - GridTransitionStateProviding properties
 
-- (BOOL)selectedTabVisible {
-  return NO;
+- (BOOL)isSelectedCellVisible {
+  switch (self.currentPage) {
+    case TabGridPageIncognitoTabs:
+      return self.incognitoTabsViewController.selectedCellVisible;
+    case TabGridPageRegularTabs:
+      return self.regularTabsViewController.selectedCellVisible;
+    case TabGridPageRemoteTabs:
+      return NO;
+  }
+}
+
+- (GridTransitionLayout*)layoutForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context {
+  switch (self.currentPage) {
+    case TabGridPageIncognitoTabs:
+      return [self.incognitoTabsViewController transitionLayout];
+    case TabGridPageRegularTabs:
+      return [self.regularTabsViewController transitionLayout];
+    case TabGridPageRemoteTabs:
+      return nil;
+  }
+}
+
+- (UIView*)proxyContainerForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context {
+  return self.view;
+}
+
+- (UIView*)proxyPositionForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context {
+  return self.scrollView;
 }
 
 #pragma mark - Public
@@ -417,74 +448,104 @@
   }
 }
 
-// Adds the top toolbar buttons.
-- (void)setupTopToolbarButtons {
+// Adds floating button and constraints.
+- (void)setupFloatingButton {
+  UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
+  button.translatesAutoresizingMaskIntoConstraints = NO;
+  // TODO(crbug.com/818198) : Replace with assets.
+  button.backgroundColor = [UIColor whiteColor];
+  button.layer.cornerRadius = 22.0f;
+  button.layer.masksToBounds = YES;
+  [self.view addSubview:button];
+  self.floatingButton = button;
+  NSArray* constraints = @[
+    [button.widthAnchor constraintEqualToConstant:44.0f],
+    [button.heightAnchor constraintEqualToConstant:44.0f],
+    [button.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor
+                                          constant:-10.0f],
+    [button.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor
+                                        constant:-10.0f]
+  ];
+  [NSLayoutConstraint activateConstraints:constraints];
+}
+
+// Sets visibility of toolbars and floating button in the arrangement containing
+// the floating button. Also updates |self.doneButton|, |self.closeAllButton|,
+// and |self.createTabButton| to the visible button.
+- (void)configureToolbarsWithFloatingButton {
+  self.topToolbar.leadingButton.hidden = NO;
+  self.topToolbar.trailingButton.hidden = NO;
+  self.bottomToolbar.hidden = YES;
+  self.floatingButton.hidden = NO;
   self.doneButton = self.topToolbar.leadingButton;
   self.closeAllButton = self.topToolbar.trailingButton;
-  self.doneButton.accessibilityIdentifier = kTabGridDoneButtonAccessibilityID;
+  self.createTabButton = self.floatingButton;
+}
+
+// Sets visibility of toolbars and floating button in the arrangement that
+// includes the bottom toolbar. Also updates |self.doneButton|,
+// |self.closeAllButton|, and |self.createTabButton| to the visible button.
+- (void)configureToolbarsWithBottomToolbar {
+  self.topToolbar.leadingButton.hidden = YES;
+  self.topToolbar.trailingButton.hidden = YES;
+  self.bottomToolbar.hidden = NO;
+  self.floatingButton.hidden = YES;
+  self.doneButton = self.bottomToolbar.leadingButton;
+  self.closeAllButton = self.bottomToolbar.trailingButton;
+  self.createTabButton = self.bottomToolbar.roundButton;
+}
+
+// Call this method whenever |self.doneButton|, |self.closeAllButton|, or
+// |self.createTabButton| is updated.
+- (void)resetButtonLabelsAndActions {
   // TODO(crbug.com/818699) : Localize strings.
   [self.doneButton setTitle:@"Done" forState:UIControlStateNormal];
   [self.closeAllButton setTitle:@"Close All" forState:UIControlStateNormal];
+  self.doneButton.accessibilityIdentifier = kTabGridDoneButtonAccessibilityID;
   [self.doneButton addTarget:self
                       action:@selector(doneButtonTapped:)
             forControlEvents:UIControlEventTouchUpInside];
   [self.closeAllButton addTarget:self
                           action:@selector(closeAllButtonTapped:)
                 forControlEvents:UIControlEventTouchUpInside];
+  [self.createTabButton addTarget:self
+                           action:@selector(createTabButtonTapped:)
+                 forControlEvents:UIControlEventTouchUpInside];
 }
 
-// Adds the bottom toolbar buttons.
-- (void)setupBottomToolbarButtons {
-  // TODO(crbug.com/818699) : Localize strings.
-  [self.bottomToolbar.leadingButton setTitle:@"Done"
-                                    forState:UIControlStateNormal];
-  [self.bottomToolbar.trailingButton setTitle:@"Close All"
-                                     forState:UIControlStateNormal];
-  [self.bottomToolbar.roundButton setTitle:@"New"
-                                  forState:UIControlStateNormal];
-  [self.bottomToolbar.leadingButton addTarget:self
-                                       action:@selector(doneButtonTapped:)
-                             forControlEvents:UIControlEventTouchUpInside];
-  [self.bottomToolbar.trailingButton addTarget:self
-                                        action:@selector(closeAllButtonTapped:)
-                              forControlEvents:UIControlEventTouchUpInside];
-  [self.bottomToolbar.roundButton addTarget:self
-                                     action:@selector(newTabButtonTapped:)
-                           forControlEvents:UIControlEventTouchUpInside];
-}
-
-// Translates the toolbar views offscreen and then animates them back in using
-// the transition coordinator. Transitions are preferred here since they don't
-// interact with the layout system at all.
-- (void)animateToolbarsForAppearance {
-  DCHECK(self.transitionCoordinator);
-  // Capture the current toolbar transforms.
-  CGAffineTransform topToolbarBaseTransform = self.topToolbar.transform;
-  CGAffineTransform bottomToolbarBaseTransform = self.bottomToolbar.transform;
-  // Translate the top toolbar up offscreen by shifting it up by its height.
-  self.topToolbar.transform =
-      CGAffineTransformTranslate(self.topToolbar.transform, /*tx=*/0,
-                                 /*ty=*/-self.topToolbar.bounds.size.height);
-  // Translate the bottom toolbar down offscreen by shifting it down by its
-  // height.
-  self.bottomToolbar.transform =
-      CGAffineTransformTranslate(self.bottomToolbar.transform, /*tx=*/0,
-                                 /*ty=*/self.topToolbar.bounds.size.height);
-  // Block that restores the toolbar transforms, suitable for using with the
-  // transition coordinator.
-  void (^animation)(id<UIViewControllerTransitionCoordinatorContext>) =
-      ^(id<UIViewControllerTransitionCoordinatorContext> context) {
-        self.topToolbar.transform = topToolbarBaseTransform;
-        self.bottomToolbar.transform = bottomToolbarBaseTransform;
-      };
-  // Animate the toolbars into place alongside the current transition by
-  // restoring their transforms.
-  [self.transitionCoordinator animateAlongsideTransition:animation
-                                              completion:nil];
+// Sets up the toolbars and buttons based on size class.
+- (void)updateToolbarsForCurrentSizeClass {
+  if (self.traitCollection.verticalSizeClass ==
+      UIUserInterfaceSizeClassCompact) {
+    // When the vertical size is limited, we don't want a bottom toolbar.
+    [self configureToolbarsWithFloatingButton];
+    [self resetButtonLabelsAndActions];
+    return;
+  }
+  switch (self.traitCollection.horizontalSizeClass) {
+    case UIUserInterfaceSizeClassCompact:
+      // The UI is vertically long and narrow so include a bottom toolbar.
+      [self configureToolbarsWithBottomToolbar];
+      [self resetButtonLabelsAndActions];
+      break;
+    case UIUserInterfaceSizeClassRegular:
+      // The UI is wide and long and looks best with a FAB.
+      [self configureToolbarsWithFloatingButton];
+      // There is enough space for the tab view to have a tab strip,
+      // so put the done button on the trailing side where the tab
+      // switcher button is located on the tab view.
+      self.doneButton = self.topToolbar.trailingButton;
+      self.closeAllButton = self.topToolbar.leadingButton;
+      [self resetButtonLabelsAndActions];
+      break;
+    case UIUserInterfaceSizeClassUnspecified:
+      NOTREACHED() << "Invalid size class.";
+      break;
+  }
 }
 
 // Update |enabled| property of the done and close all buttons.
-- (void)updateDoneAndCloseAllButtons {
+- (void)enableButtonsForCurrentPage {
   switch (self.currentPage) {
     case TabGridPageIncognitoTabs:
       self.doneButton.enabled = !self.incognitoTabsViewController.isGridEmpty;
@@ -501,6 +562,45 @@
   }
 }
 
+// Translates the toolbar views offscreen and then animates them back in using
+// the transition coordinator. Transitions are preferred here since they don't
+// interact with the layout system at all.
+- (void)animateToolbarsForAppearance {
+  DCHECK(self.transitionCoordinator);
+  // TODO(crbug.com/820410): Tune the timing of these animations.
+
+  // Capture the current toolbar transforms.
+  CGAffineTransform topToolbarBaseTransform = self.topToolbar.transform;
+  CGAffineTransform bottomToolbarBaseTransform = self.bottomToolbar.transform;
+  // Translate the top toolbar up offscreen by shifting it up by its height.
+  self.topToolbar.transform = CGAffineTransformTranslate(
+      self.topToolbar.transform, /*tx=*/0,
+      /*ty=*/-(self.topToolbar.bounds.size.height * 0.5));
+  // Translate the bottom toolbar down offscreen by shifting it down by its
+  // height.
+  self.bottomToolbar.transform = CGAffineTransformTranslate(
+      self.bottomToolbar.transform, /*tx=*/0,
+      /*ty=*/(self.topToolbar.bounds.size.height * 0.5));
+
+  // Block that restores the toolbar transforms, suitable for using with the
+  // transition coordinator.
+  auto animation = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
+    self.topToolbar.transform = topToolbarBaseTransform;
+    self.bottomToolbar.transform = bottomToolbarBaseTransform;
+  };
+
+  // Also hide the scroll view (and thus the tab grids) until the transition
+  // completes.
+  self.scrollView.hidden = YES;
+  auto cleanup = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
+    self.scrollView.hidden = NO;
+  };
+
+  // Animate the toolbars into place alongside the current transition.
+  [self.transitionCoordinator animateAlongsideTransition:animation
+                                              completion:cleanup];
+}
+
 #pragma mark - GridViewControllerDelegate
 
 - (void)gridViewController:(GridViewController*)gridViewController
@@ -524,12 +624,12 @@
 
 - (void)lastItemWasClosedInGridViewController:
     (GridViewController*)gridViewController {
-  [self updateDoneAndCloseAllButtons];
+  [self enableButtonsForCurrentPage];
 }
 
 - (void)firstItemWasAddedInGridViewController:
     (GridViewController*)gridViewController {
-  [self updateDoneAndCloseAllButtons];
+  [self enableButtonsForCurrentPage];
 }
 
 #pragma mark - Button actions
@@ -552,7 +652,7 @@
   }
 }
 
-- (void)newTabButtonTapped:(id)sender {
+- (void)createTabButtonTapped:(id)sender {
   switch (self.currentPage) {
     case TabGridPageIncognitoTabs:
       [self.incognitoTabsDelegate addNewItem];
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn
index 729b2529..52ed4990a 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn
@@ -10,6 +10,9 @@
     "grid_to_hidden_tab_animator.mm",
     "grid_to_visible_tab_animator.h",
     "grid_to_visible_tab_animator.mm",
+    "grid_transition_layout.h",
+    "grid_transition_layout.mm",
+    "grid_transition_state_providing.h",
     "tab_to_grid_animator.h",
     "tab_to_grid_animator.mm",
   ]
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
new file mode 100644
index 0000000..c8de9ee3
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
@@ -0,0 +1,57 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_
+#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_
+
+#import <UIKit/UIKit.h>
+
+@class GridTransitionLayoutItem;
+
+// An encapsulation of information for the layout of a grid of cells that will
+// be used in an animated transition. The layout object is composed of layout
+// items (see below).
+@interface GridTransitionLayout : NSObject
+
+// All of the items in the layout.
+@property(nonatomic, copy, readonly) NSArray<GridTransitionLayoutItem*>* items;
+// The item in the layout (if any) that's selected.
+// Note that |selectedItem.cell.selected| doesn't need to be YES; the transition
+// animation may set or unset that selection state as part of the animation.
+@property(nonatomic, strong, readonly) GridTransitionLayoutItem* selectedItem;
+
+// Creates a new layout object with |items|, and |selectedItem| selected.
+// |items| should be non-nil, but it may be empty.
+// |selectedItem| must either be nil, or one of the members of |items|.
++ (instancetype)layoutWithItems:(NSArray<GridTransitionLayoutItem*>*)items
+                   selectedItem:(GridTransitionLayoutItem*)selectedItem;
+
+@end
+
+// An encapsulation of information for the layout of a single grid cell, in the
+// form of UICollectionView classes.
+@interface GridTransitionLayoutItem : NSObject
+
+// A cell object with the desired appearance for the animation. This should
+// correspond to an actual cell in the collection view involved in the trans-
+// ition, but the value of thie property should not be in any view hierarchy
+// when the layout item is created.
+@property(nonatomic, strong, readonly) UICollectionViewCell* cell;
+// The layout attributes for the cell in the collection view, normalized to
+// UIWindow coordinates. It's the responsibility of the setter to do this
+// normalization.
+@property(nonatomic, strong, readonly)
+    UICollectionViewLayoutAttributes* attributes;
+
+// Creates a new layout item instance will |cell| and |attributes|, neither of
+// which can be nil.
+// It's an error if |cell| has a superview.
+// The properties (size, etc) of |attributes| don't need to match the corres-
+// ponding properties of |cell| when the item is created.
++ (instancetype)itemWithCell:(UICollectionViewCell*)cell
+                  attributes:(UICollectionViewLayoutAttributes*)attributes;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
new file mode 100644
index 0000000..26d5256
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
@@ -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.
+
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#include "base/logging.h"
+
+@interface GridTransitionLayout ()
+@property(nonatomic, readwrite) NSArray<GridTransitionLayoutItem*>* items;
+@property(nonatomic, readwrite) GridTransitionLayoutItem* selectedItem;
+@end
+
+@implementation GridTransitionLayout
+@synthesize selectedItem = _selectedItem;
+@synthesize items = _items;
+
++ (instancetype)layoutWithItems:(NSArray<GridTransitionLayoutItem*>*)items
+                   selectedItem:(GridTransitionLayoutItem*)selectedItem {
+  DCHECK(items);
+  GridTransitionLayout* layout = [[GridTransitionLayout alloc] init];
+  layout.items = items;
+  layout.selectedItem = selectedItem;
+  return layout;
+}
+
+- (void)setSelectedItem:(GridTransitionLayoutItem*)selectedItem {
+  DCHECK([self.items containsObject:selectedItem]);
+  _selectedItem = selectedItem;
+}
+
+@end
+
+@interface GridTransitionLayoutItem ()
+@property(nonatomic, readwrite) UICollectionViewCell* cell;
+@property(nonatomic, readwrite) UICollectionViewLayoutAttributes* attributes;
+@end
+
+@implementation GridTransitionLayoutItem
+@synthesize cell = _cell;
+@synthesize attributes = _attributes;
+
++ (instancetype)itemWithCell:(UICollectionViewCell*)cell
+                  attributes:(UICollectionViewLayoutAttributes*)attributes {
+  DCHECK(cell);
+  DCHECK(attributes);
+  DCHECK(!cell.superview);
+  GridTransitionLayoutItem* item = [[GridTransitionLayoutItem alloc] init];
+  item.cell = cell;
+  item.attributes = attributes;
+  return item;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h
new file mode 100644
index 0000000..5e1de24
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_STATE_PROVIDING_H_
+#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_STATE_PROVIDING_H_
+
+#import <Foundation/Foundation.h>
+
+@class GridTransitionLayout;
+
+// Objects conforming to this protocol can provide state information to
+// transition delegates and animators for a grid.
+@protocol GridTransitionStateProviding
+
+// YES if the currently selected cell is visible in the grid.
+@property(nonatomic, readonly, getter=isSelectedCellVisible)
+    BOOL selectedCellVisible;
+
+// Asks the provider for an aray of layout items that provide objects for use
+// in building an animated transition.
+- (GridTransitionLayout*)layoutForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context;
+
+// Asks the provider for the view to add proxy views to when building an
+// animated transition.
+- (UIView*)proxyContainerForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context;
+
+// Asks the provider for the view (if any) that proxy views should be added
+// in front of when building an animated transition. It's an error if this
+// view is not nil and isn't an immediate subview of the view returned by
+// |-proxyContainerForTransitionContext:|
+- (UIView*)proxyPositionForTransitionContext:
+    (id<UIViewControllerContextTransitioning>)context;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_TAB_GRID_TRANSITION_STATE_PROVIDING_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h
index 1c4b9da..b13f238 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h
+++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h
@@ -7,8 +7,17 @@
 
 #import <UIKit/UIKit.h>
 
+@protocol GridTransitionStateProviding;
+
+// Animator object for transitioning from a fullscreen view controller (the
+// "tab") into a collection view of square-ish items (the "grid").
 @interface TabToGridAnimator : NSObject<UIViewControllerAnimatedTransitioning>
 
+// Initialize an animator object with |stateProvider| to provide state
+// information for the transition.
+- (instancetype)initWithStateProvider:
+    (id<GridTransitionStateProviding>)stateProvider;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_TAB_TO_GRID_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
index 4ca4baf..03b3319 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
@@ -4,19 +4,191 @@
 
 #import "ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h"
 
+#import "base/logging.h"
+#import "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+@interface TabToGridAnimator ()
+// State provider for this transition.
+@property(nonatomic, weak) id<GridTransitionStateProviding> stateProvider;
+@end
+
 @implementation TabToGridAnimator
+@synthesize stateProvider = _stateProvider;
+
+- (instancetype)initWithStateProvider:
+    (id<GridTransitionStateProviding>)stateProvider {
+  if ((self = [super init])) {
+    _stateProvider = stateProvider;
+  }
+  return self;
+}
 
 - (NSTimeInterval)transitionDuration:
     (id<UIViewControllerContextTransitioning>)transitionContext {
-  return 0.25;
+  return 0.4;
 }
 
 - (void)animateTransition:
     (id<UIViewControllerContextTransitioning>)transitionContext {
+  // Get views and view controllers for this transition.
+  UIView* containerView = [transitionContext containerView];
+  UIViewController* gridViewController = [transitionContext
+      viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView* gridView =
+      [transitionContext viewForKey:UITransitionContextToViewKey];
+  UIView* dismissingView =
+      [transitionContext viewForKey:UITransitionContextFromViewKey];
+
+  // Extract some useful metrics from the tab view.
+  CGSize proxySize = dismissingView.bounds.size;
+  CGPoint proxyCenter = dismissingView.center;
+
+  // Add the grid view to the container. This isn't just for the transition;
+  // this is how the grid view controller's view is added to the view
+  // hierarchy.
+  [containerView insertSubview:gridView belowSubview:dismissingView];
+  gridView.frame =
+      [transitionContext finalFrameForViewController:gridViewController];
+
+  // Get the layout of the grid for the transition.
+  GridTransitionLayout* layout =
+      [self.stateProvider layoutForTransitionContext:transitionContext];
+
+  // Compute the scale of the transition grid (which is at the propotional size
+  // of the actual tab view.
+  CGFloat xScale = proxySize.width / layout.selectedItem.attributes.size.width;
+  CGFloat yScale =
+      proxySize.height / layout.selectedItem.attributes.size.height;
+
+  // Ask the state provider for the views to use when inserting the tab grid.
+  UIView* proxyContainer =
+      [self.stateProvider proxyContainerForTransitionContext:transitionContext];
+  UIView* viewBehindProxies =
+      [self.stateProvider proxyPositionForTransitionContext:transitionContext];
+
+  // Lay out the transition grid and add it to the view hierarchy.
+  CGFloat finalSelectedCellCornerRadius = 0.0;
+  for (GridTransitionLayoutItem* item in layout.items) {
+    // The state provider vends attributes in UIWindow coordinates.
+    // Find where this item is located in |proxyContainer|'s coordinate.
+    CGPoint gridCenter =
+        [proxyContainer convertPoint:item.attributes.center fromView:nil];
+    // Map that to the scale and position of the transition grid.
+    CGPoint center = CGPointMake(
+        proxyCenter.x +
+            ((gridCenter.x - layout.selectedItem.attributes.center.x) * xScale),
+        proxyCenter.y +
+            ((gridCenter.y - layout.selectedItem.attributes.center.y) *
+             yScale));
+    UICollectionViewCell* cell = item.cell;
+    cell.bounds = item.attributes.bounds;
+    // Add a scale transform to the cell so it matches the x-scale of the
+    // open tab.
+    cell.transform = CGAffineTransformScale(cell.transform, xScale, xScale);
+    cell.center = center;
+    if (item == layout.selectedItem) {
+      finalSelectedCellCornerRadius = cell.contentView.layer.cornerRadius;
+      cell.contentView.layer.cornerRadius = 0.0;
+    }
+    // Add the cell into the container for the transition.
+    [proxyContainer insertSubview:cell aboveSubview:viewBehindProxies];
+  }
+
+  // The transition is structured as four separate animations. Three of them
+  // are timed based on |staggeredDuration|, which is a configurable fraction
+  // of the overall animation duration.
+  // (1) Fading out the view being dismissed. This happens during the first 20%
+  //     of the overall animation.
+  // (2) Zooming the selected cell into position. This starts immediately and
+  //     has a duration of |staggeredDuration|.
+  // (3) Fading in the selected cell highlight indicator. This starts after a
+  //     delay of |staggeredDuration| and runs to the end of the transition.
+  //     This means it starts as soon as (2) ends.
+  // (4) Zooming all other cells into position. This ends at the end of the
+  //     transition and has a duration of |staggeredDuration|.
+  //
+  // Animation (4) always runs the whole duration of the transition, so it's
+  // where the completion block that does overall cleanup is run.
+
+  // TODO(crbug.com/804539): Factor all of these animations into a single
+  // Orchestrator object that the present and dismiss animation can both use.
+
+  // TODO(crbug.com/820410): Tune the timing, relative pacing, and curves of
+  // these animations.
+
+  NSTimeInterval duration = [self transitionDuration:transitionContext];
+  CGFloat staggeredDuration = duration * 0.7;
+
+  // (1) Fade out active tab view.
+  [UIView animateWithDuration:duration / 5
+                   animations:^{
+                     dismissingView.alpha = 0;
+                   }
+                   completion:nil];
+
+  // (2) Zoom selected cell into place. Also round its corners.
+  UICollectionViewCell* selectedCell = layout.selectedItem.cell;
+  [UIView animateWithDuration:staggeredDuration
+                        delay:0.0
+                      options:UIViewAnimationOptionCurveEaseOut
+                   animations:^{
+                     selectedCell.center = [containerView
+                         convertPoint:layout.selectedItem.attributes.center
+                             fromView:nil];
+                     selectedCell.bounds =
+                         layout.selectedItem.attributes.bounds;
+                     selectedCell.transform = CGAffineTransformIdentity;
+                     selectedCell.contentView.layer.cornerRadius =
+                         finalSelectedCellCornerRadius;
+                   }
+                   completion:nil];
+
+  // (3) Show highlight state on selected cell.
+  [UIView animateWithDuration:duration - staggeredDuration
+                        delay:staggeredDuration
+                      options:UIViewAnimationOptionCurveEaseIn
+                   animations:^{
+                     selectedCell.selected = YES;
+                   }
+                   completion:nil];
+
+  // (4) Zoom other cells into place.
+  [UIView animateWithDuration:staggeredDuration
+      delay:duration - staggeredDuration
+      options:UIViewAnimationOptionCurveEaseOut
+      animations:^{
+        for (GridTransitionLayoutItem* item in layout.items) {
+          if (item == layout.selectedItem)
+            continue;
+          UIView* cell = item.cell;
+          cell.center =
+              [containerView convertPoint:item.attributes.center fromView:nil];
+          cell.transform = CGAffineTransformIdentity;
+        }
+      }
+      completion:^(BOOL finished) {
+        // Clean up all of the proxy cells.
+        for (GridTransitionLayoutItem* item in layout.items) {
+          [item.cell removeFromSuperview];
+        }
+        // If the transition was cancelled, restore the dismissing view and
+        // remove the grid view.
+        // If not, remove the dismissing view.
+        if (transitionContext.transitionWasCancelled) {
+          dismissingView.alpha = 1.0;
+          [gridView removeFromSuperview];
+        } else {
+          [dismissingView removeFromSuperview];
+        }
+        // Mark the transition as completed.
+        [transitionContext completeTransition:YES];
+      }];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
index b6a9aa7..f5df865 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
@@ -149,8 +149,6 @@
 - (void)setUpBlurredBackground {
   UIBlurEffect* blurEffect = self.buttonFactory.toolbarConfiguration.blurEffect;
   self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
-  self.blur.contentView.backgroundColor =
-      self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor;
   [self addSubview:self.blur];
 
   self.contentView = self;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
index 260a995..33b489a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
@@ -85,9 +85,6 @@
 
   UIBlurEffect* blurEffect = self.buttonFactory.toolbarConfiguration.blurEffect;
   self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
-  self.blur.contentView.backgroundColor =
-      self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor;
-
   [self addSubview:self.blur];
   self.blur.translatesAutoresizingMaskIntoConstraints = NO;
   AddSameConstraints(self.blur, self);
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
index 41eb942..3d21add 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
@@ -22,9 +22,6 @@
 // Blur effect for the toolbar background.
 @property(nonatomic, readonly) UIBlurEffect* blurEffect;
 
-// Background color for the blur effect view.
-@property(nonatomic, readonly) UIColor* blurEffectBackgroundColor;
-
 // Background color of the NTP. Used to do as if the toolbar was transparent and
 // the NTP is visible behind it.
 @property(nonatomic, readonly) UIColor* NTPBackgroundColor;
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
index 043786ad..97fb26e1 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
@@ -35,16 +35,6 @@
   }
 }
 
-- (UIColor*)blurEffectBackgroundColor {
-  switch (self.style) {
-    case NORMAL:
-      return [UIColor colorWithWhite:kBlurBackgroundGrayscaleComponent
-                               alpha:kBlurBackgroundAlpha];
-    case INCOGNITO:
-      return nil;
-  }
-}
-
 - (UIColor*)NTPBackgroundColor {
   switch (self.style) {
     case NORMAL:
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
index 2c45c40b5..7ebe34e 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
@@ -340,6 +340,9 @@
   CGRect newFrame = oldFrame;
   newFrame.size.width = width;
 
+  if (self.webStateList->GetActiveWebState())
+    [self updateToolbarForSnapshot:self.webStateList->GetActiveWebState()];
+
   self.viewController.view.superview.frame = newFrame;
   [self.toolbarViewController activateFakeSafeAreaInsets:safeAreaInsets];
   [self.viewController.view.superview layoutIfNeeded];
@@ -349,11 +352,17 @@
   self.viewController.view.superview.frame = oldFrame;
   [self.toolbarViewController deactivateFakeSafeAreaInsets];
 
+  if (self.webStateList->GetActiveWebState())
+    [self resetToolbarAfterSnapshot];
+
   return toolbarSnapshotView;
 }
 
 - (UIColor*)toolbarBackgroundColor {
-  return self.toolbarViewController.backgroundColor;
+  if (self.webStateList && self.webStateList->GetActiveWebState() &&
+      IsVisibleUrlNewTabPage(self.webStateList->GetActiveWebState()))
+    return self.toolbarViewController.backgroundColorNTP;
+  return nil;
 }
 
 #pragma mark - FakeboxFocuser
@@ -400,12 +409,12 @@
 #pragma mark - SideSwipeToolbarSnapshotProviding
 
 - (UIImage*)toolbarSideSwipeSnapshotForWebState:(web::WebState*)webState {
-  [self updateToolbarForSideSwipeSnapshot:webState];
+  [self updateToolbarForSnapshot:webState];
   UIImage* toolbarSnapshot = CaptureViewWithOption(
       [self.viewController view], [[UIScreen mainScreen] scale],
       kClientSideRendering);
 
-  [self resetToolbarAfterSideSwipeSnapshot];
+  [self resetToolbarAfterSnapshot];
   return toolbarSnapshot;
 }
 
@@ -483,28 +492,29 @@
 
 // Updates the toolbar so it is in a state where a snapshot for |webState| can
 // be taken.
-- (void)updateToolbarForSideSwipeSnapshot:(web::WebState*)webState {
+- (void)updateToolbarForSnapshot:(web::WebState*)webState {
   BOOL isNTP = IsVisibleUrlNewTabPage(webState);
 
-  // Don't do anything for a live non-ntp tab.
-  if (webState == self.webStateList->GetActiveWebState() && !isNTP) {
+  self.viewController.view.hidden = NO;
+  // Don't do anything for the current tab if it is not a non-incognito NTP.
+  if (webState == self.webStateList->GetActiveWebState() &&
+      !(isNTP && !self.browserState->IsOffTheRecord())) {
     [self.locationBarCoordinator.view setHidden:NO];
     return;
   }
 
-  self.viewController.view.hidden = NO;
   [self.locationBarCoordinator.view setHidden:YES];
   [self.mediator updateConsumerForWebState:webState];
-  [self.toolbarViewController updateForSideSwipeSnapshotOnNTP:isNTP];
+  [self.toolbarViewController updateForSnapshotOnNTP:isNTP];
 }
 
-// Resets the toolbar after taking a side swipe snapshot. After calling this
-// method the toolbar is adapted to the current webState.
-- (void)resetToolbarAfterSideSwipeSnapshot {
+// Resets the toolbar after taking a snapshot. After calling this method the
+// toolbar is adapted to the current webState.
+- (void)resetToolbarAfterSnapshot {
   [self.mediator
       updateConsumerForWebState:self.webStateList->GetActiveWebState()];
   [self.locationBarCoordinator.view setHidden:NO];
-  [self.toolbarViewController resetAfterSideSwipeSnapshot];
+  [self.toolbarViewController resetAfterSnapshot];
 }
 
 // Animates |_toolbar| and |_locationBarView| for omnibox expansion. If
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
index 527ddb1..d21ecd93 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
@@ -45,8 +45,8 @@
 @property(nonatomic, assign) BOOL expanded;
 // Omnibox focuser.
 @property(nonatomic, weak) id<OmniboxFocuser> omniboxFocuser;
-// Background color of the toolbar. Returns nil if it is the default color.
-@property(nonatomic, strong, readonly) UIColor* backgroundColor;
+// Background color of the toolbar when presented on the NTP.
+@property(nonatomic, strong, readonly) UIColor* backgroundColorNTP;
 
 // Sets the location bar view, containing the omnibox.
 - (void)setLocationBarView:(UIView*)locationBarView;
@@ -63,9 +63,9 @@
 - (void)addToolbarContractionAnimations:(UIViewPropertyAnimator*)animator;
 // Updates the view so a snapshot can be taken. It needs to be adapted,
 // depending on if it is a snapshot displayed |onNTP| or not.
-- (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP;
-// Resets the view after taking a snapshot for a side swipe.
-- (void)resetAfterSideSwipeSnapshot;
+- (void)updateForSnapshotOnNTP:(BOOL)onNTP;
+// Resets the view after taking a snapshot.
+- (void)resetAfterSnapshot;
 // Sets the background color of the Toolbar to the one of the Incognito NTP,
 // with an |alpha|.
 - (void)setBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha;
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
index 056608b..80f0584 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
@@ -236,7 +236,7 @@
   self.expanded = NO;
 }
 
-- (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP {
+- (void)updateForSnapshotOnNTP:(BOOL)onNTP {
   self.view.progressBar.hidden = YES;
   if (onNTP) {
     self.view.backgroundView.alpha = 1;
@@ -247,7 +247,7 @@
   }
 }
 
-- (void)resetAfterSideSwipeSnapshot {
+- (void)resetAfterSnapshot {
   self.view.backgroundView.alpha = 0;
   self.view.locationBarContainer.hidden = NO;
   self.view.backButton.hiddenInCurrentState = NO;
@@ -331,9 +331,7 @@
   return self.view.toolsMenuButton;
 }
 
-- (UIColor*)backgroundColor {
-  if (self.view.backgroundView.hidden || self.view.backgroundView.alpha == 0)
-    return nil;
+- (UIColor*)backgroundColorNTP {
   return self.view.backgroundView.backgroundColor;
 }
 
diff --git a/ios/web/download/download_task_impl.mm b/ios/web/download/download_task_impl.mm
index 1d8063c..15341db 100644
--- a/ios/web/download/download_task_impl.mm
+++ b/ios/web/download/download_task_impl.mm
@@ -182,6 +182,9 @@
 
 DownloadTaskImpl::~DownloadTaskImpl() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
+  for (auto& observer : observers_)
+    observer.OnDownloadDestroyed(this);
+
   if (delegate_) {
     delegate_->OnTaskDestroyed(this);
   }
diff --git a/ios/web/download/download_task_impl_unittest.mm b/ios/web/download/download_task_impl_unittest.mm
index f77b7c6..8baf503 100644
--- a/ios/web/download/download_task_impl_unittest.mm
+++ b/ios/web/download/download_task_impl_unittest.mm
@@ -50,6 +50,12 @@
 class MockDownloadTaskObserver : public DownloadTaskObserver {
  public:
   MOCK_METHOD1(OnDownloadUpdated, void(DownloadTask* task));
+  void OnDownloadDestroyed(DownloadTask* task) override {
+    // Removing observer here works as a test that
+    // DownloadTaskObserver::OnDownloadDestroyed is actually called.
+    // DownloadTask DCHECKs if it is destroyed without observer removal.
+    task->RemoveObserver(this);
+  }
 };
 
 // Allows waiting for DownloadTaskObserver::OnDownloadUpdated callback.
@@ -128,12 +134,6 @@
     task_->AddObserver(&task_observer_);
   }
 
-  ~DownloadTaskImplTest() {
-    if (task_) {
-      task_->RemoveObserver(&task_observer_);
-    }
-  }
-
   // Starts the download and return NSURLSessionDataTask fake for this task.
   CRWFakeNSURLSessionTask* Start(
       std::unique_ptr<net::URLFetcherResponseWriter> writer) {
@@ -674,7 +674,6 @@
   ASSERT_TRUE(session_task);
   testing::Mock::VerifyAndClearExpectations(&task_observer_);
   EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get()));
-  task_->RemoveObserver(&task_observer_);
   task_ = nullptr;  // Destruct DownloadTaskImpl.
   EXPECT_TRUE(session_task.state = NSURLSessionTaskStateCanceling);
 }
diff --git a/ios/web/public/download/download_task_observer.h b/ios/web/public/download/download_task_observer.h
index 42ced95..2110817 100644
--- a/ios/web/public/download/download_task_observer.h
+++ b/ios/web/public/download/download_task_observer.h
@@ -23,6 +23,10 @@
   // downloaded data.
   virtual void OnDownloadUpdated(DownloadTask* task) {}
 
+  // Called when the download task is about to be destructed. After this
+  // callback all references to provided DownloadTask should be cleared.
+  virtual void OnDownloadDestroyed(DownloadTask* task) {}
+
   DownloadTaskObserver() = default;
   virtual ~DownloadTaskObserver() = default;
 
diff --git a/ios/web/public/test/fakes/fake_download_task.mm b/ios/web/public/test/fakes/fake_download_task.mm
index a5bd772..89cf90d 100644
--- a/ios/web/public/test/fakes/fake_download_task.mm
+++ b/ios/web/public/test/fakes/fake_download_task.mm
@@ -17,7 +17,10 @@
                                    const std::string& mime_type)
     : original_url_(original_url), mime_type_(mime_type), identifier_(@"") {}
 
-FakeDownloadTask::~FakeDownloadTask() = default;
+FakeDownloadTask::~FakeDownloadTask() {
+  for (auto& observer : observers_)
+    observer.OnDownloadDestroyed(this);
+}
 
 DownloadTask::State FakeDownloadTask::GetState() const {
   return state_;
diff --git a/mash/BUILD.gn b/mash/BUILD.gn
index 6784a46..415a893 100644
--- a/mash/BUILD.gn
+++ b/mash/BUILD.gn
@@ -14,7 +14,7 @@
 
   deps = [
     ":mash_catalog",
-    "//components/leveldb",
+    "//components/services/leveldb",
     "//mash/catalog_viewer",
     "//mash/example",
     "//mash/runner",
@@ -41,7 +41,7 @@
   testonly = true
 
   standalone_services = [
-    "//components/leveldb:manifest",
+    "//components/services/leveldb:manifest",
     "//mash/catalog_viewer:manifest",
     "//mash/session:manifest",
     "//mash/task_viewer:manifest",
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc
index 4c772ef..c6b00853 100644
--- a/media/cdm/cdm_paths.cc
+++ b/media/cdm/cdm_paths.cc
@@ -14,20 +14,9 @@
 const char kClearKeyCdmLibraryName[] = "clearkeycdm";
 
 const char kClearKeyCdmBaseDirectory[] = "ClearKeyCdm";
-
-const char kClearKeyCdmAdapterFileName[] =
-#if defined(OS_MACOSX)
-    "clearkeycdmadapter.plugin";
-#elif defined(OS_WIN)
-    "clearkeycdmadapter.dll";
-#elif defined(OS_POSIX)
-    "libclearkeycdmadapter.so";
-#endif
-
 const char kClearKeyCdmDisplayName[] = "Clear Key CDM";
 const char kClearKeyCdmGuid[] = "C1A6B4E3-FE48-4D53-9F52-244AEEAD5335";
 const char kClearKeyCdmDifferentGuid[] = "747C565D-34EE-4B0D-AC1E-4F9FB17DDB40";
-const char kClearKeyCdmPepperMimeType[] = "application/x-ppapi-clearkey-cdm";
 
 // As the file system was initially used by the CDM running as a pepper plugin,
 // this ID is based on the pepper plugin MIME type.
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h
index 0ecf0fd..83e68e61 100644
--- a/media/cdm/cdm_paths.h
+++ b/media/cdm/cdm_paths.h
@@ -16,9 +16,6 @@
 
 extern const char kClearKeyCdmBaseDirectory[];
 
-// Platform-specific filename relative to kClearKeyCdmBaseDirectory.
-extern const char kClearKeyCdmAdapterFileName[];
-
 // Display name for Clear Key CDM.
 extern const char kClearKeyCdmDisplayName[];
 
@@ -29,10 +26,6 @@
 // CDMs in the system.
 extern const char kClearKeyCdmDifferentGuid[];
 
-// Pepper type for Clear Key CDM.
-// TODO(xhwang): Remove after switching to mojo CDM.
-extern const char kClearKeyCdmPepperMimeType[];
-
 // Identifier used by the PluginPrivateFileSystem to identify the files stored
 // for the Clear Key CDM.
 extern const char kClearKeyCdmFileSystemId[];
diff --git a/media/cdm/library_cdm/BUILD.gn b/media/cdm/library_cdm/BUILD.gn
deleted file mode 100644
index 907b168..0000000
--- a/media/cdm/library_cdm/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//chrome/process_version_rc_template.gni")
-import("//media/cdm/library_cdm/cdm_paths.gni")
-import("//media/cdm/library_cdm/ppapi_cdm_adapter.gni")
-
-process_version_rc_template("clearkeycdmadapter_resources") {
-  visibility = [ ":*" ]
-  sources = [
-    "clear_key_cdm/BRANDING",
-    "clearkeycdmadapter.ver",
-  ]
-  output = "$target_gen_dir/clearkeycdmadapter_version.rc"
-}
-
-ppapi_cdm_adapter("clearkeycdmadapter") {
-  output_dir = "$root_out_dir/$clearkey_cdm_path"
-
-  # Check whether the plugin's origin URL is valid.
-  defines = [ "CHECK_DOCUMENT_URL" ]
-  deps = [
-    ":clearkeycdmadapter_resources",
-    "//base",  # Required for the allocator implementation.
-    "//media:shared_memory_support",
-    "//media/cdm/library_cdm/clear_key_cdm",
-    "//ui/gfx/geometry",
-  ]
-}
diff --git a/media/cdm/library_cdm/clear_key_cdm/BRANDING b/media/cdm/library_cdm/clear_key_cdm/BRANDING
deleted file mode 100644
index c253da9..0000000
--- a/media/cdm/library_cdm/clear_key_cdm/BRANDING
+++ /dev/null
@@ -1,3 +0,0 @@
-PRODUCT_FULLNAME=External Clear Key Content Decryption Module Adapter
-PRODUCT_SHORTNAME=External Clear Key
-PRODUCT_DESCRIPTION=External Clear Key Content Decryption Module Adapter. Used for testing EME.
diff --git a/media/cdm/library_cdm/clearkeycdmadapter.ver b/media/cdm/library_cdm/clearkeycdmadapter.ver
deleted file mode 100644
index 800abea6..0000000
--- a/media/cdm/library_cdm/clearkeycdmadapter.ver
+++ /dev/null
@@ -1,2 +0,0 @@
-INTERNAL_NAME=clearkeycdmadapter_dll
-ORIGINAL_FILENAME=clearkeycdmadapter.dll
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 6a8344fc..c47a2ac6 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -16,7 +16,6 @@
     "USE_VAAPI=$use_vaapi",
     "USE_V4L2_CODEC=$use_v4l2_codec",
     "USE_LIBV4L2=$use_v4lplugin",
-    "ENABLE_D3D11_VIDEO_DECODER=$enable_d3d11_video_decoder",
   ]
 }
 
@@ -249,6 +248,14 @@
 
   if (is_win) {
     sources += [
+      "windows/d3d11_h264_accelerator.cc",
+      "windows/d3d11_h264_accelerator.h",
+      "windows/d3d11_picture_buffer.cc",
+      "windows/d3d11_picture_buffer.h",
+      "windows/d3d11_video_decoder.cc",
+      "windows/d3d11_video_decoder.h",
+      "windows/d3d11_video_decoder_impl.cc",
+      "windows/d3d11_video_decoder_impl.h",
       "windows/dxva_picture_buffer_win.cc",
       "windows/dxva_picture_buffer_win.h",
       "windows/dxva_video_decode_accelerator_win.cc",
@@ -284,18 +291,6 @@
       "/DELAYLOAD:mf.dll",
       "/DELAYLOAD:mfplat.dll",
     ]
-    if (enable_d3d11_video_decoder) {
-      sources += [
-        "windows/d3d11_h264_accelerator.cc",
-        "windows/d3d11_h264_accelerator.h",
-        "windows/d3d11_picture_buffer.cc",
-        "windows/d3d11_picture_buffer.h",
-        "windows/d3d11_video_decoder.cc",
-        "windows/d3d11_video_decoder.h",
-        "windows/d3d11_video_decoder_impl.cc",
-        "windows/d3d11_video_decoder_impl.h",
-      ]
-    }
     if (enable_library_cdms) {
       sources += [
         "windows/d3d11_cdm_proxy.cc",
diff --git a/media/gpu/vaapi/BUILD.gn b/media/gpu/vaapi/BUILD.gn
index 27185f1..e4bc702 100644
--- a/media/gpu/vaapi/BUILD.gn
+++ b/media/gpu/vaapi/BUILD.gn
@@ -5,6 +5,8 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//media/gpu/args.gni")
+import("//ui/gl/features.gni")
+import("//ui/ozone/ozone.gni")
 
 assert(use_vaapi)
 
@@ -51,35 +53,36 @@
 source_set("vaapi") {
   defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
   sources = [
-              "va_surface.cc",
-              "va_surface.h",
-              "vaapi_decode_surface.cc",
-              "vaapi_decode_surface.h",
-              "vaapi_jpeg_decode_accelerator.cc",
-              "vaapi_jpeg_decode_accelerator.h",
-              "vaapi_jpeg_decoder.cc",
-              "vaapi_jpeg_decoder.h",
-              "vaapi_jpeg_encode_accelerator.cc",
-              "vaapi_jpeg_encode_accelerator.h",
-              "vaapi_jpeg_encoder.cc",
-              "vaapi_jpeg_encoder.h",
-              "vaapi_picture.cc",
-              "vaapi_picture.h",
-              "vaapi_picture_factory.cc",
-              "vaapi_picture_factory.h",
-              "vaapi_video_decode_accelerator.cc",
-              "vaapi_video_decode_accelerator.h",
-              "vaapi_video_encode_accelerator.cc",
-              "vaapi_video_encode_accelerator.h",
-              "vaapi_h264_accelerator.cc",
-              "vaapi_h264_accelerator.h",
-              "vaapi_vp8_accelerator.cc",
-              "vaapi_vp8_accelerator.h",
-              "vaapi_vp9_accelerator.cc",
-              "vaapi_vp9_accelerator.h",
-              "vaapi_wrapper.cc",
-              "vaapi_wrapper.h",
-            ] + get_target_outputs(":libva_generate_stubs")
+    "va_surface.cc",
+    "va_surface.h",
+    "vaapi_decode_surface.cc",
+    "vaapi_decode_surface.h",
+    "vaapi_h264_accelerator.cc",
+    "vaapi_h264_accelerator.h",
+    "vaapi_jpeg_decode_accelerator.cc",
+    "vaapi_jpeg_decode_accelerator.h",
+    "vaapi_jpeg_decoder.cc",
+    "vaapi_jpeg_decoder.h",
+    "vaapi_jpeg_encode_accelerator.cc",
+    "vaapi_jpeg_encode_accelerator.h",
+    "vaapi_jpeg_encoder.cc",
+    "vaapi_jpeg_encoder.h",
+    "vaapi_picture.cc",
+    "vaapi_picture.h",
+    "vaapi_picture_factory.cc",
+    "vaapi_picture_factory.h",
+    "vaapi_video_decode_accelerator.cc",
+    "vaapi_video_decode_accelerator.h",
+    "vaapi_video_encode_accelerator.cc",
+    "vaapi_video_encode_accelerator.h",
+    "vaapi_vp8_accelerator.cc",
+    "vaapi_vp8_accelerator.h",
+    "vaapi_vp9_accelerator.cc",
+    "vaapi_vp9_accelerator.h",
+    "vaapi_wrapper.cc",
+    "vaapi_wrapper.h",
+  ]
+  sources += get_target_outputs(":libva_generate_stubs")
 
   configs += [ "//third_party/libyuv:libyuv_config" ]
 
@@ -90,24 +93,34 @@
     "//media/gpu:common",
     "//third_party/libyuv",
   ]
+
   if (use_x11) {
     configs += [ "//build/config/linux:x11" ]
     deps += [ "//ui/gfx/x" ]
     sources += [
-      "vaapi_tfp_picture.cc",
-      "vaapi_tfp_picture.h",
+      "vaapi_picture_tfp.cc",
+      "vaapi_picture_tfp.h",
     ]
   }
 
-  if (is_linux) {
+  if (ozone_platform_gbm || use_egl) {
     sources += [
-      "vaapi_drm_picture.cc",
-      "vaapi_drm_picture.h",
+      "vaapi_picture_native_pixmap.cc",
+      "vaapi_picture_native_pixmap.h",
     ]
-  }
-
-  if (use_ozone) {
-    deps += [ "//ui/ozone" ]
+    if (ozone_platform_gbm) {
+      sources += [
+        "vaapi_picture_native_pixmap_ozone.cc",
+        "vaapi_picture_native_pixmap_ozone.h",
+      ]
+      deps += [ "//ui/ozone" ]
+    }
+    if (use_egl) {
+      sources += [
+        "vaapi_picture_native_pixmap_egl.cc",
+        "vaapi_picture_native_pixmap_egl.h",
+      ]
+    }
   }
 }
 
diff --git a/media/gpu/vaapi/vaapi_drm_picture.cc b/media/gpu/vaapi/vaapi_drm_picture.cc
deleted file mode 100644
index 7bf98222..0000000
--- a/media/gpu/vaapi/vaapi_drm_picture.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/gpu/vaapi/vaapi_drm_picture.h"
-
-#include "base/file_descriptor_posix.h"
-#include "media/gpu/vaapi/va_surface.h"
-#include "media/gpu/vaapi/vaapi_wrapper.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/linux/native_pixmap_dmabuf.h"
-#include "ui/gfx/native_pixmap.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_image_native_pixmap.h"
-#include "ui/gl/scoped_binders.h"
-
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-#endif
-
-namespace media {
-
-namespace {
-
-static unsigned BufferFormatToInternalFormat(gfx::BufferFormat format) {
-  switch (format) {
-    case gfx::BufferFormat::BGRX_8888:
-    case gfx::BufferFormat::RGBX_8888:
-      return GL_RGB;
-
-    case gfx::BufferFormat::BGRA_8888:
-      return GL_BGRA_EXT;
-
-    case gfx::BufferFormat::YVU_420:
-      return GL_RGB_YCRCB_420_CHROMIUM;
-
-    default:
-      NOTREACHED();
-      return GL_BGRA_EXT;
-  }
-}
-
-}  // anonymous namespace
-
-VaapiDrmPicture::VaapiDrmPicture(
-    const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
-    const MakeGLContextCurrentCallback& make_context_current_cb,
-    const BindGLImageCallback& bind_image_cb,
-    int32_t picture_buffer_id,
-    const gfx::Size& size,
-    uint32_t texture_id,
-    uint32_t client_texture_id,
-    uint32_t texture_target)
-    : VaapiPicture(vaapi_wrapper,
-                   make_context_current_cb,
-                   bind_image_cb,
-                   picture_buffer_id,
-                   size,
-                   texture_id,
-                   client_texture_id,
-                   texture_target) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-}
-
-VaapiDrmPicture::~VaapiDrmPicture() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (gl_image_ && make_context_current_cb_.Run()) {
-    gl_image_->ReleaseTexImage(texture_target_);
-    DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
-  }
-}
-
-bool VaapiDrmPicture::Initialize() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(pixmap_);
-
-  // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
-  va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_);
-  if (!va_surface_) {
-    LOG(ERROR) << "Failed creating VASurface for NativePixmap";
-    return false;
-  }
-
-#if defined(USE_OZONE)
-  // Import dmabuf fds into the output gl texture through EGLImage.
-  if (texture_id_ != 0 && !make_context_current_cb_.is_null()) {
-    if (!make_context_current_cb_.Run())
-      return false;
-
-    gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
-
-    gfx::BufferFormat format = pixmap_->GetBufferFormat();
-
-    scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap(
-        size_, BufferFormatToInternalFormat(format)));
-    if (!image->Initialize(pixmap_.get(), format)) {
-      LOG(ERROR) << "Failed to create GLImage";
-      return false;
-    }
-    gl_image_ = image;
-    if (!gl_image_->BindTexImage(texture_target_)) {
-      LOG(ERROR) << "Failed to bind texture to GLImage";
-      return false;
-    }
-  }
-#else
-  // On non-ozone, no need to import dmabuf fds into output the gl texture
-  // because the dmabuf fds have been made from it.
-  DCHECK(pixmap_->AreDmaBufFdsValid());
-#endif
-
-  if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) {
-    if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
-                            true)) {
-      LOG(ERROR) << "Failed to bind client_texture_id";
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool VaapiDrmPicture::Allocate(gfx::BufferFormat format) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-// The goal of this method (ozone and non-ozone) is to allocate the
-// |pixmap_| which is a gl::GLImageNativePixmap.
-#if defined(USE_OZONE)
-  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
-  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
-  pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size_,
-                                        format, gfx::BufferUsage::SCANOUT);
-#else
-  // Export the gl texture as dmabuf.
-  if (texture_id_ != 0 && !make_context_current_cb_.is_null()) {
-    if (!make_context_current_cb_.Run())
-      return false;
-
-    scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap(
-        size_, BufferFormatToInternalFormat(format)));
-
-    // Create an EGLImage from a gl texture
-    if (!image->InitializeFromTexture(texture_id_)) {
-      DLOG(ERROR) << "Failed to initialize eglimage from texture id: "
-                  << texture_id_;
-      return false;
-    }
-
-    // Export the EGLImage as dmabuf.
-    gfx::NativePixmapHandle native_pixmap_handle = image->ExportHandle();
-    if (!native_pixmap_handle.planes.size()) {
-      DLOG(ERROR) << "Failed to export EGLImage as dmabuf fds";
-      return false;
-    }
-
-    // Convert NativePixmapHandle to NativePixmapDmaBuf.
-    scoped_refptr<gfx::NativePixmap> native_pixmap_dmabuf(
-        new gfx::NativePixmapDmaBuf(size_, format, native_pixmap_handle));
-    if (!native_pixmap_dmabuf->AreDmaBufFdsValid()) {
-      DLOG(ERROR) << "Invalid dmabuf fds";
-      return false;
-    }
-
-    if (!image->BindTexImage(texture_target_)) {
-      DLOG(ERROR) << "Failed to bind texture to GLImage";
-      return false;
-    }
-
-    // The |pixmap_| takes ownership of the dmabuf fds. So the only reason to
-    // to keep a reference on the image is because the GPU service needs to
-    // track this image as it will be attached to a client texture.
-    pixmap_ = native_pixmap_dmabuf;
-    gl_image_ = image;
-  }
-#endif  // USE_OZONE
-
-  if (!pixmap_) {
-    DVLOG(1) << "Failed allocating a pixmap";
-    return false;
-  }
-
-  return Initialize();
-}
-
-bool VaapiDrmPicture::ImportGpuMemoryBufferHandle(
-    gfx::BufferFormat format,
-    const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-#if defined(USE_OZONE)
-  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
-  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
-  // CreateNativePixmapFromHandle() will take ownership of the handle.
-  pixmap_ = factory->CreateNativePixmapFromHandle(
-      gfx::kNullAcceleratedWidget, size_, format,
-      gpu_memory_buffer_handle.native_pixmap_handle);
-#else
-  NOTIMPLEMENTED();
-#endif
-  if (!pixmap_) {
-    DVLOG(1) << "Failed creating a pixmap from a native handle";
-    return false;
-  }
-
-  return Initialize();
-}
-
-bool VaapiDrmPicture::DownloadFromSurface(
-    const scoped_refptr<VASurface>& va_surface) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return vaapi_wrapper_->BlitSurface(va_surface, va_surface_);
-}
-
-bool VaapiDrmPicture::AllowOverlay() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return true;
-}
-
-}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_drm_picture.h b/media/gpu/vaapi/vaapi_drm_picture.h
deleted file mode 100644
index d6acda3..0000000
--- a/media/gpu/vaapi/vaapi_drm_picture.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file contains an implementation of picture allocation for the
-// Ozone window system used by VaapiVideoDecodeAccelerator to produce
-// output pictures.
-
-#ifndef MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_
-#define MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "media/gpu/vaapi/vaapi_picture.h"
-#include "ui/gfx/buffer_types.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace gl {
-class GLImage;
-}
-
-namespace gfx {
-class NativePixmap;
-}
-
-namespace media {
-
-class VaapiWrapper;
-
-// Implementation of VaapiPicture for the ozone/drm backed chromium.
-class VaapiDrmPicture : public VaapiPicture {
- public:
-  VaapiDrmPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
-                  const MakeGLContextCurrentCallback& make_context_current_cb,
-                  const BindGLImageCallback& bind_image_cb_,
-                  int32_t picture_buffer_id,
-                  const gfx::Size& size,
-                  uint32_t texture_id,
-                  uint32_t client_texture_id,
-                  uint32_t texture_target);
-
-  ~VaapiDrmPicture() override;
-
-  bool Allocate(gfx::BufferFormat format) override;
-  bool ImportGpuMemoryBufferHandle(
-      gfx::BufferFormat format,
-      const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override;
-
-  bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
-
-  bool AllowOverlay() const override;
-
- private:
-  bool Initialize();
-
-  // Ozone buffer, the storage of the EGLImage and the VASurface.
-  scoped_refptr<gfx::NativePixmap> pixmap_;
-
-  // EGLImage bound to the GL textures used by the VDA client.
-  scoped_refptr<gl::GLImage> gl_image_;
-
-  // VASurface used to transfer from the decoder's pixel format.
-  scoped_refptr<VASurface> va_surface_;
-
-  DISALLOW_COPY_AND_ASSIGN(VaapiDrmPicture);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_
diff --git a/media/gpu/vaapi/vaapi_picture_factory.cc b/media/gpu/vaapi/vaapi_picture_factory.cc
index 5f4aa40..20ae5ab 100644
--- a/media/gpu/vaapi/vaapi_picture_factory.cc
+++ b/media/gpu/vaapi/vaapi_picture_factory.cc
@@ -7,10 +7,14 @@
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #include "ui/gl/gl_bindings.h"
 
-#include "media/gpu/vaapi/vaapi_drm_picture.h"
-
 #if defined(USE_X11)
-#include "media/gpu/vaapi/vaapi_tfp_picture.h"
+#include "media/gpu/vaapi/vaapi_picture_tfp.h"
+#endif
+#if defined(USE_OZONE)
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h"
+#endif
+#if defined(USE_EGL)
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h"
 #endif
 
 namespace media {
@@ -51,10 +55,17 @@
   // Select DRM(egl) / TFP(glx) at runtime with --use-gl=egl / --use-gl=desktop
   switch (GetVaapiImplementation(gl::GetGLImplementation())) {
     case kVaapiImplementationDrm:
-      picture.reset(new VaapiDrmPicture(vaapi_wrapper, make_context_current_cb,
-                                        bind_image_cb, picture_buffer_id, size,
-                                        texture_id, client_texture_id,
-                                        texture_target));
+#if defined(USE_OZONE)
+      picture.reset(new VaapiPictureNativePixmapOzone(
+          vaapi_wrapper, make_context_current_cb, bind_image_cb,
+          picture_buffer_id, size, texture_id, client_texture_id,
+          texture_target));
+#elif defined(USE_EGL)
+      picture.reset(new VaapiPictureNativePixmapEgl(
+          vaapi_wrapper, make_context_current_cb, bind_image_cb,
+          picture_buffer_id, size, texture_id, client_texture_id,
+          texture_target));
+#endif
       break;
 
 #if defined(USE_X11)
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap.cc
new file mode 100644
index 0000000..6ef8b6e
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap.cc
@@ -0,0 +1,67 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h"
+
+#include "media/gpu/vaapi/va_surface.h"
+#include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
+#include "ui/gfx/native_pixmap.h"
+#include "ui/gl/gl_image_native_pixmap.h"
+
+namespace media {
+
+VaapiPictureNativePixmap::VaapiPictureNativePixmap(
+    const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+    const MakeGLContextCurrentCallback& make_context_current_cb,
+    const BindGLImageCallback& bind_image_cb,
+    int32_t picture_buffer_id,
+    const gfx::Size& size,
+    uint32_t texture_id,
+    uint32_t client_texture_id,
+    uint32_t texture_target)
+    : VaapiPicture(vaapi_wrapper,
+                   make_context_current_cb,
+                   bind_image_cb,
+                   picture_buffer_id,
+                   size,
+                   texture_id,
+                   client_texture_id,
+                   texture_target) {}
+
+VaapiPictureNativePixmap::~VaapiPictureNativePixmap() = default;
+
+bool VaapiPictureNativePixmap::DownloadFromSurface(
+    const scoped_refptr<VASurface>& va_surface) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return vaapi_wrapper_->BlitSurface(va_surface, va_surface_);
+}
+
+bool VaapiPictureNativePixmap::AllowOverlay() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return true;
+}
+
+unsigned VaapiPictureNativePixmap::BufferFormatToInternalFormat(
+    gfx::BufferFormat format) const {
+  switch (format) {
+    case gfx::BufferFormat::BGRX_8888:
+    case gfx::BufferFormat::RGBX_8888:
+      return GL_RGB;
+
+    case gfx::BufferFormat::BGRA_8888:
+      return GL_BGRA_EXT;
+
+    case gfx::BufferFormat::YVU_420:
+      return GL_RGB_YCRCB_420_CHROMIUM;
+
+    default:
+      NOTREACHED() << gfx::BufferFormatToString(format);
+      return GL_BGRA_EXT;
+  }
+}
+
+}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap.h b/media/gpu/vaapi/vaapi_picture_native_pixmap.h
new file mode 100644
index 0000000..ab852425
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap.h
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_
+#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_
+
+#include <stdint.h>
+
+#include "base/memory/ref_counted.h"
+#include "media/gpu/vaapi/vaapi_picture.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace gl {
+class GLImage;
+}
+
+namespace gfx {
+class NativePixmap;
+}
+
+namespace media {
+
+class VaapiWrapper;
+
+// Implementation of VaapiPicture based on NativePixmaps.
+class VaapiPictureNativePixmap : public VaapiPicture {
+ public:
+  VaapiPictureNativePixmap(
+      const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+      const MakeGLContextCurrentCallback& make_context_current_cb,
+      const BindGLImageCallback& bind_image_cb_,
+      int32_t picture_buffer_id,
+      const gfx::Size& size,
+      uint32_t texture_id,
+      uint32_t client_texture_id,
+      uint32_t texture_target);
+  ~VaapiPictureNativePixmap() override;
+
+  // VaapiPicture implementation.
+  bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
+  bool AllowOverlay() const override;
+
+  unsigned BufferFormatToInternalFormat(gfx::BufferFormat format) const;
+
+ protected:
+  // Ozone buffer, the storage of the EGLImage and the VASurface.
+  scoped_refptr<gfx::NativePixmap> pixmap_;
+
+  // GLImage bound to the GL textures used by the VDA client.
+  scoped_refptr<gl::GLImage> gl_image_;
+
+  // VASurface used to transfer from the decoder's pixel format.
+  scoped_refptr<VASurface> va_surface_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmap);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
new file mode 100644
index 0000000..f7d4981
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
@@ -0,0 +1,133 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h"
+
+#include "base/file_descriptor_posix.h"
+#include "media/gpu/vaapi/va_surface.h"
+#include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
+#include "ui/gfx/native_pixmap.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_image_native_pixmap.h"
+#include "ui/gl/scoped_binders.h"
+
+namespace media {
+
+VaapiPictureNativePixmapEgl::VaapiPictureNativePixmapEgl(
+    const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+    const MakeGLContextCurrentCallback& make_context_current_cb,
+    const BindGLImageCallback& bind_image_cb,
+    int32_t picture_buffer_id,
+    const gfx::Size& size,
+    uint32_t texture_id,
+    uint32_t client_texture_id,
+    uint32_t texture_target)
+    : VaapiPictureNativePixmap(vaapi_wrapper,
+                               make_context_current_cb,
+                               bind_image_cb,
+                               picture_buffer_id,
+                               size,
+                               texture_id,
+                               client_texture_id,
+                               texture_target) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+VaapiPictureNativePixmapEgl::~VaapiPictureNativePixmapEgl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (gl_image_ && make_context_current_cb_.Run()) {
+    gl_image_->ReleaseTexImage(texture_target_);
+    DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
+  }
+}
+
+bool VaapiPictureNativePixmapEgl::Initialize() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(pixmap_);
+
+  // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
+  va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_);
+  if (!va_surface_) {
+    LOG(ERROR) << "Failed creating VASurface for NativePixmap";
+    return false;
+  }
+
+  // On non-ozone, no need to import dmabuf fds into output the gl texture
+  // because the dmabuf fds have been made from it.
+  DCHECK(pixmap_->AreDmaBufFdsValid());
+
+  if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) {
+    if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
+                            true)) {
+      LOG(ERROR) << "Failed to bind client_texture_id";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool VaapiPictureNativePixmapEgl::Allocate(gfx::BufferFormat format) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // Export the gl texture as dmabuf.
+  if (texture_id_ != 0 && !make_context_current_cb_.is_null()) {
+    if (!make_context_current_cb_.Run())
+      return false;
+
+    scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap(
+        size_, BufferFormatToInternalFormat(format)));
+
+    // Create an EGLImage from a gl texture
+    if (!image->InitializeFromTexture(texture_id_)) {
+      DLOG(ERROR) << "Failed to initialize eglimage from texture id: "
+                  << texture_id_;
+      return false;
+    }
+
+    // Export the EGLImage as dmabuf.
+    gfx::NativePixmapHandle native_pixmap_handle = image->ExportHandle();
+    if (!native_pixmap_handle.planes.size()) {
+      DLOG(ERROR) << "Failed to export EGLImage as dmabuf fds";
+      return false;
+    }
+
+    // Convert NativePixmapHandle to NativePixmapDmaBuf.
+    scoped_refptr<gfx::NativePixmap> native_pixmap_dmabuf(
+        new gfx::NativePixmapDmaBuf(size_, format, native_pixmap_handle));
+    if (!native_pixmap_dmabuf->AreDmaBufFdsValid()) {
+      DLOG(ERROR) << "Invalid dmabuf fds";
+      return false;
+    }
+
+    if (!image->BindTexImage(texture_target_)) {
+      DLOG(ERROR) << "Failed to bind texture to GLImage";
+      return false;
+    }
+
+    // The |pixmap_| takes ownership of the dmabuf fds. So the only reason
+    // to keep a reference on the image is because the GPU service needs to
+    // track this image as it will be attached to a client texture.
+    pixmap_ = native_pixmap_dmabuf;
+    gl_image_ = image;
+  }
+
+  if (!pixmap_) {
+    DVLOG(1) << "Failed allocating a pixmap";
+    return false;
+  }
+
+  return Initialize();
+}
+
+bool VaapiPictureNativePixmapEgl::ImportGpuMemoryBufferHandle(
+    gfx::BufferFormat format,
+    const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  NOTIMPLEMENTED();
+  return false;
+}
+
+}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h
new file mode 100644
index 0000000..17e17e4
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_
+#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+class VaapiWrapper;
+
+// Implementation of VaapiPictureNativePixmap for EGL backends, see
+// https://crbug.com/785201.
+class VaapiPictureNativePixmapEgl : public VaapiPictureNativePixmap {
+ public:
+  VaapiPictureNativePixmapEgl(
+      const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+      const MakeGLContextCurrentCallback& make_context_current_cb,
+      const BindGLImageCallback& bind_image_cb_,
+      int32_t picture_buffer_id,
+      const gfx::Size& size,
+      uint32_t texture_id,
+      uint32_t client_texture_id,
+      uint32_t texture_target);
+
+  ~VaapiPictureNativePixmapEgl() override;
+
+  // VaapiPicture implementation.
+  bool Allocate(gfx::BufferFormat format) override;
+  bool ImportGpuMemoryBufferHandle(
+      gfx::BufferFormat format,
+      const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override;
+
+ private:
+  bool Initialize();
+
+  DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmapEgl);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
new file mode 100644
index 0000000..48e4850c
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
@@ -0,0 +1,128 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h"
+
+#include "media/gpu/vaapi/va_surface.h"
+#include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
+#include "ui/gfx/native_pixmap.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_image_native_pixmap.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace media {
+
+VaapiPictureNativePixmapOzone::VaapiPictureNativePixmapOzone(
+    const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+    const MakeGLContextCurrentCallback& make_context_current_cb,
+    const BindGLImageCallback& bind_image_cb,
+    int32_t picture_buffer_id,
+    const gfx::Size& size,
+    uint32_t texture_id,
+    uint32_t client_texture_id,
+    uint32_t texture_target)
+    : VaapiPictureNativePixmap(vaapi_wrapper,
+                               make_context_current_cb,
+                               bind_image_cb,
+                               picture_buffer_id,
+                               size,
+                               texture_id,
+                               client_texture_id,
+                               texture_target) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+VaapiPictureNativePixmapOzone::~VaapiPictureNativePixmapOzone() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (gl_image_ && make_context_current_cb_.Run()) {
+    gl_image_->ReleaseTexImage(texture_target_);
+    DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
+  }
+}
+
+bool VaapiPictureNativePixmapOzone::Initialize() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(pixmap_);
+
+  // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
+  va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_);
+  if (!va_surface_) {
+    LOG(ERROR) << "Failed creating VASurface for NativePixmap";
+    return false;
+  }
+
+  // Import dmabuf fds into the output gl texture through EGLImage.
+  if (texture_id_ != 0 && !make_context_current_cb_.is_null()) {
+    if (!make_context_current_cb_.Run())
+      return false;
+
+    gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
+
+    gfx::BufferFormat format = pixmap_->GetBufferFormat();
+
+    scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap(
+        size_, BufferFormatToInternalFormat(format)));
+    if (!image->Initialize(pixmap_.get(), format)) {
+      LOG(ERROR) << "Failed to create GLImage";
+      return false;
+    }
+    gl_image_ = image;
+    if (!gl_image_->BindTexImage(texture_target_)) {
+      LOG(ERROR) << "Failed to bind texture to GLImage";
+      return false;
+    }
+  }
+
+  if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) {
+    if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
+                            true)) {
+      LOG(ERROR) << "Failed to bind client_texture_id";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool VaapiPictureNativePixmapOzone::Allocate(gfx::BufferFormat format) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+  pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size_,
+                                        format, gfx::BufferUsage::SCANOUT);
+
+  if (!pixmap_) {
+    DVLOG(1) << "Failed allocating a pixmap";
+    return false;
+  }
+
+  return Initialize();
+}
+
+bool VaapiPictureNativePixmapOzone::ImportGpuMemoryBufferHandle(
+    gfx::BufferFormat format,
+    const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+  // CreateNativePixmapFromHandle() will take ownership of the handle.
+  pixmap_ = factory->CreateNativePixmapFromHandle(
+      gfx::kNullAcceleratedWidget, size_, format,
+      gpu_memory_buffer_handle.native_pixmap_handle);
+
+  if (!pixmap_) {
+    DVLOG(1) << "Failed creating a pixmap from a native handle";
+    return false;
+  }
+
+  return Initialize();
+}
+
+}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
new file mode 100644
index 0000000..23ebfe0a
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_
+#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+class VaapiWrapper;
+
+// Implementation of VaapiPictureNativePixmap using Ozone.
+class VaapiPictureNativePixmapOzone : public VaapiPictureNativePixmap {
+ public:
+  VaapiPictureNativePixmapOzone(
+      const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
+      const MakeGLContextCurrentCallback& make_context_current_cb,
+      const BindGLImageCallback& bind_image_cb_,
+      int32_t picture_buffer_id,
+      const gfx::Size& size,
+      uint32_t texture_id,
+      uint32_t client_texture_id,
+      uint32_t texture_target);
+
+  ~VaapiPictureNativePixmapOzone() override;
+
+  // VaapiPicture implementation.
+  bool Allocate(gfx::BufferFormat format) override;
+  bool ImportGpuMemoryBufferHandle(
+      gfx::BufferFormat format,
+      const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override;
+
+ private:
+  bool Initialize();
+
+  DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmapOzone);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_
diff --git a/media/gpu/vaapi/vaapi_tfp_picture.cc b/media/gpu/vaapi/vaapi_picture_tfp.cc
similarity index 98%
rename from media/gpu/vaapi/vaapi_tfp_picture.cc
rename to media/gpu/vaapi/vaapi_picture_tfp.cc
index 4e45b57..30d6f0d97 100644
--- a/media/gpu/vaapi/vaapi_tfp_picture.cc
+++ b/media/gpu/vaapi/vaapi_picture_tfp.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/gpu/vaapi/vaapi_tfp_picture.h"
+#include "media/gpu/vaapi/vaapi_picture_tfp.h"
 
 #include "media/gpu/vaapi/va_surface.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
diff --git a/media/gpu/vaapi/vaapi_tfp_picture.h b/media/gpu/vaapi/vaapi_picture_tfp.h
similarity index 79%
rename from media/gpu/vaapi/vaapi_tfp_picture.h
rename to media/gpu/vaapi/vaapi_picture_tfp.h
index a386118..a9ba8a1 100644
--- a/media/gpu/vaapi/vaapi_tfp_picture.h
+++ b/media/gpu/vaapi/vaapi_picture_tfp.h
@@ -1,13 +1,9 @@
 // Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// This file contains an implementation of picture allocation for the
-// X11 window system used by VaapiVideoDecodeAccelerator to produce
-// output pictures.
 
-#ifndef MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_
-#define MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_
+#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_
+#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_
 
 #include <stdint.h>
 
@@ -25,7 +21,8 @@
 
 class VaapiWrapper;
 
-// Implementation of VaapiPicture for the X11 backed chromium.
+// Implementation of VaapiPicture for the X11 backends with Texture-From-Pixmap
+// extension.
 class VaapiTFPPicture : public VaapiPicture {
  public:
   VaapiTFPPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
@@ -39,11 +36,11 @@
 
   ~VaapiTFPPicture() override;
 
+  // VaapiPicture implementation.
   bool Allocate(gfx::BufferFormat format) override;
   bool ImportGpuMemoryBufferHandle(
       gfx::BufferFormat format,
       const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override;
-
   bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override;
 
  private:
@@ -59,4 +56,4 @@
 
 }  // namespace media
 
-#endif  // MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_
+#endif  // MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_
diff --git a/media/gpu/windows/d3d11_picture_buffer.cc b/media/gpu/windows/d3d11_picture_buffer.cc
index 022c60d..1fbb749 100644
--- a/media/gpu/windows/d3d11_picture_buffer.cc
+++ b/media/gpu/windows/d3d11_picture_buffer.cc
@@ -28,7 +28,7 @@
 namespace {
 
 static bool MakeContextCurrent(gpu::CommandBufferStub* stub) {
-  return stub && stub->decoder()->MakeCurrent();
+  return stub && stub->decoder_context()->MakeCurrent();
 }
 
 }  // namespace
@@ -100,8 +100,8 @@
   // TODO(liberato): see GpuVideoFrameFactory.
   // stub_->AddDestructionObserver(this);
 
-  auto decoder_helper = GLES2DecoderHelper::Create(stub->decoder());
-  gpu::gles2::ContextGroup* group = stub->decoder()->GetContextGroup();
+  auto decoder_helper = GLES2DecoderHelper::Create(stub->decoder_context());
+  gpu::gles2::ContextGroup* group = stub->decoder_context()->GetContextGroup();
   gpu::MailboxManager* mailbox_manager = group->mailbox_manager();
   gpu::gles2::TextureManager* texture_manager = group->texture_manager();
   RETURN_ON_FAILURE(!!texture_manager, "No texture manager", false);
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index 7440598..1489c65 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -73,8 +73,8 @@
     bool low_delay,
     CdmContext* cdm_context,
     const InitCB& init_cb,
-    const OutputCB& output_cb const
-        WaitingForDecryptionKeyCB& /* waiting_for_decryption_key_cb */) {
+    const OutputCB& output_cb,
+    const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) {
   bool is_h264 = config.profile() >= H264PROFILE_MIN &&
                  config.profile() <= H264PROFILE_MAX;
   if (!is_h264) {
@@ -90,7 +90,9 @@
       base::BindOnce(
           &VideoDecoder::Initialize, impl_weak_, config, low_delay, cdm_context,
           BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), init_cb),
-          BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), output_cb)));
+          BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), output_cb),
+          BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(),
+                                       waiting_for_decryption_key_cb)));
 }
 
 void D3D11VideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.cc b/media/gpu/windows/d3d11_video_decoder_impl.cc
index 0e9c469..a56fc02 100644
--- a/media/gpu/windows/d3d11_video_decoder_impl.cc
+++ b/media/gpu/windows/d3d11_video_decoder_impl.cc
@@ -22,7 +22,7 @@
 namespace {
 
 static bool MakeContextCurrent(gpu::CommandBufferStub* stub) {
-  return stub && stub->decoder()->MakeCurrent();
+  return stub && stub->decoder_context()->MakeCurrent();
 }
 
 }  // namespace
@@ -41,11 +41,13 @@
   return "D3D11VideoDecoderImpl";
 }
 
-void D3D11VideoDecoderImpl::Initialize(const VideoDecoderConfig& config,
-                                       bool low_delay,
-                                       CdmContext* cdm_context,
-                                       const InitCB& init_cb,
-                                       const OutputCB& output_cb) {
+void D3D11VideoDecoderImpl::Initialize(
+    const VideoDecoderConfig& config,
+    bool low_delay,
+    CdmContext* cdm_context,
+    const InitCB& init_cb,
+    const OutputCB& output_cb,
+    const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) {
   init_cb_ = init_cb;
   output_cb_ = output_cb;
 
@@ -153,9 +155,9 @@
     return;
   }
 
-  h264_accelerator_.reset(new D3D11H264Accelerator(
-      this, video_decoder, video_device_, video_context_));
-  decoder_.reset(new media::H264Decoder(h264_accelerator_.get()));
+  accelerated_video_decoder_ =
+      std::make_unique<H264Decoder>(std::make_unique<D3D11H264Accelerator>(
+          this, video_decoder, video_device_, video_context_));
 
   state_ = State::kRunning;
   std::move(init_cb_).Run(true);
@@ -192,7 +194,7 @@
     if (current_buffer_->end_of_stream()) {
       // Flush, then signal the decode cb once all pictures have been output.
       current_buffer_ = nullptr;
-      if (!decoder_->Flush()) {
+      if (!accelerated_video_decoder_->Flush()) {
         // This will also signal error |current_decode_cb_|.
         NotifyError("Flush failed");
         return;
@@ -202,8 +204,8 @@
       std::move(current_decode_cb_).Run(DecodeStatus::OK);
       return;
     }
-    decoder_->SetStream((const uint8_t*)current_buffer_->data(),
-                        current_buffer_->data_size());
+    accelerated_video_decoder_->SetStream(
+        (const uint8_t*)current_buffer_->data(), current_buffer_->data_size());
   }
 
   while (true) {
@@ -211,7 +213,8 @@
     if (state_ == State::kError)
       return;
 
-    media::AcceleratedVideoDecoder::DecodeResult result = decoder_->Decode();
+    media::AcceleratedVideoDecoder::DecodeResult result =
+        accelerated_video_decoder_->Decode();
     // TODO(liberato): switch + class enum.
     if (result == media::AcceleratedVideoDecoder::kRanOutOfStreamData) {
       current_buffer_ = nullptr;
@@ -248,7 +251,7 @@
   input_buffer_queue_.clear();
 
   // TODO(liberato): how do we signal an error?
-  decoder_->Reset();
+  accelerated_video_decoder_->Reset();
   closure.Run();
 }
 
@@ -272,7 +275,7 @@
   // the VDA requests 20.
   const int num_buffers = 20;
 
-  gfx::Size size = decoder_->GetPicSize();
+  gfx::Size size = accelerated_video_decoder_->GetPicSize();
 
   // Create an array of |num_buffers| elements to back the PictureBuffers.
   D3D11_TEXTURE2D_DESC texture_desc = {};
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.h b/media/gpu/windows/d3d11_video_decoder_impl.h
index 0a89262..2a2039c 100644
--- a/media/gpu/windows/d3d11_video_decoder_impl.h
+++ b/media/gpu/windows/d3d11_video_decoder_impl.h
@@ -33,11 +33,13 @@
 
   // VideoDecoder implementation:
   std::string GetDisplayName() const override;
-  void Initialize(const VideoDecoderConfig& config,
-                  bool low_delay,
-                  CdmContext* cdm_context,
-                  const InitCB& init_cb,
-                  const OutputCB& output_cb) override;
+  void Initialize(
+      const VideoDecoderConfig& config,
+      bool low_delay,
+      CdmContext* cdm_context,
+      const InitCB& init_cb,
+      const OutputCB& output_cb,
+      const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) override;
   void Decode(const scoped_refptr<DecoderBuffer>& buffer,
               const DecodeCB& decode_cb) override;
   void Reset(const base::Closure& closure) override;
@@ -82,8 +84,7 @@
   Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
   Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_;
 
-  std::unique_ptr<AcceleratedVideoDecoder> decoder_;
-  std::unique_ptr<D3D11H264Accelerator> h264_accelerator_;
+  std::unique_ptr<AcceleratedVideoDecoder> accelerated_video_decoder_;
 
   GUID decoder_guid_;
 
diff --git a/media/media_options.gni b/media/media_options.gni
index 9d821803..5aa62d6 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -81,9 +81,6 @@
 
   # If true, use cast CMA backend instead of default chromium media pipeline.
   is_cast_using_cma_backend = is_cast_audio_only || !is_android
-
-  # A temporary arg for enabling D3D11VideoDecoder
-  enable_d3d11_video_decoder = false
 }
 
 # enable_hls_sample_aes can only be true if enable_mse_mpeg2ts_stream_parser is.
@@ -135,8 +132,8 @@
   # |mojo_media_services|). When enabled, selected mojo paths will be enabled in
   # the media pipeline and corresponding services will hosted in the selected
   # remote process (e.g. "utility" process, see |mojo_media_host|).
-  enable_mojo_media = is_android || is_chromecast || enable_library_cdms ||
-                      enable_d3d11_video_decoder
+  enable_mojo_media =
+      is_android || is_chromecast || enable_library_cdms || is_win
 
   # Enable the TestMojoMediaClient to be used in mojo MediaService. This is for
   # testing only and will override the default platform MojoMediaClient, if any.
@@ -203,41 +200,41 @@
   # - "gpu": Use mojo media service hosted in the gpu process.
   # - "utility": Use mojo media service hosted in the utility process.
   mojo_media_host = "none"
+}
 
-  # Default mojo_media_services and mojo_media_host on various platforms.
-  # Can be overridden by gn build arguments from the --args command line flag
-  # for local testing.
-  if (enable_mojo_media) {
-    if (is_chromecast && is_cast_using_cma_backend) {
-      mojo_media_services = [
-        "cdm",
-        "renderer",
-      ]
-      mojo_media_host = "browser"
-    } else if (is_android) {
-      # Both chrome for Android and cast for ATV belongs to this case
-      mojo_media_services = [
-        "cdm",
-        "audio_decoder",
-      ]
-      mojo_media_services += [ "video_decoder" ]
-      mojo_media_host = "gpu"
-    } else if (enable_library_cdms) {
-      mojo_media_services = [ "cdm" ]
-      mojo_media_host = "gpu"
-    }
+# Default mojo_media_services and mojo_media_host on various platforms.
+# Can be overridden by gn build arguments from the --args command line flag
+# for local testing.
+if (enable_mojo_media) {
+  if (is_chromecast && is_cast_using_cma_backend) {
+    mojo_media_services = [
+      "cdm",
+      "renderer",
+    ]
+    mojo_media_host = "browser"
+  } else if (is_android) {
+    # Both chrome for Android and cast for ATV belongs to this case
+    mojo_media_services = [
+      "cdm",
+      "audio_decoder",
+      "video_decoder",
+    ]
+    mojo_media_host = "gpu"
+  } else if (is_win) {
+    mojo_media_services += [ "video_decoder" ]
+    mojo_media_host = "gpu"
+  }
 
-    if (is_win) {
-      if (enable_d3d11_video_decoder) {
-        mojo_media_services += [
-          "cdm",
-          "video_decoder",
-        ]
+  if (enable_library_cdms) {
+    mojo_media_services += [ "cdm" ]
+    assert(
+        mojo_media_host == "none" || mojo_media_host == "gpu",
+        "For now, mojo_media_host should not overwrite it with a different " +
+            "value if it has been set.")
 
-        # TODO(liberato): This is temporary.
-        mojo_media_host = "gpu"
-      }
-    }
+    # Having a CDM running means it could require a CdmProxy running in the GPU
+    # process.
+    mojo_media_host = "gpu"
   }
 }
 
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 0f37f63..e2ff8b1 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -31,9 +31,9 @@
 #endif  // defined(OS_ANDROID)
 
 // OS_WIN guards are needed for cross-compiling on linux.
-#if defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)
+#if defined(OS_WIN)
 #include "media/gpu/windows/d3d11_video_decoder.h"
-#endif  // BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)
+#endif  // defined(OS_WIN)
 
 namespace media {
 
@@ -61,8 +61,7 @@
 }
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_ANDROID) || \
-    (defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER))
+#if defined(OS_ANDROID) || defined(OS_WIN)
 gpu::CommandBufferStub* GetCommandBufferStub(
     base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager,
     base::UnguessableToken channel_token,
@@ -77,7 +76,7 @@
 
   return channel->LookupCommandBuffer(route_id);
 }
-#endif  // OS_ANDROID || (OS_WIN && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER))
+#endif  // OS_ANDROID || OS_WIN
 
 }  // namespace
 
@@ -123,7 +122,7 @@
       android_overlay_factory_cb_, std::move(request_overlay_info_cb),
       std::make_unique<VideoFrameFactoryImpl>(gpu_task_runner_,
                                               std::move(get_stub_cb)));
-#elif defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)
+#elif defined(OS_WIN)
   return std::make_unique<D3D11VideoDecoder>(
       gpu_task_runner_,
       base::BindRepeating(&GetCommandBufferStub, media_gpu_channel_manager_,
diff --git a/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java b/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java
index c5f50d0..ec39f80a 100644
--- a/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java
+++ b/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java
@@ -70,7 +70,14 @@
                     != ApplicationState.HAS_RUNNING_ACTIVITIES) {
                 return;
             }
-            mSignalLevel = signalStrength.getLevel();
+            try {
+                mSignalLevel = signalStrength.getLevel();
+            } catch (SecurityException e) {
+                // Catch any exceptions thrown due to unavailability of permissions on certain
+                // Android devices. See  https://crbug.com/820564 for details.
+                mSignalLevel = CellularSignalStrengthError.ERROR_NOT_SUPPORTED;
+                assert false;
+            }
         }
 
         // ApplicationStatus.ApplicationStateListener
diff --git a/net/proxy_resolution/proxy_config_with_annotation.cc b/net/proxy_resolution/proxy_config_with_annotation.cc
index 31ddb8a..b4541ff 100644
--- a/net/proxy_resolution/proxy_config_with_annotation.cc
+++ b/net/proxy_resolution/proxy_config_with_annotation.cc
@@ -8,16 +8,17 @@
 
 namespace {
 
-// TODO(rhalavati): Update annotation.
 constexpr NetworkTrafficAnnotationTag kDirectProxyTrafficAnnotation =
     DefineNetworkTrafficAnnotation("proxy_config_direct", R"(
     semantics {
       sender: "Proxy Config"
       description:
-        "This settings create a direct proxy, which practically connects "
-        "directly to the target website without any intervention."
+        "Direct connections are being used instead of a proxy. This is a place "
+        "holder annotation that would include details about where the "
+        "configuration, which can trigger fetching a PAC file, came from."
       trigger:
-        "Direct proxy is the default mode of connection."
+        "Connecting directly to destination sites instead of using a proxy is "
+        "the default behavior."
       data:
         "None."
       destination: WEBSITE
@@ -25,7 +26,8 @@
     policy {
       cookies_allowed: NO
       setting:
-        "Selecting a proxy in settings will prevent use of direct proxy."
+        "This isn't a real network request. A proxy can be selected in "
+        "settings."
       policy_exception_justification:
         "Using either of 'ProxyMode', 'ProxyServer', or 'ProxyPacUrl' policies "
         "can set Chrome to use a specific proxy settings and avoid directly "
diff --git a/pdf/run_all_unittests.cc b/pdf/run_all_unittests.cc
index 138e5a2..a700cb9 100644
--- a/pdf/run_all_unittests.cc
+++ b/pdf/run_all_unittests.cc
@@ -20,5 +20,5 @@
   base::TestSuite test_suite(argc, argv);
   return base::LaunchUnitTests(
       argc, argv,
-      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
+      base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
 }
diff --git a/services/catalog/BUILD.gn b/services/catalog/BUILD.gn
index 594b4fb..b47cf5d 100644
--- a/services/catalog/BUILD.gn
+++ b/services/catalog/BUILD.gn
@@ -38,7 +38,7 @@
   deps = [
     ":constants",
     "//base",
-    "//components/filesystem:lib",
+    "//components/services/filesystem:lib",
     "//services/catalog/public/cpp",
     "//services/catalog/public/mojom",
     "//services/service_manager/public/cpp",
@@ -46,7 +46,7 @@
 
   public_deps = [
     # directory.mojom.h is #included by catalog.h
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
   ]
 }
 
diff --git a/services/catalog/DEPS b/services/catalog/DEPS
index 46b0331..25aecc83 100644
--- a/services/catalog/DEPS
+++ b/services/catalog/DEPS
@@ -1,3 +1,3 @@
 include_rules = [
-  "+components/filesystem"
+  "+components/services/filesystem"
 ]
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc
index d1763702..71455ef0 100644
--- a/services/catalog/catalog.cc
+++ b/services/catalog/catalog.cc
@@ -20,9 +20,9 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_scheduler/post_task.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/lock_table.h"
-#include "components/filesystem/public/interfaces/types.mojom.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/catalog/constants.h"
 #include "services/catalog/entry_cache.h"
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h
index 8ea3159..1cd8d382 100644
--- a/services/catalog/catalog.h
+++ b/services/catalog/catalog.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/catalog/entry_cache.h"
diff --git a/services/catalog/public/cpp/BUILD.gn b/services/catalog/public/cpp/BUILD.gn
index 0fbdf132..febd1d7 100644
--- a/services/catalog/public/cpp/BUILD.gn
+++ b/services/catalog/public/cpp/BUILD.gn
@@ -12,7 +12,7 @@
 
   deps = [
     "//base",
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
     "//services/catalog:constants",
diff --git a/services/catalog/public/cpp/resource_loader.cc b/services/catalog/public/cpp/resource_loader.cc
index 90afc1e5..2c106417 100644
--- a/services/catalog/public/cpp/resource_loader.cc
+++ b/services/catalog/public/cpp/resource_loader.cc
@@ -9,7 +9,7 @@
 
 #include "base/bind.h"
 #include "base/files/file.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
diff --git a/services/catalog/public/cpp/resource_loader.h b/services/catalog/public/cpp/resource_loader.h
index 738be36..2ff3221d41 100644
--- a/services/catalog/public/cpp/resource_loader.h
+++ b/services/catalog/public/cpp/resource_loader.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 
 namespace base {
 class File;
diff --git a/services/file/BUILD.gn b/services/file/BUILD.gn
index 0e402e0..1bd2822e 100644
--- a/services/file/BUILD.gn
+++ b/services/file/BUILD.gn
@@ -17,10 +17,10 @@
 
   deps = [
     "//base",
-    "//components/filesystem:lib",
-    "//components/filesystem/public/interfaces",
-    "//components/leveldb:lib",
-    "//components/leveldb/public/interfaces",
+    "//components/services/filesystem:lib",
+    "//components/services/filesystem/public/interfaces",
+    "//components/services/leveldb:lib",
+    "//components/services/leveldb/public/interfaces",
     "//mojo/common",
     "//mojo/common:common_base",
     "//services/file/public/mojom",
diff --git a/services/file/DEPS b/services/file/DEPS
index 798ec210..e1577c7 100644
--- a/services/file/DEPS
+++ b/services/file/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
-  "+components/filesystem",
-  "+components/leveldb",
+  "+components/services/filesystem",
+  "+components/services/leveldb",
 ]
diff --git a/services/file/file_service.cc b/services/file/file_service.cc
index 18335a20..c9738152 100644
--- a/services/file/file_service.cc
+++ b/services/file/file_service.cc
@@ -8,8 +8,8 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task_scheduler/post_task.h"
-#include "components/filesystem/lock_table.h"
-#include "components/leveldb/leveldb_service_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/file/file_system.h"
 #include "services/file/user_id_map.h"
diff --git a/services/file/file_service.h b/services/file/file_service.h
index 977007c..8cd9814 100644
--- a/services/file/file_service.h
+++ b/services/file/file_service.h
@@ -8,8 +8,8 @@
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
-#include "components/filesystem/lock_table.h"
-#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/file/public/mojom/file_system.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
diff --git a/services/file/file_system.cc b/services/file/file_system.cc
index 92a41f83..9ec52419 100644
--- a/services/file/file_system.cc
+++ b/services/file/file_system.cc
@@ -14,9 +14,9 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/filesystem/directory_impl.h"
-#include "components/filesystem/lock_table.h"
-#include "components/filesystem/public/interfaces/types.mojom.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/public/interfaces/types.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
 namespace file {
diff --git a/services/file/file_system.h b/services/file/file_system.h
index 45dbda27..0e1800b 100644
--- a/services/file/file_system.h
+++ b/services/file/file_system.h
@@ -6,7 +6,7 @@
 #define SERVICES_FILE_FILE_SYSTEM_H_
 
 #include "base/files/file_path.h"
-#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/services/filesystem/public/interfaces/directory.mojom.h"
 #include "services/file/public/mojom/file_system.mojom.h"
 
 namespace filesystem {
diff --git a/services/file/public/mojom/BUILD.gn b/services/file/public/mojom/BUILD.gn
index 98b0cc0b1..38118ee 100644
--- a/services/file/public/mojom/BUILD.gn
+++ b/services/file/public/mojom/BUILD.gn
@@ -10,7 +10,7 @@
   ]
 
   deps = [
-    "//components/filesystem/public/interfaces",
+    "//components/services/filesystem/public/interfaces",
   ]
 
   public_deps = [
diff --git a/services/file/public/mojom/file_system.mojom b/services/file/public/mojom/file_system.mojom
index 2d2659c..e513a8c 100644
--- a/services/file/public/mojom/file_system.mojom
+++ b/services/file/public/mojom/file_system.mojom
@@ -4,7 +4,7 @@
 
 module file.mojom;
 
-import "components/filesystem/public/interfaces/directory.mojom";
+import "components/services/filesystem/public/interfaces/directory.mojom";
 import "mojo/public/mojom/base/file_error.mojom";
 
 // Provide access to various directories within the requesting user's directory.
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc
index 1d465ac..467a282 100644
--- a/services/network/resource_scheduler.cc
+++ b/services/network/resource_scheduler.cc
@@ -1257,6 +1257,11 @@
   static const char kNonDelayableWeightBase[] = "NonDelayableWeight";
 
   ParamsForNetworkQualityContainer result;
+  // Set the default params for networks with ECT Slow2G and 2G. These params
+  // can still be overridden using the field trial.
+  result.push_back({net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, 8, 3});
+  result.push_back({net::EFFECTIVE_CONNECTION_TYPE_2G, 8, 3});
+
   if (!base::FeatureList::IsEnabled(kThrottleDelayable))
     return result;
 
@@ -1290,8 +1295,22 @@
       return result;
     }
 
-    result.push_back({effective_connection_type.value(), max_delayable_requests,
-                      non_delayable_weight});
+    // Check if the entry is already present. This will happen if the default
+    // params are being overridden by the field trial.
+    bool entry_found = false;
+    for (auto& range : result) {
+      if (effective_connection_type == range.effective_connection_type) {
+        range.max_delayable_requests = max_delayable_requests;
+        range.non_delayable_weight = non_delayable_weight;
+        entry_found = true;
+        break;
+      }
+    }
+
+    if (!entry_found) {
+      result.push_back({effective_connection_type.value(),
+                        max_delayable_requests, non_delayable_weight});
+    }
     config_param_index++;
   }
 }
diff --git a/services/network/resource_scheduler_unittest.cc b/services/network/resource_scheduler_unittest.cc
index 99cdd3d..a22bd06b 100644
--- a/services/network/resource_scheduler_unittest.cc
+++ b/services/network/resource_scheduler_unittest.cc
@@ -281,7 +281,7 @@
                                           experiment_status, 0.0);
 
     // Set the effective connection type to Slow-2G, which is slower than the
-    // threshold configured in |InitializeMaxDelayableRequestsExperiment|. Needs
+    // threshold configured in |InitializeThrottleDelayableExperiment|. Needs
     // to be done before initializing the scheduler because the client is
     // created on the call to |InitializeScheduler|, which is where the initial
     // limits for the delayable requests in flight are computed.
@@ -303,7 +303,7 @@
     EXPECT_TRUE(high2->started());
 
     // Should match the configuration set by
-    // |InitializeMaxDelayableRequestsExperiment|
+    // |InitializeThrottleDelayableExperiment|
     const int kOverriddenNumRequests = 2;
 
     std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
@@ -366,7 +366,7 @@
       experiment_enabled = true;
       params["EffectiveConnectionType1"] = "Slow-2G";
       if (params["MaxDelayableRequests1"] == "")
-        params["MaxDelayableRequests1"] = "10";
+        params["MaxDelayableRequests1"] = "8";
       params["NonDelayableWeight1"] =
           base::NumberToString(non_delayable_weight);
     }
@@ -395,26 +395,38 @@
             ResourceScheduler::GetParamsForNetworkQualityContainerForTests();
 
     if (!lower_delayable_count_enabled && non_delayable_weight <= 0.0) {
-      ASSERT_EQ(0u, params_network_quality_container.size());
+      ASSERT_EQ(2u, params_network_quality_container.size());
+      EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
+                params_network_quality_container[0].effective_connection_type);
+      EXPECT_EQ(8u, params_network_quality_container[0].max_delayable_requests);
+      EXPECT_EQ(3.0, params_network_quality_container[0].non_delayable_weight);
+
+      EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+                params_network_quality_container[1].effective_connection_type);
+      EXPECT_EQ(8u, params_network_quality_container[1].max_delayable_requests);
+      EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight);
       return;
     }
 
     // Check that the configuration was parsed and stored correctly.
-    ASSERT_EQ(lower_delayable_count_enabled ? 2u : 1u,
+    ASSERT_EQ(lower_delayable_count_enabled ? 3u : 2u,
               params_network_quality_container.size());
 
     EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
               params_network_quality_container[0].effective_connection_type);
-    EXPECT_EQ(non_delayable_weight > 0.0 ? 10u : 2u,
+    EXPECT_EQ(non_delayable_weight > 0.0 ? 8u : 2u,
               params_network_quality_container[0].max_delayable_requests);
     EXPECT_EQ(non_delayable_weight > 0.0 ? non_delayable_weight : 0.0,
               params_network_quality_container[0].non_delayable_weight);
 
+    EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+              params_network_quality_container[1].effective_connection_type);
+
     if (lower_delayable_count_enabled) {
       EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G,
-                params_network_quality_container[1].effective_connection_type);
-      EXPECT_EQ(4u, params_network_quality_container[1].max_delayable_requests);
-      EXPECT_EQ(0.0, params_network_quality_container[1].non_delayable_weight);
+                params_network_quality_container[2].effective_connection_type);
+      EXPECT_EQ(4u, params_network_quality_container[2].max_delayable_requests);
+      EXPECT_EQ(0.0, params_network_quality_container[2].non_delayable_weight);
     }
   }
 
@@ -450,23 +462,38 @@
             ResourceScheduler::GetParamsForNetworkQualityContainerForTests();
 
     // Check that the configuration was parsed and stored correctly.
-    ASSERT_EQ(params_network_quality_container.size(), num_ranges);
-    for (size_t index = 1; index <= num_ranges; index++) {
+    ASSERT_EQ(std::max(static_cast<size_t>(2u), num_ranges),
+              params_network_quality_container.size());
+    for (size_t index = 1; index <= params_network_quality_container.size();
+         index++) {
       EXPECT_EQ(1 + index,
                 static_cast<size_t>(params_network_quality_container[index - 1]
                                         .effective_connection_type));
-      EXPECT_EQ(
-          index * 10u,
-          params_network_quality_container[index - 1].max_delayable_requests);
-      EXPECT_EQ(
-          0, params_network_quality_container[index - 1].non_delayable_weight);
+      if (params_network_quality_container[index - 1]
+                  .effective_connection_type <=
+              net::EFFECTIVE_CONNECTION_TYPE_2G &&
+          num_ranges < index) {
+        EXPECT_EQ(
+            8u,
+            params_network_quality_container[index - 1].max_delayable_requests);
+        EXPECT_EQ(
+            3,
+            params_network_quality_container[index - 1].non_delayable_weight);
+      } else {
+        EXPECT_EQ(
+            index * 10u,
+            params_network_quality_container[index - 1].max_delayable_requests);
+        EXPECT_EQ(
+            0,
+            params_network_quality_container[index - 1].non_delayable_weight);
+      }
     }
   }
 
   void NonDelayableThrottlesDelayableHelper(double non_delayable_weight) {
     base::test::ScopedFeatureList scoped_feature_list;
-    // Should be in sync with .cc.
-    const int kDefaultMaxNumDelayableRequestsPerClient = 10;
+    // Should be in sync with .cc for ECT SLOW_2G,
+    const int kDefaultMaxNumDelayableRequestsPerClient = 8;
     // Initialize the experiment.
     InitializeThrottleDelayableExperiment(&scoped_feature_list, false,
                                           non_delayable_weight);
@@ -1598,7 +1625,7 @@
   EXPECT_TRUE(high->started());
 
   // Should be based on the value set by
-  // |InitializeMaxDelayableRequestsExperiment| for the given range.
+  // |InitializeThrottleDelayableExperiment| for the given range.
   const int kOverriddenNumRequests = 2;
 
   std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
@@ -1791,11 +1818,16 @@
   // Only the first configuration parameter must be read because a match was not
   // found for index 2. The configuration parameters with index 3 and 4 must be
   // ignored, even though they are valid configuration parameters.
-  EXPECT_EQ(1u, params_network_quality_container.size());
+  EXPECT_EQ(2u, params_network_quality_container.size());
   EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
             params_network_quality_container[0].effective_connection_type);
   EXPECT_EQ(10u, params_network_quality_container[0].max_delayable_requests);
   EXPECT_EQ(0.0, params_network_quality_container[0].non_delayable_weight);
+
+  EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+            params_network_quality_container[1].effective_connection_type);
+  EXPECT_EQ(8u, params_network_quality_container[1].max_delayable_requests);
+  EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight);
 }
 
 // Test that the default limit is used for delayable requests when the
@@ -1841,7 +1873,7 @@
   base::test::ScopedFeatureList scoped_feature_list;
   const double kNonDelayableWeight = 2.0;
   const int kDefaultMaxNumDelayableRequestsPerClient =
-      10;  // Should be in sync with cc.
+      8;  // Should be in sync with cc.
   // Initialize the experiment with |kNonDelayableWeight| as the weight of
   // non-delayable requests.
   InitializeThrottleDelayableExperiment(&scoped_feature_list, false,
@@ -1879,12 +1911,6 @@
   }
 }
 
-// Test that the default limit is used for delayable requests in the presence of
-// non-delayable requests when the non-delayable request weight is zero.
-TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight0) {
-  NonDelayableThrottlesDelayableHelper(0.0);
-}
-
 // Test that each non-delayable request in-flight results in the reduction of
 // one in the limit of delayable requests in-flight when the non-delayable
 // request weight is 1.
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 08242a6..c88a5d7a6 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef SkUserConfig_DEFINED
-#define SkUserConfig_DEFINED
+#ifndef SKIA_CONFIG_SKUSERCONFIG_H_
+#define SKIA_CONFIG_SKUSERCONFIG_H_
 
 /*  SkTypes.h, the root of the public header files, does the following trick:
 
@@ -213,10 +213,6 @@
 #define SK_LEGACY_GPU_PIXEL_OPS
 #endif
 
-#ifndef SK_SUPPORT_LEGACY_BLURMASKFILTER
-#define SK_SUPPORT_LEGACY_BLURMASKFILTER
-#endif
-
 #ifndef SK_SUPPORT_LEGACY_YUV_COLORSPACE
 #define SK_SUPPORT_LEGACY_YUV_COLORSPACE
 #endif
diff --git a/sql/test/run_all_unittests.cc b/sql/test/run_all_unittests.cc
index 85ceac0..bdbe97b 100644
--- a/sql/test/run_all_unittests.cc
+++ b/sql/test/run_all_unittests.cc
@@ -10,7 +10,6 @@
   sql::SQLTestSuite test_suite(argc, argv);
 
   return base::LaunchUnitTests(
-      argc,
-      argv,
-      base::Bind(&sql::SQLTestSuite::Run, base::Unretained(&test_suite)));
+      argc, argv,
+      base::BindOnce(&sql::SQLTestSuite::Run, base::Unretained(&test_suite)));
 }
diff --git a/testing/buildbot/filters/viz.browser_tests.filter b/testing/buildbot/filters/viz.browser_tests.filter
index 8ed9070e..c74a371 100644
--- a/testing/buildbot/filters/viz.browser_tests.filter
+++ b/testing/buildbot/filters/viz.browser_tests.filter
@@ -101,3 +101,10 @@
 # Unknown Flakes
 # Flaky timeouts. http://crbug.com/807773
 -PDFExtensionClipboardTest.*
+
+# Windows timeouts. https://crbug.com/821029
+-ManifestVerifierBrowserTest.*
+-PrefHashBrowserTest*
+-UserInitiatedRunsDisabled*
+-UserInitiatedRunsEnabled*
+-WithVaryingSeeds/ChromeCleanerPromptUserTest.*
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 5932335b..1776d9f8 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -527,7 +527,7 @@
     "type": "windowed_test_launcher",
   },
   "filesystem_service_unittests": {
-    "label": "//components/filesystem:filesystem_service_unittests",
+    "label": "//components/services/filesystem:filesystem_service_unittests",
     "type": "console_test_launcher",
   },
   "gcm_unit_tests": {
@@ -739,7 +739,7 @@
     "type": "console_test_launcher",
   },
   "leveldb_service_unittests": {
-    "label": "//components/leveldb:leveldb_service_unittests",
+    "label": "//components/services/leveldb:leveldb_service_unittests",
     "type": "console_test_launcher",
   },
   "libjingle_xmpp_unittests": {
diff --git a/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc b/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc
index ca42f67..59aff298 100644
--- a/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc
@@ -12,26 +12,30 @@
 
 // Entry point for LibFuzzer.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::string input(reinterpret_cast<const char*>(data), size);
-  int out_int;
-  base::StringToInt(input, &out_int);
-  unsigned out_uint;
-  base::StringToUint(input, &out_uint);
-  int64_t out_int64;
-  base::StringToInt64(input, &out_int64);
-  uint64_t out_uint64;
-  base::StringToUint64(input, &out_uint64);
-  size_t out_size;
-  base::StringToSizeT(input, &out_size);
-  double out_double;
-  base::StringToDouble(input, &out_double);
-  base::HexStringToInt(input, &out_int);
-  base::HexStringToUInt(input, &out_uint);
-  base::HexStringToInt64(input, &out_int64);
-  base::HexStringToUInt64(input, &out_uint64);
+  base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
+                                       size);
+  std::string string_input(reinterpret_cast<const char*>(data), size);
 
+  int out_int;
+  base::StringToInt(string_piece_input, &out_int);
+  unsigned out_uint;
+  base::StringToUint(string_piece_input, &out_uint);
+  int64_t out_int64;
+  base::StringToInt64(string_piece_input, &out_int64);
+  uint64_t out_uint64;
+  base::StringToUint64(string_piece_input, &out_uint64);
+  size_t out_size;
+  base::StringToSizeT(string_piece_input, &out_size);
+
+  double out_double;
+  base::StringToDouble(string_input, &out_double);
+
+  base::HexStringToInt(string_piece_input, &out_int);
+  base::HexStringToUInt(string_piece_input, &out_uint);
+  base::HexStringToInt64(string_piece_input, &out_int64);
+  base::HexStringToUInt64(string_piece_input, &out_uint64);
   std::vector<uint8_t> out_bytes;
-  base::HexStringToBytes(input, &out_bytes);
+  base::HexStringToBytes(string_piece_input, &out_bytes);
 
   base::HexEncode(data, size);
   return 0;
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 877dd32..343cc2c 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3693,15 +3693,9 @@
                 {
                     "name": "Enabled",
                     "params": {
-                        "EffectiveConnectionType1": "Slow-2G",
-                        "EffectiveConnectionType2": "2G",
-                        "EffectiveConnectionType3": "3G",
-                        "MaxDelayableRequests1": "8",
-                        "MaxDelayableRequests2": "8",
-                        "MaxDelayableRequests3": "14",
-                        "NonDelayableWeight1": "2.0",
-                        "NonDelayableWeight2": "2.0",
-                        "NonDelayableWeight3": "2.0"
+                        "EffectiveConnectionType1": "3G",
+                        "MaxDelayableRequests1": "14",
+                        "NonDelayableWeight1": "2.0"
                     },
                     "enable_features": [
                         "ThrottleDelayable"
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 42f3000..227f8724 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -97,7 +97,7 @@
 crbug.com/591099 animations/animation-ready-reject-script-forbidden.html [ Timeout ]
 crbug.com/591099 animations/cross-fade-list-style-image.html [ Failure ]
 crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Timeout ]
-crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Pass Timeout ]
+crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/svg-stroke-dasharray-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Pass Timeout ]
 crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Pass ]
@@ -106,14 +106,12 @@
 crbug.com/714962 compositing/background-color/view-blending-base-background.html [ Failure ]
 crbug.com/591099 compositing/draws-content/canvas-background-layer.html [ Failure ]
 crbug.com/591099 compositing/draws-content/webgl-background-layer.html [ Failure ]
-crbug.com/591099 compositing/generated-content.html [ Failure Pass ]
 crbug.com/591099 compositing/geometry/bounds-ignores-hidden-dynamic.html [ Failure ]
 crbug.com/591099 compositing/geometry/bounds-ignores-hidden.html [ Failure ]
 crbug.com/591099 compositing/geometry/clipping-foreground.html [ Failure ]
 crbug.com/591099 compositing/geometry/composited-in-columns.html [ Failure ]
 crbug.com/591099 compositing/geometry/foreground-layer.html [ Failure ]
 crbug.com/591099 compositing/geometry/repaint-foreground-layer.html [ Failure ]
-crbug.com/591099 compositing/geometry/transfrom-origin-on-zero-size-layer.html [ Failure Pass ]
 crbug.com/591099 compositing/geometry/video-opacity-overlay.html [ Failure ]
 crbug.com/714962 compositing/gestures/gesture-tapHighlight-2-overflow-div-scrolled-inner.html [ Failure ]
 crbug.com/714962 compositing/gestures/gesture-tapHighlight-simple-multi-line.html [ Pass ]
@@ -126,12 +124,9 @@
 crbug.com/591099 compositing/overflow/nested-border-radius-clipping.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ]
 crbug.com/714962 compositing/overflow/rtl-overflow.html [ Failure ]
-crbug.com/591099 compositing/overflow/scaled-mask.html [ Failure Pass ]
 crbug.com/591099 compositing/overflow/scrolling-content-clip-to-viewport.html [ Failure ]
 crbug.com/591099 compositing/overflow/universal-accelerated-overflow-scroll.html [ Timeout ]
 crbug.com/591099 compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure ]
-crbug.com/591099 compositing/reflections/compositing-change-inside-reflection.html [ Failure Pass ]
-crbug.com/591099 compositing/reflections/transform-inside-reflection.html [ Failure Pass ]
 crbug.com/591099 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ]
 crbug.com/591099 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
 crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
@@ -199,7 +194,6 @@
 crbug.com/591099 editing/caret/caret-color-014.html [ Failure ]
 crbug.com/591099 editing/caret/caret-color-015.html [ Failure ]
 crbug.com/591099 editing/deleting/5272440.html [ Failure ]
-crbug.com/591099 editing/deleting/5369009.html [ Failure Pass ]
 crbug.com/591099 editing/deleting/delete-at-paragraph-boundaries-011.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-different-styles.html [ Failure ]
 crbug.com/591099 editing/deleting/merge-endOfParagraph.html [ Failure ]
@@ -217,10 +211,8 @@
 crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs-in-pre.html [ Failure ]
 crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs.html [ Failure ]
 crbug.com/591099 editing/execCommand/insertImage.html [ Failure ]
-crbug.com/591099 editing/execCommand/query-command-state.html [ Pass Timeout ]
 crbug.com/591099 editing/execCommand/query-format-block.html [ Timeout ]
 crbug.com/591099 editing/execCommand/remove-list-from-range-selection.html [ Failure ]
-crbug.com/591099 editing/input/linux_rtl_composition_underline.html [ Failure Pass ]
 crbug.com/591099 editing/inserting/4875189-1.html [ Failure ]
 crbug.com/591099 editing/inserting/4959067.html [ Failure ]
 crbug.com/591099 editing/inserting/editable-inline-element.html [ Failure ]
@@ -235,7 +227,6 @@
 crbug.com/591099 editing/inserting/paragraph-separator-in-table-1.html [ Failure ]
 crbug.com/591099 editing/inserting/paragraph-separator-in-table-2.html [ Failure ]
 crbug.com/591099 editing/pasteboard/4631972.html [ Failure ]
-crbug.com/591099 editing/pasteboard/5071074.html [ Failure Pass ]
 crbug.com/591099 editing/pasteboard/bad-placeholder.html [ Failure ]
 crbug.com/714962 editing/pasteboard/copy-element-with-conflicting-background-color-from-rule.html [ Failure ]
 crbug.com/714962 editing/pasteboard/copy-paste-pre-line-content.html [ Failure ]
@@ -283,7 +274,7 @@
 crbug.com/591099 editing/selection/extend-selection-bidi.html [ Failure ]
 crbug.com/591099 editing/selection/extend-selection-character.html [ Timeout ]
 crbug.com/591099 editing/selection/extend-selection-home-end.html [ Timeout ]
-crbug.com/591099 editing/selection/extend-selection-word.html [ Timeout ]
+crbug.com/591099 editing/selection/extend-selection-word.html [ Pass Timeout ]
 crbug.com/591099 editing/selection/focus-body.html [ Failure ]
 crbug.com/591099 editing/selection/home-end.html [ Timeout ]
 crbug.com/591099 editing/selection/line-wrap-2.html [ Failure ]
@@ -360,6 +351,7 @@
 crbug.com/591099 external/wpt/compat/webkit-text-fill-color-property-005.html [ Pass ]
 crbug.com/591099 external/wpt/credential-management/federatedcredential-framed-get.sub.https.html [ Pass ]
 crbug.com/591099 external/wpt/credential-management/passwordcredential-framed-get.sub.https.html [ Pass ]
+crbug.com/591099 external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht [ Pass ]
 crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001e.xht [ Pass ]
@@ -373,7 +365,6 @@
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/positioning-float-001.xht [ Pass ]
-crbug.com/591099 external/wpt/css/CSS2/text/text-decoration-applies-to-015.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ]
@@ -777,71 +768,122 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-018.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-020.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-030.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-005.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-017.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-029.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-041.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-053.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-065.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-077.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-089.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-095.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-105.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-109.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-121.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-125.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-137.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-141.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-153.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-157.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-169.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-173.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-185.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-189.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-201.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-205.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-217.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-221.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-225.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-229.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-002.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-004.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-006.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-008.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-010.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-012.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-014.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-016.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-018.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-020.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-024.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-026.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-028.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-030.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-032.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-034.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-036.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-038.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-040.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-042.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-044.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-048.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-050.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-052.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-054.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-056.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-060.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-064.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-066.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-072.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-074.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-076.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-078.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-080.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-084.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-086.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-088.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-090.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-092.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-096.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-102.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-104.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-106.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-108.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-110.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-112.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-114.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-116.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-118.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-122.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-124.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-126.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-128.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-130.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-132.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-136.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-138.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-140.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-142.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-144.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-146.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-148.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-150.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-154.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-156.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-158.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-160.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-162.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-164.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-170.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-172.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-176.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-178.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-186.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-188.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-192.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-194.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-198.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-202.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-204.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-206.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-208.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-210.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-212.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-214.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-218.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-220.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-222.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-224.xht [ Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-226.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-228.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/available-size-001.html [ Failure ]
@@ -1017,7 +1059,7 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/dir-style-03a.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-15.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-01.html [ Failure Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure Pass ]
+crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001.html [ Failure ]
 crbug.com/591099 external/wpt/dom/interfaces.html [ Timeout ]
 crbug.com/591099 external/wpt/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html [ Pass ]
@@ -1161,7 +1203,7 @@
 crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ]
 crbug.com/591099 external/wpt/feature-policy/payment-allowed-by-feature-policy.https.sub.html [ Pass ]
 crbug.com/591099 external/wpt/feature-policy/payment-disabled-by-feature-policy.https.sub.html [ Pass ]
-crbug.com/591099 external/wpt/fetch/api/request/request-cache-default-conditional.html [ Timeout ]
+crbug.com/591099 external/wpt/fetch/api/request/request-cache-default-conditional.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ]
 crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ]
@@ -1227,7 +1269,7 @@
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Timeout ]
-crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Timeout ]
+crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch-manual.html [ Pass ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch-manual.html [ Failure ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Timeout ]
@@ -1368,17 +1410,14 @@
 crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ]
 crbug.com/591099 fast/backgrounds/background-inherit-color-bug.html [ Failure ]
 crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ]
-crbug.com/591099 fast/backgrounds/background-origin-root-element.html [ Failure Pass ]
 crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Failure ]
 crbug.com/591099 fast/backgrounds/border-radius-split-background.html [ Failure ]
-crbug.com/591099 fast/backgrounds/opacity-on-document-element.html [ Failure Pass ]
 crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ]
 crbug.com/591099 fast/backgrounds/repeat/noRepeatCorrectClip.html [ Failure ]
 crbug.com/591099 fast/backgrounds/selection-background-color-of-image-list-style.html [ Failure ]
 crbug.com/591099 fast/backgrounds/selection-background-color-of-list-style.html [ Failure ]
 crbug.com/591099 fast/backgrounds/size/backgroundSize16.html [ Failure ]
 crbug.com/591099 fast/backgrounds/size/contain-and-cover.html [ Failure ]
-crbug.com/591099 fast/backgrounds/size/zero.html [ Failure Pass ]
 crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ]
 crbug.com/591099 fast/block/block-add-child-crash.html [ Crash ]
 crbug.com/591099 fast/block/block-width-recalc-with-relative-height.html [ Failure ]
@@ -1424,7 +1463,6 @@
 crbug.com/591099 fast/borders/border-antialiasing.html [ Failure ]
 crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
 crbug.com/714962 fast/borders/border-image-outset-split-inline.html [ Failure ]
-crbug.com/714962 fast/borders/border-image-scaled.html [ Failure Pass ]
 crbug.com/714962 fast/borders/border-inner-bleed.html [ Failure ]
 crbug.com/714962 fast/borders/border-radius-inline-flow.html [ Failure ]
 crbug.com/591099 fast/borders/border-radius-mask-canvas-all.html [ Failure ]
@@ -1454,7 +1492,6 @@
 crbug.com/714962 fast/borders/borderRadiusSolid03.html [ Failure ]
 crbug.com/714962 fast/borders/borderRadiusSolid04.html [ Failure ]
 crbug.com/714962 fast/borders/dashed-1px-with-border-radius.html [ Failure ]
-crbug.com/714962 fast/borders/different-color-borders.html [ Failure Pass ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset.html [ Failure ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image.html [ Failure ]
@@ -1470,22 +1507,13 @@
 crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ]
 crbug.com/591099 fast/box-shadow/inset.html [ Failure ]
 crbug.com/591099 fast/box-sizing/replaced.html [ Failure ]
-crbug.com/714962 fast/canvas/canvas-textMetrics-width.html [ Failure Pass ]
-crbug.com/714962 fast/canvas/image-object-in-canvas.html [ Failure Pass ]
-crbug.com/591099 fast/canvas/patternfill-repeat.html [ Failure Pass ]
-crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Failure Pass ]
 crbug.com/591099 fast/clip/overflow-border-radius-combinations.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-composited.html [ Failure ]
-crbug.com/591099 fast/clip/overflow-border-radius-fixed-position.html [ Failure Pass ]
 crbug.com/591099 fast/clip/overflow-border-radius-transformed.html [ Failure ]
-crbug.com/591099 fast/css-generated-content/001.html [ Failure Pass ]
-crbug.com/591099 fast/css-generated-content/007.html [ Failure Pass ]
 crbug.com/591099 fast/css-generated-content/009.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/012.html [ Failure ]
-crbug.com/591099 fast/css-generated-content/013.html [ Failure Pass ]
 crbug.com/591099 fast/css-generated-content/015.html [ Failure ]
-crbug.com/591099 fast/css-generated-content/after-duplicated-after-split.html [ Failure Pass ]
 crbug.com/805301 fast/css-generated-content/crash-selection-editing-removes-pseudo.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/empty-first-letter-with-columns-crash.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ]
@@ -1493,6 +1521,7 @@
 crbug.com/714962 fast/css-generated-content/hover-inline.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-before-after-child-add.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-cell-before-after-child-add.html [ Failure ]
+crbug.com/591099 fast/css-generated-content/table-parts-before-and-after.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/table-row-before-after-child-add.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-row-group-to-inline.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/table-row-group-with-before.html [ Failure ]
@@ -1588,7 +1617,7 @@
 crbug.com/591099 fast/css-grid-layout/minmax-min-content-column-resolution-rows.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-columns.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-rows.html [ Failure ]
-crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Timeout ]
+crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Pass Timeout ]
 crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-dynamic-get-set.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid.html [ Failure ]
@@ -1683,13 +1712,10 @@
 crbug.com/591099 fast/css/word-space-extra.html [ Failure ]
 crbug.com/714962 fast/css3-text/css3-text-decoration/repaint/repaint-text-decoration-style.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-decoration-skip-ink.html [ Failure ]
-crbug.com/591099 fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow.html [ Failure Pass ]
-crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-all.html [ Failure Pass ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-auto.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html [ Failure ]
 crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic.html [ Failure ]
 crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-subscript.html [ Failure ]
-crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under-out-of-flow.html [ Failure Pass ]
 crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under-vertical.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-indent/negative-text-indent-leading-out-of-flow-text-align-left-and-right.html [ Failure ]
@@ -1699,9 +1725,6 @@
 crbug.com/591099 fast/css3-text/css3-text-justify/text-justify-distribute.html [ Failure ]
 crbug.com/591099 fast/deprecated-flexbox/004.html [ Failure ]
 crbug.com/591099 fast/deprecated-flexbox/009-horizontal.html [ Failure ]
-crbug.com/714962 fast/deprecated-flexbox/009.html [ Failure Pass ]
-crbug.com/714962 fast/deprecated-flexbox/023.html [ Failure Pass ]
-crbug.com/714962 fast/deprecated-flexbox/024.html [ Failure Pass ]
 crbug.com/591099 fast/deprecated-flexbox/flexing-overflow-scroll-item.html [ Failure ]
 crbug.com/591099 fast/deprecated-flexbox/relpos-flex-item-with-percent-height-abspos-child.html [ Failure ]
 crbug.com/591099 fast/deprecated-flexbox/relpos-flex-item-with-percent-height-abspos-descendant.html [ Failure ]
@@ -1715,8 +1738,6 @@
 crbug.com/714962 fast/dom/Element/getClientRects.html [ Failure ]
 crbug.com/591099 fast/dom/HTMLMeterElement/meter-boundary-values.html [ Failure ]
 crbug.com/591099 fast/dom/HTMLMeterElement/meter-optimums.html [ Failure ]
-crbug.com/591099 fast/dom/HTMLMeterElement/meter-styles.html [ Failure Pass ]
-crbug.com/591099 fast/dom/HTMLObjectElement/vspace-hspace-as-number.html [ Failure Pass ]
 crbug.com/591099 fast/dom/HTMLProgressElement/progress-bar-value-pseudo-element.html [ Failure ]
 crbug.com/714962 fast/dom/Range/collapsed-range-bounding-client-rect.html [ Failure ]
 crbug.com/714962 fast/dom/Range/get-bounding-client-rect-empty-and-non-empty.html [ Timeout ]
@@ -1752,8 +1773,6 @@
 crbug.com/591099 fast/dom/wrapper-classes.html [ Timeout ]
 crbug.com/591099 fast/dynamic/continuation-detach-crash.html [ Crash ]
 crbug.com/591099 fast/dynamic/first-letter-after-list-marker.html [ Failure ]
-crbug.com/591099 fast/dynamic/layer-hit-test-crash.html [ Failure Pass ]
-crbug.com/591099 fast/dynamic/outerHTML-img.html [ Failure Pass ]
 crbug.com/591099 fast/dynamic/selection-highlight-adjust.html [ Failure ]
 crbug.com/591099 fast/dynamic/static-to-relative-with-absolute-child.html [ Crash ]
 crbug.com/591099 fast/dynamic/text-combine.html [ Failure ]
@@ -1776,7 +1795,7 @@
 crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture.html [ Timeout ]
 crbug.com/591099 fast/events/pointerevents/mouse-pointer-event-properties.html [ Timeout ]
 crbug.com/591099 fast/events/pointerevents/mouse-pointer-preventdefault.html [ Timeout ]
-crbug.com/591099 fast/events/pointerevents/multi-pointer-preventdefault.html [ Timeout ]
+crbug.com/591099 fast/events/pointerevents/multi-pointer-preventdefault.html [ Pass Timeout ]
 crbug.com/591099 fast/events/pointerevents/touch-capture-in-iframe.html [ Timeout ]
 crbug.com/591099 fast/events/pointerevents/touch-capture.html [ Timeout ]
 crbug.com/714962 fast/events/pointerevents/touch-pointer-events.html [ Pass ]
@@ -1836,10 +1855,8 @@
 crbug.com/591099 fast/forms/textarea/textarea-resize-orthogonal-containing-block.html [ Pass ]
 crbug.com/591099 fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html [ Timeout ]
 crbug.com/591099 fast/frames/iframe-with-frameborder.html [ Failure ]
-crbug.com/591099 fast/gradients/generated-gradients.html [ Failure Pass ]
 crbug.com/591099 fast/gradients/list-item-gradient.html [ Failure ]
 crbug.com/591099 fast/gradients/radial-centered.html [ Failure ]
-crbug.com/591099 fast/gradients/simple-gradients.html [ Failure Pass ]
 crbug.com/591099 fast/gradients/unprefixed-list-item-gradient.html [ Failure ]
 crbug.com/591099 fast/hidpi/broken-image-icon-hidpi.html [ Failure ]
 crbug.com/591099 fast/hidpi/image-set-list-style-image.html [ Failure ]
@@ -1872,11 +1889,6 @@
 crbug.com/591099 fast/inline/outline-continuations.html [ Failure ]
 crbug.com/714962 fast/inline/outline-offset.html [ Failure ]
 crbug.com/591099 fast/inline/styledEmptyInlinesWithBRs.html [ Failure ]
-crbug.com/591099 fast/invalid/010.html [ Failure Pass ]
-crbug.com/591099 fast/invalid/missing-address-end-tag.html [ Failure Pass ]
-crbug.com/591099 fast/invalid/missing-dl-end-tag.html [ Failure Pass ]
-crbug.com/591099 fast/invalid/missing-dt-end-tag.html [ Failure Pass ]
-crbug.com/591099 fast/invalid/missing-font-end-tag.html [ Failure Pass ]
 crbug.com/591099 fast/js/dfg-arguments-alias-activation.html [ Timeout ]
 crbug.com/591099 fast/js/dfg-byte-array-put.html [ Timeout ]
 crbug.com/591099 fast/js/document-all-triggers-masquerades-watchpoint.html [ Timeout ]
@@ -1898,7 +1910,6 @@
 crbug.com/591099 fast/lists/calc-width-with-space.html [ Failure ]
 crbug.com/591099 fast/lists/drag-into-marker.html [ Failure ]
 crbug.com/591099 fast/lists/inline-before-content-after-list-marker.html [ Failure ]
-crbug.com/591099 fast/lists/li-with-overflow-hidden-change-list-style-position.html [ Failure Pass ]
 crbug.com/591099 fast/lists/list-color-change-no-layout.html [ Failure ]
 crbug.com/591099 fast/lists/list-inside-columns-crash.html [ Crash ]
 crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
@@ -2316,7 +2327,6 @@
 crbug.com/714962 fast/overflow/childFocusRingClip.html [ Failure ]
 crbug.com/591099 fast/overflow/height-during-simplified-layout.html [ Failure ]
 crbug.com/591099 fast/overflow/image-selection-highlight.html [ Failure ]
-crbug.com/591099 fast/overflow/infiniteRecursion.html [ Failure Pass ]
 crbug.com/714962 fast/overflow/line-clamp-hides-trailing-anchor.html [ Failure ]
 crbug.com/591099 fast/overflow/line-clamp.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-rtl-vertical.html [ Failure ]
@@ -2364,13 +2374,9 @@
 crbug.com/591099 fast/parser/001.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-html.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-xhtml.xhtml [ Failure ]
-crbug.com/591099 fast/parser/nofoo-tags-inside-paragraph.html [ Failure Pass ]
-crbug.com/591099 fast/reflections/opacity-reflection-transform.html [ Failure Pass ]
 crbug.com/591099 fast/replaced/absolute-position-percentage-height.html [ Failure ]
 crbug.com/591099 fast/replaced/border-radius-clip.html [ Failure ]
 crbug.com/591099 fast/replaced/computed-image-width-with-percent-height-and-fixed-ancestor-vertical-lr.html [ Failure ]
-crbug.com/591099 fast/replaced/max-width-percent.html [ Failure Pass ]
-crbug.com/591099 fast/replaced/percent-height-in-anonymous-block-in-table.html [ Failure Pass ]
 crbug.com/591099 fast/replaced/percent-height-in-anonymous-block.html [ Failure ]
 crbug.com/591099 fast/replaced/preferred-widths.html [ Failure ]
 crbug.com/591099 fast/replaced/replaced-element-with-percentage-height-anonymous-block-parent.html [ Failure ]
@@ -2427,9 +2433,6 @@
 crbug.com/714962 fast/scrolling/scrollbar-tickmarks-styled-after-onload.html [ Failure ]
 crbug.com/714962 fast/scrolling/scrollbar-tickmarks-styled.html [ Failure ]
 crbug.com/591099 fast/selectors/038.html [ Failure ]
-crbug.com/591099 fast/selectors/040.html [ Failure Pass ]
-crbug.com/591099 fast/selectors/041.html [ Failure Pass ]
-crbug.com/591099 fast/selectors/042.html [ Failure Pass ]
 crbug.com/591099 fast/selectors/166.html [ Failure ]
 crbug.com/591099 fast/selectors/167.html [ Failure ]
 crbug.com/591099 fast/selectors/167a.html [ Failure ]
@@ -2519,75 +2522,48 @@
 crbug.com/591099 fast/spatial-navigation/snav-use-visual-viewport.html [ Failure ]
 crbug.com/591099 fast/sub-pixel/computedstylemargin.html [ Failure ]
 crbug.com/591099 fast/sub-pixel/inline-block-with-padding.html [ Failure ]
-crbug.com/714962 fast/sub-pixel/size-of-span-with-different-positions.html [ Failure Pass ]
 crbug.com/591099 fast/sub-pixel/sub-pixel-border-2.html [ Failure ]
 crbug.com/591099 fast/table/018.html [ Failure ]
 crbug.com/591099 fast/table/032.html [ Failure ]
 crbug.com/714962 fast/table/035-vertical.html [ Failure ]
 crbug.com/714962 fast/table/040-vertical.html [ Failure ]
 crbug.com/714962 fast/table/040.html [ Failure ]
-crbug.com/714962 fast/table/041.html [ Failure Pass ]
 crbug.com/714962 fast/table/absolute-table-at-bottom.html [ Failure ]
 crbug.com/714962 fast/table/auto-with-percent-height-vertical.html [ Failure ]
-crbug.com/714962 fast/table/auto-with-percent-height.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_border-table-cell-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_border-table-cell.html [ Failure ]
-crbug.com/714962 fast/table/backgr_border-table-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_border-table-column-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_border-table-column-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_border-table-column-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_border-table-column.html [ Failure ]
-crbug.com/714962 fast/table/backgr_border-table-quirks-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_border-table-quirks.html [ Failure ]
-crbug.com/714962 fast/table/backgr_border-table-row-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_border-table-row-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_border-table-row-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_border-table-row.html [ Failure ]
 crbug.com/714962 fast/table/backgr_border-table.html [ Failure ]
-crbug.com/714962 fast/table/backgr_layers-hide-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_layers-hide.html [ Failure ]
 crbug.com/591099 fast/table/backgr_layers-opacity-collapsed-border.html [ Failure ]
 crbug.com/591099 fast/table/backgr_layers-opacity.html [ Failure ]
 crbug.com/591099 fast/table/backgr_layers-show-collapsed-border.html [ Failure ]
 crbug.com/591099 fast/table/backgr_layers-show.html [ Failure ]
-crbug.com/714962 fast/table/backgr_position-table-cell-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_position-table-cell.html [ Failure ]
-crbug.com/714962 fast/table/backgr_position-table-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_position-table-column-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_position-table-column-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_position-table-column-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_position-table-column.html [ Failure ]
-crbug.com/714962 fast/table/backgr_position-table-row-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_position-table-row-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_position-table-row-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_position-table-row.html [ Failure ]
 crbug.com/714962 fast/table/backgr_position-table.html [ Failure ]
-crbug.com/714962 fast/table/backgr_simple-table-cell-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_simple-table-cell.html [ Failure ]
-crbug.com/714962 fast/table/backgr_simple-table-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_simple-table-column-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_simple-table-column-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_simple-table-column-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_simple-table-column.html [ Failure ]
-crbug.com/714962 fast/table/backgr_simple-table-row-collapsed-border.html [ Failure Pass ]
-crbug.com/714962 fast/table/backgr_simple-table-row-group-collapsed-border.html [ Failure Pass ]
 crbug.com/714962 fast/table/backgr_simple-table-row-group.html [ Failure ]
 crbug.com/714962 fast/table/backgr_simple-table-row.html [ Failure ]
 crbug.com/714962 fast/table/backgr_simple-table.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/001-vertical.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/003-vertical.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/004-vertical.html [ Failure ]
-crbug.com/591099 fast/table/border-collapsing/004.html [ Failure Pass ]
 crbug.com/591099 fast/table/border-collapsing/border-collapsing-head-foot-vertical.html [ Failure ]
 crbug.com/714962 fast/table/border-collapsing/border-collapsing-head-foot.html [ Failure ]
 crbug.com/591099 fast/table/border-collapsing/composited-cell-collapsed-border.html [ Failure ]
-crbug.com/714962 fast/table/border-collapsing/rtl-border-collapsing-vertical.html [ Failure Pass ]
-crbug.com/714962 fast/table/border-collapsing/rtl-border-collapsing.html [ Failure Pass ]
 crbug.com/591099 fast/table/column-in-inline.html [ Failure ]
 crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ]
 crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ]
 crbug.com/591099 fast/table/fixed-table-layout/table-with-percent-width.html [ Failure ]
-crbug.com/591099 fast/table/form-with-table-style.html [ Failure Pass ]
 crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ]
 crbug.com/714962 fast/table/hittest-tablecell-bottom-edge.html [ Failure ]
 crbug.com/714962 fast/table/hittest-tablecell-right-edge.html [ Failure ]
@@ -2602,14 +2578,11 @@
 crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ]
 crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ]
 crbug.com/591099 fast/table/percent-widths-stretch-vertical.html [ Failure ]
-crbug.com/714962 fast/table/rtl-cell-display-none-assert.html [ Failure Pass ]
 crbug.com/714962 fast/table/split-table-section-before-anonymous-block-2.html [ Failure ]
 crbug.com/714962 fast/table/split-table-section-before-anonymous-block-3.html [ Failure ]
 crbug.com/714962 fast/table/split-table-section-before-anonymous-block-4.html [ Failure ]
 crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ]
-crbug.com/714962 fast/table/text-field-baseline.html [ Failure Pass ]
 crbug.com/591099 fast/table/unbreakable-images-quirk.html [ Failure ]
-crbug.com/591099 fast/table/unused-percent-heights.html [ Failure Pass ]
 crbug.com/591099 fast/table/vertical-align-baseline-readjust.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/cluster-inline-block-or-table.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/cluster-inline-grid-flex-box.html [ Failure ]
@@ -2642,7 +2615,6 @@
 crbug.com/591099 fast/text-autosizing/form-controls-autosizing-select-element.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/form-controls-autosizing-textfield-input-elements.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/form-controls-textfield-in-span.html [ Failure ]
-crbug.com/591099 fast/text-autosizing/hackernews-comments.html [ Failure Pass ]
 crbug.com/591099 fast/text-autosizing/header-li-links-autosizing.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/header-links-autosizing-different-fontsize.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/header-links-autosizing.html [ Failure ]
@@ -2673,7 +2645,6 @@
 crbug.com/591099 fast/text-autosizing/wide-child.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/wide-in-narrow-overflow-scroll.html [ Failure ]
 crbug.com/591099 fast/text/break-word-with-floats.html [ Failure ]
-crbug.com/591099 fast/text/chromium-linux-fontconfig-renderstyle.html [ Failure Pass ]
 crbug.com/591099 fast/text/complex-text-opacity.html [ Failure ]
 crbug.com/591099 fast/text/container-align-with-inlines.html [ Failure ]
 crbug.com/591099 fast/text/decorations-transformed.html [ Failure ]
@@ -2696,7 +2667,6 @@
 crbug.com/714962 fast/text/get-client-rects-grapheme.html [ Failure ]
 crbug.com/714962 fast/text/glyph-reordering.html [ Failure ]
 crbug.com/591099 fast/text/hide-atomic-inlines-after-ellipsis.html [ Failure ]
-crbug.com/714962 fast/text/international/bidi-layout-across-linebreak.html [ Failure Pass ]
 crbug.com/591099 fast/text/international/bidi-linebreak-002.html [ Failure ]
 crbug.com/591099 fast/text/international/bidi-linebreak-003.html [ Failure ]
 crbug.com/714962 fast/text/international/cjk-segmentation.html [ Failure ]
@@ -2795,12 +2765,9 @@
 crbug.com/591099 fast/writing-mode/text-combine-justify.html [ Failure ]
 crbug.com/591099 fast/writing-mode/text-combine-line-break.html [ Failure ]
 crbug.com/591099 fast/writing-mode/text-combine-various-fonts.html [ Failure ]
-crbug.com/714962 fast/writing-mode/text-orientation-basic.html [ Failure Pass ]
 crbug.com/591099 fast/writing-mode/vertical-baseline-alignment.html [ Failure ]
 crbug.com/714962 fast/writing-mode/vertical-font-fallback.html [ Failure ]
 crbug.com/591099 fast/writing-mode/vertical-lr-replaced-selection.html [ Failure ]
-crbug.com/591099 fast/xsl/xslt-entity.xml [ Failure Pass ]
-crbug.com/591099 fast/xsl/xslt-extra-content-at-end.xml [ Failure Pass ]
 crbug.com/591099 fonts/monospace.html [ Failure ]
 crbug.com/591099 fonts/sans-serif.html [ Failure ]
 crbug.com/591099 fonts/serif.html [ Failure ]
@@ -2897,7 +2864,6 @@
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
-crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
@@ -2920,7 +2886,6 @@
 crbug.com/591099 html/dialog/modal-dialog-in-table-column.html [ Failure ]
 crbug.com/591099 html/dialog/modal-dialog-scroll-height.html [ Failure ]
 crbug.com/591099 html/dialog/multiple-centered-dialogs.html [ Failure ]
-crbug.com/591099 html/dialog/top-layer-containing-block.html [ Crash Pass ]
 crbug.com/591099 html/marquee/marquee-scroll.html [ Failure ]
 crbug.com/591099 html/marquee/marquee-scrollamount.html [ Failure ]
 crbug.com/591099 http/tests/css/css-image-valued-shape.html [ Failure ]
@@ -2948,7 +2913,6 @@
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ]
 crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ]
-crbug.com/591099 http/tests/devtools/elements/styles-2/paste-property.js [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.js [ Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure ]
@@ -2981,9 +2945,7 @@
 crbug.com/591099 http/tests/local/fileapi/select-dragged-file-input.html [ Skip ]
 crbug.com/591099 http/tests/misc/acid2.html [ Failure ]
 crbug.com/591099 http/tests/misc/acid3.html [ Crash ]
-crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm [ Failure Pass ]
 crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation.xhtml [ Failure ]
-crbug.com/591099 http/tests/misc/slow-loading-mask.html [ Failure Pass ]
 crbug.com/591099 http/tests/origin_trials/sample-api-workers.html [ Pass ]
 crbug.com/591099 http/tests/permissions/test-api-surface.html [ Pass ]
 crbug.com/591099 http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Failure ]
@@ -3047,7 +3009,7 @@
 crbug.com/591099 inspector-protocol/css/css-set-style-text.js [ Timeout ]
 crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ]
 crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Timeout ]
-crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Pass Timeout ]
+crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Timeout ]
 crbug.com/714962 inspector-protocol/layers/paint-profiler.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.js [ Failure ]
 crbug.com/591099 inspector-protocol/layout-fonts/fallback-pua-last-resort.js [ Failure ]
@@ -3070,10 +3032,6 @@
 crbug.com/714962 intersection-observer/text-target.html [ Failure ]
 crbug.com/591099 media/audio-controls-rendering.html [ Failure ]
 crbug.com/591099 media/autoplay/document-user-activation.html [ Failure ]
-crbug.com/591099 media/controls/volumechange-muted-attribute.html [ Failure Pass ]
-crbug.com/591099 media/video-aspect-ratio.html [ Failure Pass ]
-crbug.com/591099 media/video-colorspace-yuv420.html [ Failure Pass ]
-crbug.com/591099 media/video-colorspace-yuv422.html [ Failure Pass ]
 crbug.com/591099 media/video-display-toggle.html [ Failure ]
 crbug.com/591099 media/video-persistence.html [ Crash ]
 crbug.com/591099 media/video-transformed.html [ Failure ]
@@ -3103,7 +3061,6 @@
 crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clipped-relative.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/control-clip.html [ Failure ]
-crbug.com/591099 paint/invalidation/clip/intermediate-layout-position-clip.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ]
 crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
@@ -3112,8 +3069,6 @@
 crbug.com/591099 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/iframe-clip-removed.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ]
-crbug.com/591099 paint/invalidation/compositing/layer-repaint-rects.html [ Failure Pass ]
-crbug.com/591099 paint/invalidation/compositing/layer-repaint.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ]
 crbug.com/714962 paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/should-invoke-deferred-compositing.html [ Failure ]
@@ -3315,7 +3270,6 @@
 crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/embedded-svg-size-changes-no-layout-triggers.html [ Failure ]
-crbug.com/714962 paint/invalidation/svg/hit-test-with-br.xhtml [ Failure Pass ]
 crbug.com/591099 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ]
 crbug.com/591099 paint/invalidation/svg/object-sizing-no-width-height-change-content-box-size.xhtml [ Failure ]
@@ -3356,6 +3310,7 @@
 crbug.com/591099 paint/invalidation/table/caret-contenteditable-content-after.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/collapsed-border-cell-resize.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/collapsed-border-change-rowspan.html [ Failure ]
+crbug.com/591099 paint/invalidation/table/collapsed-border-current-color.html [ Crash ]
 crbug.com/591099 paint/invalidation/table/composited-table-background-col-initial-empty.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/composited-table-background-col-span-initial-empty.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/composited-table-background-col-span.html [ Failure ]
@@ -3419,7 +3374,6 @@
 crbug.com/591099 paint/markers/first-letter.html [ Failure ]
 crbug.com/591099 paint/markers/inline-spelling-markers-hidpi-composited.html [ Failure ]
 crbug.com/591099 paint/markers/inline-spelling-markers-hidpi.html [ Failure ]
-crbug.com/591099 paint/markers/inline_spelling_markers.html [ Failure Pass ]
 crbug.com/591099 paint/markers/marker-early-break-bug.html [ Failure ]
 crbug.com/591099 paint/overflow/background-mask-should-be-recorded-full.html [ Failure ]
 crbug.com/591099 paint/overflow/composited-scroll-vertical-rl.html [ Failure ]
@@ -3519,11 +3473,8 @@
 crbug.com/714962 svg/as-background-image/svg-as-background-body.html [ Failure ]
 crbug.com/591099 svg/as-border-image/svg-as-border-image-2.html [ Failure ]
 crbug.com/591099 svg/as-border-image/svg-as-border-image.html [ Failure ]
-crbug.com/714962 svg/canvas/canvas-pattern-svg.html [ Failure Pass ]
-crbug.com/591099 svg/custom/clone-element-with-animated-svg-properties.html [ Failure Pass ]
 crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ]
 crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ]
-crbug.com/591099 svg/custom/inline-svg-in-xhtml.xml [ Failure Pass ]
 crbug.com/591099 svg/custom/inline-svg-use-available-width-in-stf.html [ Failure ]
 crbug.com/591099 svg/custom/invisible-text-after-scrolling.xhtml [ Failure ]
 crbug.com/591099 svg/custom/junk-data.svg [ Failure ]
@@ -3533,17 +3484,14 @@
 crbug.com/591099 svg/custom/object-sizing-no-width-height.xhtml [ Failure ]
 crbug.com/591099 svg/custom/object-sizing.xhtml [ Failure ]
 crbug.com/591099 svg/custom/path-bad-data.svg [ Failure ]
-crbug.com/591099 svg/custom/rootmost-svg-xy-attrs.xhtml [ Failure Pass ]
 crbug.com/591099 svg/custom/svg-fonts-in-html.html [ Failure ]
 crbug.com/591099 svg/custom/text-match-highlight.html [ Failure ]
 crbug.com/591099 svg/custom/transformed-text-pattern.html [ Failure ]
 crbug.com/591099 svg/custom/use-event-retargeting.html [ Failure ]
 crbug.com/591099 svg/custom/use-font-face-crash.svg [ Failure ]
-crbug.com/714962 svg/dom/SVGStringList-basics.xhtml [ Failure Pass ]
-crbug.com/591099 svg/dom/svgangle-units.html [ Pass Timeout ]
+crbug.com/591099 svg/dom/svgangle-units.html [ Timeout ]
 crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ]
 crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ]
-crbug.com/591099 svg/foreignObject/svg-document-in-html-document.svg [ Failure Pass ]
 crbug.com/591099 svg/hixie/error/012.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/013.xml [ Failure ]
 crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Timeout ]
@@ -3562,179 +3510,75 @@
 crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ]
 crbug.com/591099 svg/transforms/transformed-text-fill-pattern.html [ Failure ]
 crbug.com/591099 svg/wicd/test-scalable-background-image1.xhtml [ Failure ]
-crbug.com/591099 svg/zoom/page/zoom-hixie-mixed-009.xml [ Failure Pass ]
-crbug.com/591099 svg/zoom/page/zoom-hixie-rendering-model-004.xhtml [ Failure Pass ]
 crbug.com/591099 svg/zoom/page/zoom-replaced-intrinsic-ratio-001.htm [ Failure ]
-crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure Pass ]
-crbug.com/591099 svg/zoom/text/zoom-hixie-mixed-009.xml [ Failure Pass ]
 crbug.com/591099 tables/layering/paint-test-layering-1.html [ Failure ]
 crbug.com/591099 tables/layering/paint-test-layering-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug101674.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug106158-1.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug106158-2.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug109043.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug110566.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug113235-1.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug11384q.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug11384s.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug1188.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug11944.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug12008.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug126742.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug1271.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug1302.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug131020-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug131020.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug131020_iframe.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug13118.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug1318.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug13196.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug133948.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug137388-1.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug137388-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug137388-3.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug139524-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug1430.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug149275-1.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug149275-2.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug16252.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug17130-1.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug18359.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug18440.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug18664.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug18955.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug19599.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug20579.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug219693-2.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug2267.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug23235.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug2479-1.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug2479-3.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug2479-4.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug2509.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug26553.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug27038-1.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug27038-2.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug2757.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug2886-2.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug2947.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug2962.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug2973.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug2981-1.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug2981-2.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug2997.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug30692.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug3191.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug32205-3.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug3454.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug38916.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug3977.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug43039.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug4427.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug44523.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug4501.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug4576.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug46268-1.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug46268-2.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug46268-5.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug46268.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug46368-1.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug46368-2.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug46480-1.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug46480-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug46623-1.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug46623-2.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug46924.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug48028-1.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug4803.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug4849-2.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug48827.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug5188.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug53690-2.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug5538.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug55694.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug57828-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug57828.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug5798.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug58402-1.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug59354.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug6304.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug641-2.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug650.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug69382-2.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug7112-1.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug7112-2.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug727.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug7342.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug78162.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug80762-1.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug82946-1.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug82946-2.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug8381.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug88035-1.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug88035-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug88524.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug9123-1.html [ Failure ]
-crbug.com/714962 tables/mozilla/bugs/bug93363.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/bugs/bug96334.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug98196.html [ Failure ]
-crbug.com/591099 tables/mozilla/collapsing_borders/bug41262-3.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla/core/bloomberg.html [ Failure ]
 crbug.com/591099 tables/mozilla/core/table_heights.html [ Failure ]
-crbug.com/714962 tables/mozilla/marvin/col_span.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/colgroup_span.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/colgroup_width_pct.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/colgroup_width_px.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_cellpadding.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_cellpadding_pct.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_cellspacing.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_class.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_style.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_td_colspan.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_td_height.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_td_rowspan.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_td_width.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_th_colspan.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_th_height.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_th_rowspan.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/marvin/tables_th_width.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_width_percent.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tables_width_px.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/tbody_char.html [ Failure Pass ]
-crbug.com/591099 tables/mozilla/marvin/tfoot_char.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/thead_char.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_col_width_pct.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_col_width_px.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_col_width_rel.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_colgroup_width_pct.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_colgroup_width_rel.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_table.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/marvin/x_table_style.xml [ Failure Pass ]
-crbug.com/714962 tables/mozilla/other/cellspacing.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/other/test3.html [ Failure ]
 crbug.com/714962 tables/mozilla/other/test6.html [ Failure ]
 crbug.com/591099 tables/mozilla/other/wa_table_thtd_rowspan.html [ Failure ]
 crbug.com/591099 tables/mozilla_expected_failures/bugs/bug1010.html [ Failure ]
 crbug.com/714962 tables/mozilla_expected_failures/bugs/bug1055-2.html [ Failure ]
 crbug.com/714962 tables/mozilla_expected_failures/bugs/bug1128.html [ Failure ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug14007-1.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug21518.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug22122.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug2479-5.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug25707.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla_expected_failures/bugs/bug32205-4.html [ Failure ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug42043.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug4294.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug51000.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug56024.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla_expected_failures/bugs/bug7113.html [ Failure ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug72393.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/bugs/bug80762-2.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla_expected_failures/bugs/bug85016.html [ Failure ]
 crbug.com/714962 tables/mozilla_expected_failures/bugs/bug91057.html [ Failure ]
-crbug.com/714962 tables/mozilla_expected_failures/core/standards1.html [ Failure Pass ]
 crbug.com/591099 tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure ]
 crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption.html [ Failure ]
 crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_bottom.html [ Failure ]
@@ -3743,23 +3587,18 @@
 crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_left.html [ Failure ]
 crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_right.html [ Failure ]
 crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_top.html [ Failure ]
-crbug.com/714962 tables/mozilla_expected_failures/marvin/tables_cellspacing_pct.html [ Failure Pass ]
-crbug.com/714962 tables/mozilla_expected_failures/marvin/x_colgroup_width_px.xml [ Failure Pass ]
 crbug.com/714962 touchadjustment/context-menu-select-text.html [ Failure ]
 crbug.com/714962 touchadjustment/context-menu-text-subtargets.html [ Failure ]
 crbug.com/714962 touchadjustment/touch-links-longpress.html [ Failure ]
 crbug.com/591099 transforms/2d/compound-transforms-vs-containers.html [ Failure ]
 crbug.com/591099 transforms/2d/hindi-rotated.html [ Failure ]
 crbug.com/591099 transforms/2d/transform-2d.html [ Timeout ]
-crbug.com/591099 transforms/2d/transform-fixed-container.html [ Failure Pass ]
 crbug.com/591099 transforms/3d/general/perspective-non-layer.html [ Failure ]
 crbug.com/591099 transforms/3d/hit-testing/backface-hit-test.html [ Failure ]
 crbug.com/591099 transforms/3d/hit-testing/backface-no-transform-hit-test.html [ Failure ]
 crbug.com/714962 transforms/inline-in-transformed-multicol.html [ Failure ]
 crbug.com/714962 transforms/selection-bounds-in-transformed-view.html [ Failure ]
 crbug.com/591099 transforms/shadows.html [ Failure ]
-crbug.com/591099 transforms/transform-positioned-ancestor.html [ Failure Pass ]
-crbug.com/591099 transforms/transforms-with-zoom.html [ Failure Pass ]
 crbug.com/591099 virtual/android/ [ Skip ]
 crbug.com/591099 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html [ Pass ]
 crbug.com/591099 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass ]
@@ -3797,10 +3636,6 @@
 crbug.com/714962 virtual/gpu/fast/canvas/canvas-css-clip-path.html [ Failure ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality.html [ Pass ]
-crbug.com/714962 virtual/gpu/fast/canvas/canvas-textMetrics-width.html [ Failure Pass ]
-crbug.com/714962 virtual/gpu/fast/canvas/image-object-in-canvas.html [ Failure Pass ]
-crbug.com/591099 virtual/gpu/fast/canvas/patternfill-repeat.html [ Failure Pass ]
-crbug.com/714962 virtual/gpu/fast/canvas/setWidthResetAfterForcedRender.html [ Failure Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ]
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html [ Pass ]
 crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html [ Pass ]
@@ -3870,11 +3705,8 @@
 crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ]
 crbug.com/714962 virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-workers-view.js [ Failure ]
 crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ]
-crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass ]
 crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
-crbug.com/714962 virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ]
 crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
-crbug.com/714962 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ]
 crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
 crbug.com/591099 virtual/scroll_customization/ [ Skip ]
 crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-animation.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 2708dbb..7655a7b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -158,6 +158,7 @@
 crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ]
 crbug.com/711704 external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht [ Failure ]
 
+crbug.com/711709 external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html [ Failure ]
 crbug.com/711709 external/wpt/css/CSS2/floats-clear/floating-replaced-height-008.xht [ Skip ]
 crbug.com/711709 external/wpt/css/CSS2/floats-clear/floats-108.xht [ Skip ]
 crbug.com/711709 external/wpt/css/CSS2/floats-clear/floats-109.xht [ Skip ]
@@ -843,6 +844,8 @@
 
 crbug.com/813098 external/wpt/editing/run/removeformat.html [ Timeout Pass ]
 
+crbug.com/821455 [ Linux ] editing/pasteboard/drag-files-to-editable-element.html [ Failure Pass ]
+
 crbug.com/688613 external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
 crbug.com/688613 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
 
@@ -1304,19 +1307,16 @@
 crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-17.html [ Failure Pass ]
 crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-18.html [ Failure Pass ]
 crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-external-font-face-01.html [ Pass Failure ]
-crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-01.html [ Failure ]
-crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure ]
 
-crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001a.html [ Failure ]
-crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005a.html [ Failure Pass ]
-crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006.html [ Failure ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure Pass ]
-crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure Pass ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001a.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005a.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006.html [ Failure ]
+crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure ]
 
 crbug.com/752449 [ Mac10.12 Mac10.13 Retina ] external/wpt/css/css-fonts/matching/fixed-stretch-style-over-weight.html [ Failure ]
 crbug.com/752449 [ Mac10.12 Retina ] external/wpt/css/css-fonts/matching/stretch-distance-over-weight-distance.html [ Failure ]
@@ -1432,9 +1432,6 @@
 crbug.com/v8/7486 http/tests/devtools/startup/console/console-format-startup-bigint.js [ Skip ]
 crbug.com/v8/7486 http/tests/devtools/console/console-format-bigint.js [ Skip ]
 
-# Temporarily disable test until we land change to v8::ScriptCompiler::CompileFunctionInContext.
-crbug.com/v8/7172 inspector-protocol/debugger/step-into-inline-event-handler.js [ NeedsManualRebaseline ]
-
 crbug.com/564109 [ Win ]  http/tests/webfont/font-display-intervention.html [ Pass Failure Timeout ]
 
 crbug.com/399951 http/tests/mime/javascript-mimetype-usecounters.html [ Pass Failure ]
@@ -1671,6 +1668,7 @@
 crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html [ Skip ]
 crbug.com/626703 [ Mac10.11 ] external/wpt/payment-handler/can-make-payment-event-constructor.https.worker.html [ Timeout ]
 crbug.com/626703 [ Linux Win ] external/wpt/css/css-text/letter-spacing/letter-spacing-control-chars-001.html [ Failure ]
 crbug.com/626703 [ Linux Mac10.10 Mac10.12 Mac10.13 Retina Win ] external/wpt/payment-handler/can-make-payment-event-constructor.https.worker.html [ Timeout ]
@@ -1716,7 +1714,7 @@
 crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/white-space-collapsing-preserve-breaks-001.xht [ Failure ]
 crbug.com/626703 [ Linux Mac10.12 Retina Win ] external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-028.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-006.html [ Failure ]
 crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-028.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-004.xht [ Skip ]
@@ -1724,14 +1722,12 @@
 crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-justify-004.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-005.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-normal-km-000.html [ Failure ]
-crbug.com/626703 [ Linux Win ] external/wpt/css/css-text/text-transform/text-transform-upperlower-016.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-010.html [ Failure ]
 crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-end-016.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-fullwidth-001.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-my-000.html [ Failure ]
 crbug.com/626703 [ Win7 ] external/wpt/css/css-text/text-justify/text-justify-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-029.html [ Failure ]
 crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-start-004.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/hanging-punctuation/hanging-punctuation-allow-end-001.xht [ Skip ]
@@ -1943,7 +1939,6 @@
 crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-1.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-3.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-kerning-03.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-01.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-02.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-03.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-04.html [ Failure ]
@@ -3368,7 +3363,7 @@
 crbug.com/811977 virtual/new-remote-playback-pipeline/media/controls/picture-in-picture-interstitial.html [ Skip ]
 
 # Sheriff 2018-02-26
-crbug.com/816475 [ Win7 ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ]
+crbug.com/816475 [ Win7 Linux ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ]
 crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ]
 crbug.com/816766 [ Mac ] fast/dom/Window/window-focus-self.html [ Failure Pass ]
 crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html b/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html
index fb33992..a1dc7fc 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html
@@ -228,3 +228,30 @@
   });
 }, "AOM event bubbling respects aria-owns over DOM parent chain");
 </script>
+
+<p id="container7" aria-label="Container7"></p>
+
+<script>
+async_test(function(t) {
+  enableAccessibilityEventsPermission().then(function() {
+    var container7 = document.getElementById("container7");
+    var axContainer7 = accessibilityController.accessibleElementById(
+        "container7");
+
+    var virtualNode = new AccessibleNode();
+    virtualNode.role = "button";
+    virtualNode.label = "Button7";
+    container7.accessibleNode.appendChild(virtualNode);
+    var axVirtualNode = axContainer7.childAtIndex(0);
+
+    var success = false;
+    virtualNode.onaccessibleclick = function() {
+      success = true;
+    };
+    axVirtualNode.press();
+
+    assert_true(success);
+    t.done();
+  });
+}, "AccessibleNode.onaccessibleclick on virtual node");
+</script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html b/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html
index 4b8baa02..d6dca9ce 100644
--- a/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html
+++ b/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html
@@ -74,3 +74,26 @@
     assert_equals(axListItem2.role, "AXRole: AXListItem");
 }, "Create a virtual list using AccessibleNodes");
 </script>
+
+<script>
+test(function(t) {
+    var container = document.getElementById("container2");
+
+    var list1 = new AccessibleNode();
+    list1.role = "list";
+    container.accessibleNode.appendChild(list1);
+
+    var list2 = new AccessibleNode();
+    list2.role = "list";
+    container.accessibleNode.appendChild(list2);
+
+    var item = new AccessibleNode();
+    item.role = "listitem";
+    list1.appendChild(item);
+
+    // TODO: support reparenting and then fix this test.
+    assert_throws('NotSupportedError', function() {
+      list2.appendChild(item);
+    });
+}, "Reparenting is not supported yet");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 5badc09..3f612a36 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -4681,6 +4681,12 @@
      {}
     ]
    ],
+   "payment-request/payment-request-canmakepayment-method-manual.https.html": [
+    [
+     "/payment-request/payment-request-canmakepayment-method-manual.https.html",
+     {}
+    ]
+   ],
    "payment-request/payment-response/complete-method-manual.https.html": [
     [
      "/payment-request/payment-response/complete-method-manual.https.html",
@@ -98409,26 +98415,6 @@
      {}
     ]
    ],
-   "beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "beacon/headers/header-referrer-strict-origin.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "beacon/headers/header-referrer-unsafe-url.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "beacon/headers/header-referrer.js": [
     [
      {}
@@ -98654,6 +98640,21 @@
      {}
     ]
    ],
+   "client-hints/OWNERS": [
+    [
+     {}
+    ]
+   ],
+   "client-hints/accept_ch.https.html.headers": [
+    [
+     {}
+    ]
+   ],
+   "client-hints/echo_device_memory_header_received.py": [
+    [
+     {}
+    ]
+   ],
    "clipboard-apis/OWNERS": [
     [
      {}
@@ -174795,6 +174796,12 @@
      {}
     ]
    ],
+   "client-hints/accept_ch.https.html": [
+    [
+     "/client-hints/accept_ch.https.html",
+     {}
+    ]
+   ],
    "clipboard-apis/async-interfaces.https.html": [
     [
      "/clipboard-apis/async-interfaces.https.html",
@@ -183531,6 +183538,12 @@
      {}
     ]
    ],
+   "css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html": [
+    [
+     "/css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html",
+     {}
+    ]
+   ],
    "css/css-typed-om/the-stylepropertymap/properties/shape-outside.html": [
     [
      "/css/css-typed-om/the-stylepropertymap/properties/shape-outside.html",
@@ -215611,12 +215624,6 @@
      {}
     ]
    ],
-   "payment-request/payment-request-canmakepayment-method.https.html": [
-    [
-     "/payment-request/payment-request-canmakepayment-method.https.html",
-     {}
-    ]
-   ],
    "payment-request/payment-request-constructor-crash.https.html": [
     [
      "/payment-request/payment-request-constructor-crash.https.html",
@@ -250184,10 +250191,6 @@
    "aee7b4c817f064e871d10cc80da8d25759c16158",
    "testharness"
   ],
-  "beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt": [
-   "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3",
-   "support"
-  ],
   "beacon/headers/header-referrer-no-referrer-when-downgrade.https.html": [
    "273c7d0110d5efc9fac0029cd257256894d3eb4b",
    "testharness"
@@ -250208,26 +250211,14 @@
    "9701f2f0a83c6eeefe781d7de2c0cdbcff38b58e",
    "testharness"
   ],
-  "beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt": [
-   "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3",
-   "support"
-  ],
   "beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html": [
    "295ef746c475fca0ae8b492375a48948b4ea19c3",
    "testharness"
   ],
-  "beacon/headers/header-referrer-strict-origin.https-expected.txt": [
-   "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3",
-   "support"
-  ],
   "beacon/headers/header-referrer-strict-origin.https.html": [
    "295ef746c475fca0ae8b492375a48948b4ea19c3",
    "testharness"
   ],
-  "beacon/headers/header-referrer-unsafe-url.https-expected.txt": [
-   "cd3cfb43cf8a6c7e1fafaa4262f0fd7df7633872",
-   "support"
-  ],
   "beacon/headers/header-referrer-unsafe-url.https.html": [
    "a7b6e697be165124ed5d6846335c8d3a38ee98f5",
    "testharness"
@@ -251052,6 +251043,22 @@
    "10f5f9d409ef513edb129e0e8522aa5f74d51ce8",
    "support"
   ],
+  "client-hints/OWNERS": [
+   "56ef0ac9f9d3c2fcd69f16c409599402de8057f0",
+   "support"
+  ],
+  "client-hints/accept_ch.https.html": [
+   "b54ae9b17399e0fe4472fedbf1badd67d28e68f3",
+   "testharness"
+  ],
+  "client-hints/accept_ch.https.html.headers": [
+   "bf59baf9a030d117964df414efc11ddb07e7a7fa",
+   "support"
+  ],
+  "client-hints/echo_device_memory_header_received.py": [
+   "defa16c455bebc2589c058d0d888326d667e317a",
+   "support"
+  ],
   "clipboard-apis/OWNERS": [
    "29571a481e6d9fbbef55c7e0731280f08af5ac93",
    "support"
@@ -303356,6 +303363,10 @@
    "68a2611eaf9eecb7393c2b0db0f4378ebe285f22",
    "testharness"
   ],
+  "css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html": [
+   "d37d336e4695e5055706a7822572b81b943fdbd4",
+   "testharness"
+  ],
   "css/css-typed-om/the-stylepropertymap/properties/shape-outside-expected.txt": [
    "fda10e01b3af2298d545ebcfb5e3c77ed91c8932",
    "support"
@@ -324317,7 +324328,7 @@
    "testharness"
   ],
   "fetch/api/redirect/redirect-location.js": [
-   "3b48bf04659cc82462c3f33db47fd2f44f63c0c3",
+   "c8795b2a372e365e1b6e052d8a3309f3bfb2c143",
    "support"
   ],
   "fetch/api/redirect/redirect-method-worker.html": [
@@ -345901,7 +345912,7 @@
    "support"
   ],
   "interfaces/magnetometer.idl": [
-   "78fdc6ec345a5f05e86cb104cb025689638bbe17",
+   "ffac480912edba82886fef6d5368092d237a0c7f",
    "support"
   ],
   "interfaces/mediacapture-main.idl": [
@@ -345909,7 +345920,7 @@
    "support"
   ],
   "interfaces/orientation-sensor.idl": [
-   "d75a765c9456c21ed2733fa89a20f3e2d0eb2131",
+   "1f0698a8611726b1ba724a5d7a0961e836c7b07e",
    "support"
   ],
   "interfaces/payment-handler.idl": [
@@ -355440,14 +355451,14 @@
    "30c62af4a05a4d83cbbd1e82d0df62bae9a85e96",
    "testharness"
   ],
+  "payment-request/payment-request-canmakepayment-method-manual.https.html": [
+   "40e5bf0445eedb6bb78bd61fa4a468652462a14d",
+   "manual"
+  ],
   "payment-request/payment-request-canmakepayment-method.https-expected.txt": [
    "edf4b9aedbdc74041e2aa49d77eaa177954f0f80",
    "support"
   ],
-  "payment-request/payment-request-canmakepayment-method.https.html": [
-   "0d863558b996df81a36207201bbf8c649688845d",
-   "testharness"
-  ],
   "payment-request/payment-request-constructor-crash.https.html": [
    "383d1c3f9505ee63d504bee87e13efa90ba49f3d",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt
deleted file mode 100644
index 27ce7532..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Test referer header https://web-platform.test:8444/beacon/resources/
-FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt
deleted file mode 100644
index 27ce7532..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Test referer header https://web-platform.test:8444/beacon/resources/
-FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt
deleted file mode 100644
index 27ce7532..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Test referer header https://web-platform.test:8444/beacon/resources/
-FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt
deleted file mode 100644
index 6c07551..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html
new file mode 100644
index 0000000..f65f314
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Child of block with clear</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="position:relative; top:-20px;">
+  <div style="float:left; margin-top:20px; width:50px; height:50px; background:green;"></div>
+  <div style="padding-top:1px;">
+    <div style="margin-top:19px; width:100px; background:green;">
+      <div style="clear:left; margin-top:25px; width:100px; height:50px; background:green;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html
new file mode 100644
index 0000000..d7dc26f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Child of block with clear</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property">
+<link rel="match" href="../../reference/ref-filled-green-200px-square.html">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="container" style="overflow:hidden; width:200px; height:200px; background:red;">
+  <div style="float:left; width:10px; height:50px;"></div>
+  <div style="float:right; width:10px; height:100px;"></div>
+  <div style="clear:right;">
+    <div style="clear:left; height:200px; background:green;"></div>
+  </div>
+  <div style="height:10000px;"></div>
+</div>
+<script>
+  document.getElementById("container").scrollTop = 100;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html
new file mode 100644
index 0000000..29ecc78f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>Child of block with clear</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="position:relative; z-index:-1; top:-50px; width:100px; background:green;">
+  <div style="float:left; width:100px; height:50px; background:white;"></div>
+  <div style="clear:left; margin-top:25px;">
+    <div style="height:50px; margin-top:150px; background:white;"></div>
+  </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html
new file mode 100644
index 0000000..9b331d5e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>Child of block with clear</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property">
+<link rel="match" href="../../reference/ref-filled-green-200px-square.html">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:200px; height:200px; background:red;">
+  <div style="float:left; width:200px; height:100px; background:green;"></div>
+  <div style="clear:left; margin-top:100px;">
+    <div style="height:100px; margin-top:-1000px; background:green;"></div>
+  </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html
new file mode 100644
index 0000000..755cd78
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>Child of block with clear</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property">
+<link rel="match" href="../../reference/ref-filled-green-200px-square.html">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:200px; height:200px; background:red;">
+  <div style="float:left; width:200px; height:100px; background:green;"></div>
+  <div style="clear:left;">
+    <div style="height:100px; background:green;"></div>
+  </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html
new file mode 100644
index 0000000..defe06f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <!-- Feature-Policy: fullscreen *; -->
+  <script>
+  'use strict';
+  var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}';
+  var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
+  var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
+  var cross_origin_src = cross_origin + same_origin_src;
+  var policies = [
+    {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true},
+    {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false},
+    {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
+    {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}];
+  var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
+  var pipe_end = ';)';
+  var header_policies = ["*", "'self'", "'none'"];
+
+  // Test that frame.policy inherits from parent's header policy when allow
+  // attribute is not specified.
+  test(function() {
+    test_frame_policy('fullscreen', same_origin_src, true);
+  }, 'Test frame policy on same origin iframe inherit from header policy.');
+  test(function() {
+    test_frame_policy('fullscreen', cross_origin_src, true);
+  }, 'Test frame policy on cross origin iframe inherit from header policy.');
+
+  // Test frame policy with allow attribute set to be one of the policies above.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
+  }
+
+  // Test that the header policy of the iframe document does not change the
+  // frame policy.
+  for (var i = 0; i < policies.length; i++) {
+    for (var j = 0; j < header_policies.length; j++) {
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          same_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].sameOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          cross_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].crossOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+    }
+  }
+
+  // Test that the allow attribute overrides allowfullscreen.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+  }
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers
new file mode 100644
index 0000000..111121a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers
@@ -0,0 +1 @@
+Feature-Policy: fullscreen *;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html
new file mode 100644
index 0000000..d757d4c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <!-- Feature-Policy: fullscreen 'self'; -->
+  <script>
+  'use strict';
+  var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}';
+  var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
+  var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
+  var cross_origin_src = cross_origin + same_origin_src;
+  var policies = [
+    {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true},
+    {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false},
+    {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
+    {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}];
+  var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
+  var pipe_end = ';)';
+  var header_policies = ["*", "'self'", "'none'"];
+
+  // Test that frame.policy inherits from parent's header policy when allow
+  // attribute is not specified.
+  test(function() {
+    test_frame_policy('fullscreen', same_origin_src, true);
+  }, 'Test frame policy on same origin iframe inherit from header policy.');
+  test(function() {
+    test_frame_policy('fullscreen', cross_origin_src, false);
+  }, 'Test frame policy on cross origin iframe inherit from header policy.');
+
+  // Test frame policy with allow attribute set to be one of the policies above.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
+  }
+
+  // Test that the header policy of the iframe document does not change the
+  // frame policy.
+  for (var i = 0; i < policies.length; i++) {
+    for (var j = 0; j < header_policies.length; j++) {
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          same_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].sameOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          cross_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].crossOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+    }
+  }
+
+  // Test that the allow attribute overrides allowfullscreen.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+  }
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers
new file mode 100644
index 0000000..0cc259b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers
@@ -0,0 +1 @@
+Feature-Policy: fullscreen 'self';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html
new file mode 100644
index 0000000..f10c66f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <!-- Feature-Policy: fullscreen 'self' cross_origin https://www.example.com; -->
+  <script>
+  'use strict';
+  var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}';
+  var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
+  var cross_origin1 = 'https://{{domains[www1]}}:{{ports[https][0]}}';
+  var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
+  var cross_origin_src = cross_origin + same_origin_src;
+  var cross_origin_src1 = cross_origin1 + same_origin_src;
+  // Test feature policy with same_origin_src and cross_origin_src.
+  var policies = [
+    {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: true},
+    {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, crossOrigin1TestExpect: false},
+    {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, crossOrigin1TestExpect: false},
+    {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: false}];
+  var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
+  var pipe_end = ';)';
+  var header_policies = ["*", "'self'", "'none'"];
+
+  // Test that frame.policy inherits from parent's header policy when allow
+  // attribute is not specified.
+  test(function() {
+    test_frame_policy('fullscreen', same_origin_src, true);
+  }, 'Test frame policy on same origin iframe inherit from header policy.');
+  test(function() {
+    test_frame_policy('fullscreen', cross_origin_src, true);
+  }, 'Test frame policy on cross origin iframe inherit from header policy.');
+  test(function() {
+    test_frame_policy('fullscreen', cross_origin_src1, false);
+  }, 'Test frame policy on another cross origin iframe inherit from header policy.');
+
+  // Test frame policy with allow attribute set to be one of the policies above.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow + '".');
+  }
+
+  // Test that the header policy of the iframe document does not change the
+  // frame policy.
+  for (var i = 0; i < policies.length; i++) {
+    for (var j = 0; j < header_policies.length; j++) {
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          same_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].sameOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          cross_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].crossOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          cross_origin_src1 + pipe_front + header_policies[j] + pipe_end,
+          policies[i].crossOrigin1TestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+    }
+  }
+
+  // Test that the allow attribute overrides allowfullscreen.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+  }
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers
new file mode 100644
index 0000000..c2493a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers
@@ -0,0 +1 @@
+Feature-Policy: fullscreen 'self' https://{{domains[www]}}:{{ports[https][0]}} https://www.example.com;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html
new file mode 100644
index 0000000..e1178e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <!-- Feature-Policy: fullscreen 'none'; -->
+  <script>
+  'use strict';
+  var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}';
+  var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}';
+  var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html';
+  var cross_origin_src = cross_origin + same_origin_src;
+  var policies = [
+    {allow: "*", sameOriginTestExpect: false, crossOriginTestExpect: false},
+    {allow: "'self'", sameOriginTestExpect: false, crossOriginTestExpect: false},
+    {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false},
+    {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: false, crossOriginTestExpect: false}];
+  var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen ';
+  var pipe_end = ';)';
+  var header_policies = ["*", "'self'", "'none'"];
+
+  // Test that frame.policy inherits from parent's header policy when allow
+  // attribute is not specified.
+  test(function() {
+    test_frame_policy('fullscreen', same_origin_src, false);
+  }, 'Test frame policy on same origin iframe inherit from header policy.');
+  test(function() {
+    test_frame_policy('fullscreen', cross_origin_src, false);
+  }, 'Test frame policy on cross origin iframe inherit from header policy.');
+
+  // Test frame policy with allow attribute set to be one of the policies above.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';');
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".');
+  }
+
+  // Test that the header policy of the iframe document does not change the
+  // frame policy.
+  for (var i = 0; i < policies.length; i++) {
+    for (var j = 0; j < header_policies.length; j++) {
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          same_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].sameOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+      test(function() {
+        test_frame_policy(
+          'fullscreen',
+          cross_origin_src + pipe_front + header_policies[j] + pipe_end,
+          policies[i].crossOriginTestExpect,
+          'fullscreen ' + policies[i].allow + ';');
+      }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+         '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".');
+    }
+  }
+
+  // Test that the allow attribute overrides allowfullscreen.
+  for (var i = 0; i < policies.length; i++) {
+    test(function() {
+      test_frame_policy(
+        'fullscreen', same_origin_src, policies[i].sameOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+    test(function() {
+      test_frame_policy(
+        'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect,
+        'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true);
+    }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow +
+       '" and allowfullscreen.');
+  }
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers
new file mode 100644
index 0000000..961d4033
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers
@@ -0,0 +1 @@
+Feature-Policy: fullscreen 'none';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
index 925408ea..be8629d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
@@ -383,3 +383,33 @@
     });
   }, test_name);
 }
+
+// This function tests that frame policy allows a given feature correctly. A
+// feature is allowed in a frame either through inherited policy or specified
+// by iframe allow attribute.
+// Arguments:
+//     feature: feature name.
+//     src: the URL to load in the frame.
+//     test_expect: boolean value of whether the feature should be allowed.
+//     allow: optional, the allow attribute (container policy) of the iframe.
+//     allowfullscreen: optional, boolean value of allowfullscreen attribute.
+function test_frame_policy(
+    feature, src, test_expect, allow, allowfullscreen) {
+  let frame = document.createElement('iframe');
+  document.body.appendChild(frame);
+  // frame_policy should be dynamically updated as allow and allowfullscreen is
+  // updated.
+  var frame_policy = frame.policy;
+  if (typeof allow !== 'undefined') {
+    frame.setAttribute('allow', allow);
+  }
+  if (!!allowfullscreen) {
+    frame.setAttribute('allowfullscreen', true);
+  }
+  frame.src = src;
+  if (test_expect) {
+    assert_true(frame_policy.allowedFeatures().includes(feature));
+  } else {
+    assert_false(frame_policy.allowedFeatures().includes(feature));
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js
index cb038a68..5b9a4fe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js
@@ -32,7 +32,7 @@
 
 var redirUrl = RESOURCES_DIR + "redirect.py";
 var locationUrl = "top.txt";
-var invalidLocationUrl = "#invalidurl:";
+var invalidLocationUrl = "invalidurl:";
 var dataLocationUrl = "data:,data%20url";
 // FIXME: We may want to mix redirect-mode and cors-mode.
 // FIXME: Add tests for "error" redirect-mode.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl
index 5ede1ec..a9ef069 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl
@@ -6,10 +6,10 @@
   readonly attribute double? z;
 };
 
-enum LocalCoordinateSystem { "device", "screen" };
+enum MagnetometerLocalCoordinateSystem { "device", "screen" };
 
 dictionary MagnetometerSensorOptions : SensorOptions {
-  LocalCoordinateSystem referenceFrame = "device";
+  MagnetometerLocalCoordinateSystem referenceFrame = "device";
 };
 
 [Constructor(optional MagnetometerSensorOptions sensorOptions), SecureContext,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl
index 2fee35d..df2ea38 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl
@@ -6,10 +6,10 @@
   void populateMatrix(RotationMatrixType targetMatrix);
 };
 
-enum LocalCoordinateSystem { "device", "screen" };
+enum OrientationSensorLocalCoordinateSystem { "device", "screen" };
 
 dictionary OrientationSensorOptions : SensorOptions  {
-  LocalCoordinateSystem referenceFrame = "device";
+  OrientationSensorLocalCoordinateSystem referenceFrame = "device";
 };
 
 [Constructor(optional OrientationSensorOptions sensorOptions), SecureContext, Exposed=Window]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html
new file mode 100644
index 0000000..caf43d1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Tests for PaymentRequest.canMakePayment() method</title>
+<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({
+  explicit_done: true,
+  explicit_timeout: true,
+});
+
+const basicCard = Object.freeze({ supportedMethods: "basic-card" });
+const defaultMethods = Object.freeze([basicCard]);
+const defaultDetails = Object.freeze({
+  total: {
+    label: "Total",
+    amount: {
+      currency: "USD",
+      value: "1.00",
+    },
+  },
+});
+
+promise_test(async t => {
+  const request = new PaymentRequest(defaultMethods, defaultDetails);
+  try {
+    assert_true(
+      await request.canMakePayment(),
+      `canMakePaymentPromise should be true`
+    );
+    assert_true(
+      await request.canMakePayment(),
+      `canMakePaymentPromise should be true`
+    );
+  } catch (err) {
+    assert_equals(
+      err.name,
+      "NotAllowedError",
+      "if it throws, then it must be a NotAllowedError."
+    );
+  }
+}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`);
+
+promise_test(async t => {
+  const request = new PaymentRequest(defaultMethods, defaultDetails);
+  assert_true(await request.canMakePayment(), "basic-card should be supported");
+}, `If payment method identifier and serialized parts are supported, resolve promise with true.`);
+
+promise_test(async t => {
+  const unsupportedMethods = [
+    "this-is-not-supported",
+    "https://not.supported",
+    "e",
+    "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa",
+    "a-b-q-n-s-pw0",
+    "m-u",
+    "s-l5",
+    "k9-f",
+    "m-l",
+    "u4-n-t",
+    "i488jh6-g18-fck-yb-v7-i",
+    "x-x-t-t-c34-o",
+    "https://wpt",
+    "https://wpt.fyi/",
+    "https://wpt.fyi/payment",
+    "https://wpt.fyi/payment-request",
+    "https://wpt.fyi/payment-request?",
+    "https://wpt.fyi/payment-request?this=is",
+    "https://wpt.fyi/payment-request?this=is&totally",
+    "https://wpt.fyi:443/payment-request?this=is&totally",
+    "https://wpt.fyi:443/payment-request?this=is&totally#fine",
+    "https://:@wpt.fyi:443/payment-request?this=is&totally#👍",
+    " \thttps://wpt\n ",
+    "https://xn--c1yn36f",
+    "https://點看",
+  ];
+  for (const method of unsupportedMethods) {
+    try {
+      const request = new PaymentRequest(
+        [{ supportedMethods: method }],
+        defaultDetails
+      );
+      assert_false(
+        await request.canMakePayment(),
+        `method "${method}" must not be supported`
+      );
+    } catch (err) {
+      assert_equals(
+        err.name,
+        "NotAllowedError",
+        "if it throws, then it must be a NotAllowedError."
+      );
+    }
+  }
+}, `If payment method identifier is unknown, resolve promise with false.`);
+
+promise_test(async t => {
+  // This test might never actually hit its assertion, but that's allowed.
+  const request = new PaymentRequest(defaultMethods, defaultDetails);
+  for (let i = 0; i < 1000; i++) {
+    try {
+      await request.canMakePayment();
+    } catch (err) {
+      assert_equals(
+        err.name,
+        "NotAllowedError",
+        "if it throws, then it must be a NotAllowedError."
+      );
+      break;
+    }
+  }
+  for (let i = 0; i < 1000; i++) {
+    try {
+      await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment();
+    } catch (err) {
+      assert_equals(
+        err.name,
+        "NotAllowedError",
+        "if it throws, then it must be a NotAllowedError."
+      );
+      break;
+    }
+  }
+}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`);
+
+function manualTest1(elem){
+  elem.disabled = true;
+  promise_test(async t => {
+    const request = new PaymentRequest(defaultMethods, defaultDetails);
+    const acceptPromise = request.show(); // Sets state to "interactive"
+    const canMakePaymentPromise = request.canMakePayment();
+    try {
+      const result = await canMakePaymentPromise;
+      assert_true(
+        false,
+        `canMakePaymentPromise should have thrown InvalidStateError`
+      );
+    } catch (err) {
+      await promise_rejects(t, "InvalidStateError", canMakePaymentPromise);
+    } finally {
+      await request.abort();
+      await promise_rejects(t, "AbortError", acceptPromise);
+    }
+    // The state should be "closed"
+    await promise_rejects(t, "InvalidStateError", request.canMakePayment());
+  }, elem.textContent.trim());
+}
+
+function manualTest2(elem){
+ elem.disabled = true;
+  promise_test(async t => {
+    const request = new PaymentRequest(defaultMethods, defaultDetails);
+    const acceptPromise = request.show(); // The state is now "interactive"
+    acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
+    await request.abort(); // The state is now "closed"
+    await promise_rejects(t, "InvalidStateError", request.canMakePayment());
+    try {
+      const result = await request.canMakePayment();
+      assert_true(
+        false,
+        `should have thrown InvalidStateError, but instead returned "${result}"`
+      );
+    } catch (err) {
+      assert_equals(
+        err.name,
+        "InvalidStateError",
+        "must be an InvalidStateError."
+      );
+    }
+  }, elem.textContent.trim());
+  done();
+}
+</script>
+
+<h2>Tests for PaymentRequest.canMakePayment() method</h2>
+<p>
+  Click on each button in sequence from top to bottom without refreshing the page.
+  No payment sheet will be shown, but the tests will run in the background.
+</p>
+<ol>
+  <li>
+    <button onclick="manualTest1(this)">
+      If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.
+    </button>
+  </li>
+  <li>
+    <button onclick="manualTest2(this)">
+      If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.
+    </button>
+  </li>
+</ol>
+<small>
+  If you find a buggy test, please <a href="https://github.com/w3c/web-platform-tests/issues">file a bug</a>
+  and tag one of the <a href="https://github.com/w3c/web-platform-tests/blob/master/payment-request/OWNERS">owners</a>.
+</small>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html
deleted file mode 100644
index 9fe0c4a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html
+++ /dev/null
@@ -1,163 +0,0 @@
-<!DOCTYPE html>
-<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
-<meta charset="utf-8">
-<title>Tests for PaymentRequest.canMakePayment() method</title>
-<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-const basicCard = Object.freeze({ supportedMethods: "basic-card" });
-const defaultMethods = Object.freeze([basicCard]);
-const defaultDetails = Object.freeze({
-  total: {
-    label: "Total",
-    amount: {
-      currency: "USD",
-      value: "1.00",
-    },
-  },
-});
-
-promise_test(async t => {
-  const request = new PaymentRequest(defaultMethods, defaultDetails);
-  try {
-    assert_true(
-      await request.canMakePayment(),
-      `canMakePaymentPromise should be true`
-    );
-    assert_true(
-      await request.canMakePayment(),
-      `canMakePaymentPromise should be true`
-    );
-  } catch (err) {
-    assert_equals(
-      err.name,
-      "NotAllowedError",
-      "if it throws, then it must be a NotAllowedError."
-    );
-  }
-}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`);
-
-promise_test(async t => {
-  const request = new PaymentRequest(defaultMethods, defaultDetails);
-  const acceptPromise = request.show(); // Sets state to "interactive"
-  const canMakePaymentPromise = request.canMakePayment();
-  try {
-    const result = await canMakePaymentPromise;
-    assert_true(
-      false,
-      `canMakePaymentPromise should have thrown InvalidStateError`
-    );
-  } catch (err) {
-    await promise_rejects(t, "InvalidStateError", canMakePaymentPromise);
-  } finally {
-    await request.abort();
-    await promise_rejects(t, "AbortError", acceptPromise);
-  }
-  // The state should be "closed"
-  await promise_rejects(t, "InvalidStateError", request.canMakePayment());
-}, `If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.`);
-
-promise_test(async t => {
-  const request = new PaymentRequest(defaultMethods, defaultDetails);
-  const acceptPromise = request.show(); // The state is now "interactive"
-  acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
-  await request.abort(); // The state is now "closed"
-  await promise_rejects(t, "InvalidStateError", request.canMakePayment());
-  try {
-    const result = await request.canMakePayment();
-    assert_true(
-      false,
-      `should have thrown InvalidStateError, but instead returned "${result}"`
-    );
-  } catch (err) {
-    assert_equals(
-      err.name,
-      "InvalidStateError",
-      "must be an InvalidStateError."
-    );
-  }
-}, `If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.`);
-
-promise_test(async t => {
-  const request = new PaymentRequest(defaultMethods, defaultDetails);
-  assert_true(await request.canMakePayment(), "basic-card should be supported");
-}, `If payment method identifier and serialized parts are supported, resolve promise with true.`);
-
-promise_test(async t => {
-  const unsupportedMethods = [
-    "this-is-not-supported",
-    "https://not.supported",
-    "e",
-    "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa",
-    "a-b-q-n-s-pw0",
-    "m-u",
-    "s-l5",
-    "k9-f",
-    "m-l",
-    "u4-n-t",
-    "i488jh6-g18-fck-yb-v7-i",
-    "x-x-t-t-c34-o",
-    "https://wpt",
-    "https://wpt.fyi/",
-    "https://wpt.fyi/payment",
-    "https://wpt.fyi/payment-request",
-    "https://wpt.fyi/payment-request?",
-    "https://wpt.fyi/payment-request?this=is",
-    "https://wpt.fyi/payment-request?this=is&totally",
-    "https://wpt.fyi:443/payment-request?this=is&totally",
-    "https://wpt.fyi:443/payment-request?this=is&totally#fine",
-    "https://:@wpt.fyi:443/payment-request?this=is&totally#👍",
-    " \thttps://wpt\n ",
-    "https://xn--c1yn36f",
-    "https://點看",
-  ];
-  for (const method of unsupportedMethods) {
-    try {
-      const request = new PaymentRequest(
-        [{ supportedMethods: method }],
-        defaultDetails
-      );
-      assert_false(
-        await request.canMakePayment(),
-        `method "${method}" must not be supported`
-      );
-    } catch (err) {
-      assert_equals(
-        err.name,
-        "NotAllowedError",
-        "if it throws, then it must be a NotAllowedError."
-      );
-    }
-  }
-}, `If payment method identifier is unknown, resolve promise with false.`);
-
-promise_test(async t => {
-  // This test might never actually hit its assertion, but that's allowed.
-  const request = new PaymentRequest(defaultMethods, defaultDetails);
-  for (let i = 0; i < 1000; i++) {
-    try {
-      await request.canMakePayment();
-    } catch (err) {
-      assert_equals(
-        err.name,
-        "NotAllowedError",
-        "if it throws, then it must be a NotAllowedError."
-      );
-      break;
-    }
-  }
-  for (let i = 0; i < 1000; i++) {
-    try {
-      await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment();
-    } catch (err) {
-      assert_equals(
-        err.name,
-        "NotAllowedError",
-        "if it throws, then it must be a NotAllowedError."
-      );
-      break;
-    }
-  }
-}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`);
-</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png
index 6f6b714..58d9f9e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
index 9e6a7ff6..ce3a8eb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
@@ -25,121 +25,61 @@
         navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}));
 }, "Verify that invalid domain error returned by mock is properly handled.");
 
-promise_test(t => {
-    var customMakeCredOptions = {
-        // No challenge.
-        rp: PUBLIC_KEY_RP,
-        user: PUBLIC_KEY_USER,
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-    };
 
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey : customMakeCredOptions}));
+promise_test(t => {
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.challenge;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey : customMakeCredOptions}));
 }, "navigator.credentials.create() with missing challenge");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: PUBLIC_KEY_RP,
-        user: PUBLIC_KEY_USER,
-        // No parameters.
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey : customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.pubKeyCredParams;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey : customMakeCredOptions}));
 }, "navigator.credentials.create() with missing parameters");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        // No rp.
-        user: PUBLIC_KEY_USER,
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.rp;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing rp");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: PUBLIC_KEY_RP,
-        // No user.
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.user;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing user");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: { id: "google.com" },
-        user: PUBLIC_KEY_USER,
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.rp.name;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing rp.name");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: PUBLIC_KEY_RP,
-        user: {
-            name: "avery.a.jones@example.com",
-            displayName: "Avery A. Jones",
-            icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
-        },
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.user.id;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing user.id");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: PUBLIC_KEY_RP,
-        user: {
-            id: new TextEncoder().encode("1098237235409872"),
-            displayName: "Avery A. Jones",
-            icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
-        },
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        timeout: 60000,  // 1 minute
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-        excludeCredentials: [], // No already-registered credentials.
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customMakeCredOptions.user.name;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing user.name");
 
 promise_test(t => {
-    var customMakeCredOptions = {
-        challenge: CHALLENGE,
-        rp: PUBLIC_KEY_RP,
-        user: {
-            id: new TextEncoder().encode("1098237235409872"),
-            name: "avery.a.jones@example.com",
-            icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
-        },
-        pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-        authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.create({publicKey: customMakeCredOptions}));
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+delete customMakeCredOptions.user.displayName;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with missing user.displayName");
 
 promise_test(_ => {
@@ -150,9 +90,9 @@
   mockAuthenticator.setAuthenticatorStatus(
     webauth.mojom.AuthenticatorStatus.SUCCESS);
 
-    return navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}).then(r => {
-        assertValidMakeCredentialResponse(r);
-    });
+  return navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}).then(r => {
+      assertValidMakeCredentialResponse(r);
+  });
 }, "Verify that the mock returns the values we give it.");
 
 promise_test(t => {
@@ -185,29 +125,18 @@
 
 promise_test(_ => {
   mockAuthenticator.reset();
-  mockAuthenticator.setRawId(RAW_ID);
-  mockAuthenticator.setId(ID);
-  mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-  mockAuthenticator.setAttestationObject(ATTESTATION_OBJECT);
-  mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.SUCCESS);
-
-  var customPublicKey = {
-      challenge: CHALLENGE,
-      rp: { name: "Acme" },
-      user: PUBLIC_KEY_USER,
-      pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-  };
-
-    return navigator.credentials.create({publicKey: customPublicKey}).then(r => {
-        assertValidMakeCredentialResponse(r);
-    });
+  mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  customMakeCredOptions.rp = { name: "Acme" };
+  return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
+      assertValidMakeCredentialResponse(r);
+  });
 }, "navigator.credentials.create() with missing rp.id");
 
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   delete customMakeCredOptions.authenticatorSelection;
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
@@ -217,7 +146,7 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   delete customMakeCredOptions.authenticatorSelection.requireResidentKey;
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
@@ -227,7 +156,7 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   delete customMakeCredOptions.authenticatorSelection.userVerification;
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
@@ -238,25 +167,25 @@
   mockAuthenticator.reset();
   mockAuthenticator.setAuthenticatorStatus(
       webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   return promise_rejects(t, "NotSupportedError",
-    navigator.credentials.create({publicKey: customMakeCredOptions}));
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with requireResidentKey true");
 
 promise_test(t => {
   mockAuthenticator.reset();
   mockAuthenticator.setAuthenticatorStatus(
       webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR);
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.userVerification = 'required';
   return promise_rejects(t, "NotSupportedError",
-    navigator.credentials.create({publicKey: customMakeCredOptions}));
+      navigator.credentials.create({publicKey: customMakeCredOptions}));
 }, "navigator.credentials.create() with userVerification required");
 
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.userVerification = 'discouraged';
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
@@ -266,7 +195,7 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.authenticatorAttachment = 'platform';
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
@@ -276,10 +205,11 @@
 promise_test(_ => {
   mockAuthenticator.reset();
   mockAuthenticator.setDefaultsForSuccessfulMakeCredential();
-  var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS);
+  var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
   customMakeCredOptions.authenticatorSelection.authenticatorAttachment = 'cross-platform';
   return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => {
       assertValidMakeCredentialResponse(r);
   });
 }, "navigator.credentials.create() with cross-platform authenticatorAttachment");
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
index a48283c..63f3e8e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
@@ -115,16 +115,10 @@
 
 promise_test(_ => {
   mockAuthenticator.setRawId(RAW_ID);
-  mockAuthenticator.setId(ID);
-  mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-  mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
-  mockAuthenticator.setSignature(SIGNATURE);
-  mockAuthenticator.setAuthenticatorStatus(
-    webauth.mojom.AuthenticatorStatus.SUCCESS);
-
-    return navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS}).then(r => {
-        assertValidGetCredentialResponse(r);
-    });
+  mockAuthenticator.setDefaultsForSuccessfulGetAssertion();
+  return navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS}).then(r => {
+      assertValidGetCredentialResponse(r);
+  });
 }, "Verify that mockAuthenticator returns the values we give it.");
 
 promise_test(t => {
@@ -156,54 +150,28 @@
 }, "Verify that not supported error returned by mock is properly handled.");
 
 promise_test(function(t) {
-    var customGetCredentialOptions = {
-        // No challenge.
-        rpId: "google.com",
-        allowCredentials: [ACCEPTABLE_CREDENTIAL],
-        userVerification: "preferred",
-    };
-
-    return promise_rejects(t, new TypeError(),
-            navigator.credentials.get({publicKey: customGetCredentialOptions}));
+  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customGetCredentialOptions.challenge;
+  return promise_rejects(t, new TypeError(),
+      navigator.credentials.get({publicKey: customGetCredentialOptions}));
 }, "navigator.credentials.get() with missing challenge");
 
 promise_test(_ => {
   mockAuthenticator.reset();
-  mockAuthenticator.setRawId(RAW_ID);
-  mockAuthenticator.setId(ID);
-  mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-  mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
-  mockAuthenticator.setSignature(SIGNATURE);
-  mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.SUCCESS);
-
-  var customPublicKey = {
-      challenge: CHALLENGE,
-      allowCredentials: [ACCEPTABLE_CREDENTIAL],
-      userVerification: "preferred",
-  };
-
-  return navigator.credentials.get({publicKey: customPublicKey}).then(r => {
+  mockAuthenticator.setDefaultsForSuccessfulGetAssertion();
+  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customGetCredentialOptions.rpId;
+  return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => {
       assertValidGetCredentialResponse(r);
   });
 }, "navigator.credentials.get() with missing rpId");
 
 promise_test(_ => {
   mockAuthenticator.reset();
-  mockAuthenticator.setRawId(RAW_ID);
-  mockAuthenticator.setId(ID);
-  mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-  mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
-  mockAuthenticator.setSignature(SIGNATURE);
-  mockAuthenticator.setAuthenticatorStatus(
-      webauth.mojom.AuthenticatorStatus.SUCCESS);
-
-  var customPublicKey = {
-      challenge: CHALLENGE,
-      allowCredentials: [ACCEPTABLE_CREDENTIAL]
-  };
-
-  return navigator.credentials.get({publicKey: customPublicKey}).then(r => {
+  mockAuthenticator.setDefaultsForSuccessfulGetAssertion();
+  var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
+  delete customGetCredentialOptions.userVerification;
+  return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => {
       assertValidGetCredentialResponse(r);
   });
 }, "navigator.credentials.get() with missing user verification requirement");
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
index 9257ef3..aa8bfd1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
@@ -138,6 +138,17 @@
         webauth.mojom.AuthenticatorStatus.SUCCESS);
   }
 
+  // Sets everything needed for a GetAssertion success response.
+  setDefaultsForSuccessfulGetAssertion() {
+    mockAuthenticator.setRawId(RAW_ID);
+    mockAuthenticator.setId(ID);
+    mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
+    mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
+    mockAuthenticator.setSignature(SIGNATURE);
+    mockAuthenticator.setAuthenticatorStatus(
+        webauth.mojom.AuthenticatorStatus.SUCCESS);
+  }
+
   setAuthenticatorStatus(status) {
     this.status_ = status;
   }
@@ -267,6 +278,16 @@
   return "<script>" + code + "</scr" + "ipt>";
 }
 
+function deepCopy(value) {
+  if ([Number, String, Uint8Array].includes(value.constructor))
+    return value;
+
+  let copy = (value.constructor == Array) ? [] : {};
+  for (let key of Object.keys(value))
+    copy[key] = deepCopy(value[key]);
+  return copy;
+}
+
 // Verifies if |r| is the valid response to credentials.create(publicKey).
 function assertValidMakeCredentialResponse(r) {
 assert_equals(r.id, ID, 'id');
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt
index fd7f45ad..23be5236 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt
@@ -1,3 +1,3 @@
 Tests that Debugger.stepInto doesn't ignore inline event listeners.
-functionName (should be empty): empty
+functionName (should be onclick): onclick
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt
new file mode 100644
index 0000000..2545d4e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt
@@ -0,0 +1,13 @@
+Tests DOMSnapshot.getSnapshot method returning paint order indexes.
+box3
+box2
+box5
+box6
+box4
+box1
+box7
+iframe
+mydiv
+shadow-host
+shadow-div
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js
new file mode 100644
index 0000000..8aac438
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js
@@ -0,0 +1,42 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startURL('../resources/stacking_context.html', 'Tests DOMSnapshot.getSnapshot method returning paint order indexes.');
+
+  await session.evaluate(`
+    var host = document.querySelector('#shadow-host').attachShadow({mode: 'open'});
+    var template = document.querySelector('#shadow-template');
+    host.appendChild(template.content);
+    template.remove();
+    document.body.offsetWidth;
+  `);
+
+  function logPaintOrderList(result) {
+    let entries = [];
+
+    for (const layout_node of result.layoutTreeNodes) {
+      let attrs = result.domNodes[layout_node.domNodeIndex].attributes;
+      if (!attrs) continue;
+      for (const attr of attrs) {
+        if (attr.name === 'id') {
+          entries.push({
+            'id': attr.value,
+            'paintOrder': layout_node.paintOrder
+          });
+          break;
+        }
+      }
+    }
+
+    entries.sort(function(a, b) {
+      return a['paintOrder'] - b['paintOrder'];
+    }).forEach(function(e) {
+      testRunner.log(e['id']);
+    });
+  }
+
+  var response = await dp.DOMSnapshot.getSnapshot({'computedStyleWhitelist': [], 'includePaintOrder': true});
+  if (response.error)
+    testRunner.log(response);
+  else
+    logPaintOrderList(response.result);
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html b/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html
new file mode 100644
index 0000000..5093d03
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html
@@ -0,0 +1,81 @@
+<html>
+<head>
+  <style>
+    * {
+      margin: 0px;
+    }
+    div {
+      position: absolute;
+      padding-top: 20px;
+      border: 1px solid black;
+      color: white;
+      text-align: center;
+    }
+    #box1 {
+      z-index: 5;
+      background-color: rgba(200, 100, 100, 0.9);
+      width: 100px;
+      height: 400px;
+    }
+    #box2 {
+      z-index: 4;
+      background-color: rgba(100, 200, 100, 0.9);
+      width: 560px;
+      height: 300px;
+      top: 50px;
+      left: 70px;
+    }
+    #box3 {
+      z-index: 2;
+      background-color: rgba(200, 100, 100, 0.9);
+      width: 100px;
+      height: 400px;
+      left: 600px;
+    }
+    #box4 {
+      z-index: 6;
+      background-color: rgba(100, 100, 200, 0.9);
+      left: 20px;
+      width: 100px;
+      height: 220px;
+      padding-left: 0px;
+    }
+    #box5 {
+      z-index: 1;
+      background-color: rgba(100, 100, 200, 0.9);
+      left: 440px;
+      width: 100px;
+      height: 220px;
+    }
+    #box6 {
+      z-index: 3;
+      background-color: rgba(100, 200, 200, 0.9);
+      left: 80px;
+      top: 120px;
+      width: 400px;
+      height: 100px;
+    }
+    #box7 {
+      z-index: 5;
+      top: 500px;
+    }
+  </style>
+  <template id="shadow-template">
+    <div id="shadow-div">Hi!</div>
+  </template>
+</head>
+<body>
+<div id="box1">Box1</div>
+<div id="box2">
+  Box2
+  <div id="box4">Box4</div>
+  <div id="box5">Box5</div>
+  <div id="box6">Box6</div>
+</div>
+<div id="box3">Box3</div>
+<div id="box7">
+  <iframe src='./iframe.html' width="400" height="200" id="iframe"></iframe>
+  <div id="shadow-host"></div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
index 0a3a940..2774eb94 100644
--- a/third_party/WebKit/LayoutTests/resources/testharnessreport.js
+++ b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
@@ -27,12 +27,21 @@
         testRunner.setCloseRemainingWindowsWhenComplete(true);
         testRunner.setDumpJavaScriptDialogs(false);
 
-        // fetch-event-referrer-policy.https.html intentionally loads mixed
-        // content in order to test the referrer policy, so
-        // WebKitAllowRunningInsecureContent must be set to true or else the
-        // load would be blocked.
-        if (document.URL.indexOf('service-workers/service-worker/fetch-event-referrer-policy.https.html') >= 0) {
+        // Some tests intentionally load mixed content in order to test the
+        // referrer policy, so WebKitAllowRunningInsecureContent must be set
+        // to true or else the load would be blocked.
+        const paths = [
+            'service-workers/service-worker/fetch-event-referrer-policy.https.html',
+            'beacon/headers/header-referrer-no-referrer-when-downgrade.https.html',
+            'beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html',
+            'beacon/headers/header-referrer-strict-origin.https.html',
+            'beacon/headers/header-referrer-unsafe-url.https.html',
+        ];
+        for (const path of paths) {
+          if (document.URL.endsWith(path)) {
             testRunner.overridePreference('WebKitAllowRunningInsecureContent', true);
+            break;
+          }
         }
     }
 
diff --git a/third_party/WebKit/Source/bindings/scripts/scripts.gni b/third_party/WebKit/Source/bindings/scripts/scripts.gni
index 50a33e7f..07cba88 100644
--- a/third_party/WebKit/Source/bindings/scripts/scripts.gni
+++ b/third_party/WebKit/Source/bindings/scripts/scripts.gni
@@ -212,88 +212,50 @@
     "//third_party/WebKit/Source/core:generated_testing_idls",
   ]
 
-  # On mac spawning a python process per IDL file is slow. Use a single action
-  # instead.
-  # TODO(bashi,tikuta): Use a pool when crbug.com/635308 is fixed.
-  if (is_mac) {
-    action(target_name) {
-      script = _script
-      inputs = _inputs
-      public_deps = _public_deps
+  # Spawning a python process per IDL file is slow. Use a single action
+  # instead (crbug.com/821256).
+  action(target_name) {
+    script = _script
+    inputs = _inputs
+    public_deps = _public_deps
 
-      sources = invoker.sources
-      outputs = []
-      foreach(_source, sources) {
-        _name_part = get_path_info(_source, "name")
-        if (snake_case_source_files) {
-          outputs += [
-            "$output_dir/v8_${_name_part}${output_name_suffix}.cc",
-            "$output_dir/v8_${_name_part}${output_name_suffix}.h",
-          ]
-        } else {
-          outputs += [
-            "$output_dir/V8${_name_part}${output_name_suffix}.cpp",
-            "$output_dir/V8${_name_part}${output_name_suffix}.h",
-          ]
-        }
-      }
-
-      idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
-      write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
-      inputs += [ idl_files_list ]
-
-      args = []
+    sources = invoker.sources
+    outputs = []
+    foreach(_source, sources) {
+      _name_part = get_path_info(_source, "name")
       if (snake_case_source_files) {
-        args += [ "--snake-case-generated-files" ]
-      }
-      args += [
-        "--cache-dir",
-        rebase_path(bindings_scripts_output_dir, root_build_dir),
-        "--output-dir",
-        rebase_path(output_dir, root_build_dir),
-        "--info-dir",
-        rebase_path("$bindings_output_dir", root_build_dir),
-        "--target-component",
-        invoker.target_component,
-        "--read-idl-list-from-file",
-        rebase_path(idl_files_list, root_build_dir),
-      ]
-    }
-  } else {
-    action_foreach(target_name) {
-      script = _script
-      inputs = _inputs
-      public_deps = _public_deps
-
-      sources = invoker.sources
-      if (snake_case_source_files) {
-        outputs = [
-          "$output_dir/v8_{{source_name_part}}${output_name_suffix}.cc",
-          "$output_dir/v8_{{source_name_part}}${output_name_suffix}.h",
+        outputs += [
+          "$output_dir/v8_${_name_part}${output_name_suffix}.cc",
+          "$output_dir/v8_${_name_part}${output_name_suffix}.h",
         ]
       } else {
-        outputs = [
-          "$output_dir/V8{{source_name_part}}${output_name_suffix}.cpp",
-          "$output_dir/V8{{source_name_part}}${output_name_suffix}.h",
+        outputs += [
+          "$output_dir/V8${_name_part}${output_name_suffix}.cpp",
+          "$output_dir/V8${_name_part}${output_name_suffix}.h",
         ]
       }
-
-      args = []
-      if (snake_case_source_files) {
-        args += [ "--snake-case-generated-files" ]
-      }
-      args += [
-        "--cache-dir",
-        rebase_path(bindings_scripts_output_dir, root_build_dir),
-        "--output-dir",
-        rebase_path(output_dir, root_build_dir),
-        "--info-dir",
-        rebase_path("$bindings_output_dir", root_build_dir),
-        "--target-component",
-        invoker.target_component,
-        "{{source}}",
-      ]
     }
+
+    idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp"
+    write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir))
+    inputs += [ idl_files_list ]
+
+    args = []
+    if (snake_case_source_files) {
+      args += [ "--snake-case-generated-files" ]
+    }
+    args += [
+      "--cache-dir",
+      rebase_path(bindings_scripts_output_dir, root_build_dir),
+      "--output-dir",
+      rebase_path(output_dir, root_build_dir),
+      "--info-dir",
+      rebase_path("$bindings_output_dir", root_build_dir),
+      "--target-component",
+      invoker.target_component,
+      "--read-idl-list-from-file",
+      rebase_path(idl_files_list, root_build_dir),
+    ]
   }
 }
 
diff --git a/third_party/WebKit/Source/bindings/scripts/utilities.py b/third_party/WebKit/Source/bindings/scripts/utilities.py
index b3b43597..7f89901 100644
--- a/third_party/WebKit/Source/bindings/scripts/utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/utilities.py
@@ -525,14 +525,18 @@
     output = []
     for line in text.split('\n'):
         # Skip empty lines.
-        if re_empty_line.match(line):
+        if line == '' or re_empty_line.match(line):
             was_empty_line = True
             continue
 
         # Emit a single empty line if needed.
         if was_empty_line:
             was_empty_line = False
-            match = re_first_brace.search(line)
+            if '}' in line:
+                match = re_first_brace.search(line)
+            else:
+                match = None
+
             if was_open_brace:
                 # No empty line just after an open brace.
                 pass
@@ -547,7 +551,10 @@
         output.append(line)
 
         # Remember an open brace.
-        match = re_last_brace.search(line)
+        if '{' in line:
+            match = re_last_brace.search(line)
+        else:
+            match = None
         was_open_brace = (match and match.group('last') == '{' and 'namespace' not in line)
 
     # Let |'\n'.join| emit the last newline.
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
index e2407f83..ad5d8da 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -519,7 +519,7 @@
                         Keyframe::PropertySpecificKeyframe* keyframe,
                         const AnimatableValue* value,
                         const TimingFunction& keyframe_timing_function) {
-  FilterEffectBuilder builder(nullptr, FloatRect(), 1);
+  FilterEffectBuilder builder(FloatRect(), 1);
   CompositorFilterKeyframe filter_keyframe(
       keyframe->Offset(),
       builder.BuildFilterOperations(
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.cpp b/third_party/WebKit/Source/core/css/CSSURIValue.cpp
index 908ff91c..e476f957 100644
--- a/third_party/WebKit/Source/core/css/CSSURIValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSURIValue.cpp
@@ -6,9 +6,8 @@
 
 #include "core/css/CSSMarkup.h"
 #include "core/dom/Document.h"
-#include "core/svg/SVGElementProxy.h"
+#include "core/svg/SVGResource.h"
 #include "platform/weborigin/KURL.h"
-#include "platform/wtf/text/WTFString.h"
 
 namespace blink {
 
@@ -24,16 +23,10 @@
 
 CSSURIValue::~CSSURIValue() = default;
 
-SVGElementProxy& CSSURIValue::EnsureElementProxy(
-    const Document& document) const {
-  if (proxy_)
-    return *proxy_;
-  AtomicString fragment_id = FragmentIdentifier();
-  if (IsLocal(document))
-    proxy_ = SVGElementProxy::Create(fragment_id);
-  else
-    proxy_ = SVGElementProxy::Create(absolute_url_, fragment_id);
-  return *proxy_;
+SVGResource* CSSURIValue::EnsureResourceReference() const {
+  if (!resource_)
+    resource_ = new ExternalSVGResource(AbsoluteUrl());
+  return resource_;
 }
 
 void CSSURIValue::ReResolveUrl(const Document& document) const {
@@ -44,7 +37,7 @@
   if (url_string == absolute_url_)
     return;
   absolute_url_ = url_string;
-  proxy_ = nullptr;
+  resource_ = nullptr;
 }
 
 String CSSURIValue::CustomCSSText() const {
@@ -76,7 +69,7 @@
 }
 
 void CSSURIValue::TraceAfterDispatch(blink::Visitor* visitor) {
-  visitor->Trace(proxy_);
+  visitor->Trace(resource_);
   CSSValue::TraceAfterDispatch(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.h b/third_party/WebKit/Source/core/css/CSSURIValue.h
index 743c65e4..e8b9064 100644
--- a/third_party/WebKit/Source/core/css/CSSURIValue.h
+++ b/third_party/WebKit/Source/core/css/CSSURIValue.h
@@ -12,7 +12,7 @@
 
 class Document;
 class KURL;
-class SVGElementProxy;
+class SVGResource;
 
 class CSSURIValue : public CSSValue {
  public:
@@ -24,7 +24,7 @@
   }
   ~CSSURIValue();
 
-  SVGElementProxy& EnsureElementProxy(const Document&) const;
+  SVGResource* EnsureResourceReference() const;
   void ReResolveUrl(const Document&) const;
 
   const String& Value() const { return relative_url_; }
@@ -48,7 +48,7 @@
   AtomicString relative_url_;
   bool is_local_;
 
-  mutable Member<SVGElementProxy> proxy_;
+  mutable Member<SVGResource> resource_;
   mutable AtomicString absolute_url_;
 };
 
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
index c0e5299..eb10e745 100644
--- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
@@ -39,7 +39,6 @@
 #include "core/style/StyleGeneratedImage.h"
 #include "core/style/StyleImage.h"
 #include "core/style/StylePendingImage.h"
-#include "core/svg/SVGElementProxy.h"
 #include "core/svg/SVGTreeScopeResources.h"
 #include "platform/Length.h"
 #include "platform/loader/fetch/FetchParameters.h"
@@ -97,22 +96,21 @@
   return value.CachedImage();
 }
 
-SVGElementProxy& ElementStyleResources::CachedOrPendingFromValue(
-    const CSSURIValue& value) {
-  return value.EnsureElementProxy(*document_);
-}
-
 SVGResource* ElementStyleResources::GetSVGResourceFromValue(
     TreeScope& tree_scope,
-    const CSSURIValue& value) const {
-  if (!value.IsLocal(*document_))
-    return nullptr;
-  SVGTreeScopeResources& tree_scope_resources =
-      tree_scope.EnsureSVGTreeScopedResources();
-  return tree_scope_resources.ResourceForId(value.FragmentIdentifier());
+    const CSSURIValue& value,
+    AllowExternal allow_external) const {
+  if (value.IsLocal(*document_)) {
+    SVGTreeScopeResources& tree_scope_resources =
+        tree_scope.EnsureSVGTreeScopedResources();
+    return tree_scope_resources.ResourceForId(value.FragmentIdentifier());
+  }
+  if (allow_external == kAllowExternalResource)
+    return value.EnsureResourceReference();
+  return nullptr;
 }
 
-void ElementStyleResources::LoadPendingSVGDocuments(
+void ElementStyleResources::LoadPendingSVGResources(
     ComputedStyle* computed_style) {
   if (!computed_style->HasFilter())
     return;
@@ -123,7 +121,8 @@
       continue;
     ReferenceFilterOperation& reference_operation =
         ToReferenceFilterOperation(*filter_operation);
-    reference_operation.ElementProxy().Resolve(*document_);
+    if (SVGResource* resource = reference_operation.Resource())
+      resource->Load(*document_);
   }
 }
 
@@ -311,7 +310,7 @@
 void ElementStyleResources::LoadPendingResources(
     ComputedStyle* computed_style) {
   LoadPendingImages(computed_style);
-  LoadPendingSVGDocuments(computed_style);
+  LoadPendingSVGResources(computed_style);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
index 46cc179..29e8a15 100644
--- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
+++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
@@ -43,7 +43,6 @@
 class CSSValue;
 class ComputedStyle;
 class Document;
-class SVGElementProxy;
 class SVGResource;
 class StyleImage;
 class StylePendingImage;
@@ -60,8 +59,12 @@
   StyleImage* GetStyleImage(CSSPropertyID, const CSSValue&);
   StyleImage* CachedOrPendingFromValue(CSSPropertyID, const CSSImageValue&);
   StyleImage* SetOrPendingFromValue(CSSPropertyID, const CSSImageSetValue&);
-  SVGElementProxy& CachedOrPendingFromValue(const CSSURIValue&);
-  SVGResource* GetSVGResourceFromValue(TreeScope&, const CSSURIValue&) const;
+
+  enum AllowExternal { kDontAllowExternalResource, kAllowExternalResource };
+  SVGResource* GetSVGResourceFromValue(
+      TreeScope&,
+      const CSSURIValue&,
+      AllowExternal = kDontAllowExternalResource) const;
 
   void LoadPendingResources(ComputedStyle*);
 
@@ -69,7 +72,7 @@
   StyleImage* GeneratedOrPendingFromValue(CSSPropertyID,
                                           const CSSImageGeneratorValue&);
 
-  void LoadPendingSVGDocuments(ComputedStyle*);
+  void LoadPendingSVGResources(ComputedStyle*);
   void LoadPendingImages(ComputedStyle*);
 
   StyleImage* LoadPendingImage(
diff --git a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
index 852ef8d..7cbeda3 100644
--- a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
@@ -138,10 +138,12 @@
       CountFilterUse(FilterOperation::REFERENCE, state.GetDocument());
 
       const CSSURIValue& url_value = ToCSSURIValue(*curr_value);
-      SVGElementProxy& element_proxy =
-          state.GetElementStyleResources().CachedOrPendingFromValue(url_value);
+      SVGResource* resource =
+          state.GetElementStyleResources().GetSVGResourceFromValue(
+              state.GetTreeScope(), url_value,
+              ElementStyleResources::kAllowExternalResource);
       operations.Operations().push_back(
-          ReferenceFilterOperation::Create(url_value.Value(), element_proxy));
+          ReferenceFilterOperation::Create(url_value.Value(), resource));
       continue;
     }
 
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
index f4bb1644..89b6acf 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
@@ -991,6 +991,13 @@
     return;
   }
 
+  if (child->parent_) {
+    exception_state.ThrowDOMException(kNotSupportedError,
+                                      "Reparenting is not supported yet.");
+    return;
+  }
+  child->parent_ = this;
+
   if (!GetDocument()->GetSecurityOrigin()->CanAccess(
           child->GetDocument()->GetSecurityOrigin())) {
     exception_state.ThrowDOMException(
@@ -1036,7 +1043,13 @@
 }
 
 ExecutionContext* AccessibleNode::GetExecutionContext() const {
-  return element_->GetExecutionContext();
+  if (element_)
+    return element_->GetExecutionContext();
+
+  if (parent_)
+    return parent_->GetExecutionContext();
+
+  return nullptr;
 }
 
 void AccessibleNode::SetStringProperty(AOMStringProperty property,
@@ -1144,6 +1157,7 @@
   visitor->Trace(relation_properties_);
   visitor->Trace(relation_list_properties_);
   visitor->Trace(children_);
+  visitor->Trace(parent_);
   EventTargetWithInlineData::Trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.h b/third_party/WebKit/Source/core/dom/AccessibleNode.h
index 0dbd53f..efd24ff 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.h
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.h
@@ -388,6 +388,10 @@
   // This object's AccessibleNode children, which must be only virtual
   // AccessibleNodes (with no associated Element).
   HeapVector<Member<AccessibleNode>> children_;
+
+  // This object's AccessibleNode parent. Only set if this is a
+  // virtual AccessibleNode that's in the tree.
+  Member<AccessibleNode> parent_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 68b2f68..b507df3a 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -3659,7 +3659,11 @@
   if (style.Display() == EDisplay::kContents && !NeedsReattachLayoutTree())
     DCHECK(!GetLayoutObject() || IsPseudoElement());
 #endif
-
+  if (IsSVGElement()) {
+    Element* parent_element = LayoutTreeBuilderTraversal::ParentElement(*this);
+    if (parent_element && !parent_element->IsSVGElement())
+      return false;
+  }
   return style.Display() == EDisplay::kContents ||
          IsHTMLOptGroupElement(*this) || IsHTMLOptionElement(*this) ||
          IsSVGStopElement(*this);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
index 16111e73..ce251aa2 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
@@ -30,9 +30,14 @@
 #include "core/inspector/InspectedFrames.h"
 #include "core/inspector/InspectorDOMAgent.h"
 #include "core/inspector/InspectorDOMDebuggerAgent.h"
+#include "core/layout/LayoutEmbeddedContent.h"
 #include "core/layout/LayoutObject.h"
 #include "core/layout/LayoutText.h"
+#include "core/layout/LayoutView.h"
 #include "core/layout/line/InlineTextBox.h"
+#include "core/paint/PaintLayer.h"
+#include "core/paint/PaintLayerStackingNode.h"
+#include "core/paint/PaintLayerStackingNodeIterator.h"
 #include "platform/wtf/PtrUtil.h"
 
 namespace blink {
@@ -52,6 +57,19 @@
       .build();
 }
 
+Document* GetEmbeddedDocument(PaintLayer* layer) {
+  // Documents are embedded on their own PaintLayer via a LayoutEmbeddedContent.
+  if (layer->GetLayoutObject().IsLayoutEmbeddedContent()) {
+    FrameView* frame_view =
+        ToLayoutEmbeddedContent(layer->GetLayoutObject()).ChildFrameView();
+    if (frame_view && frame_view->IsLocalFrameView()) {
+      LocalFrameView* local_frame_view = ToLocalFrameView(frame_view);
+      return local_frame_view->GetFrame().GetDocument();
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace
 
 struct InspectorDOMSnapshotAgent::VectorStringHashTraits
@@ -99,7 +117,8 @@
 
 Response InspectorDOMSnapshotAgent::getSnapshot(
     std::unique_ptr<protocol::Array<String>> style_whitelist,
-    protocol::Maybe<bool> get_dom_listeners,
+    protocol::Maybe<bool> include_event_listeners,
+    protocol::Maybe<bool> include_paint_order,
     std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>>* dom_nodes,
     std::unique_ptr<protocol::Array<protocol::DOMSnapshot::LayoutTreeNode>>*
         layout_tree_nodes,
@@ -129,8 +148,14 @@
         std::make_pair(style_whitelist->get(i), property_id));
   }
 
+  if (include_paint_order.fromMaybe(false)) {
+    paint_order_map_ = std::make_unique<PaintOrderMap>();
+    next_paint_order_index_ = 0;
+    TraversePaintLayerTree(document);
+  }
+
   // Actual traversal.
-  VisitNode(document, get_dom_listeners.fromMaybe(false));
+  VisitNode(document, include_event_listeners.fromMaybe(false));
 
   // Extract results from state and reset.
   *dom_nodes = std::move(dom_nodes_);
@@ -138,16 +163,18 @@
   *computed_styles = std::move(computed_styles_);
   computed_styles_map_.reset();
   css_property_whitelist_.reset();
+  paint_order_map_.reset();
   return Response::OK();
 }
 
 int InspectorDOMSnapshotAgent::VisitNode(Node* node,
                                          bool include_event_listeners) {
-  if (node->IsDocumentNode()) {
-    // Update layout tree before traversal of document so that we inspect a
-    // current and consistent state of all trees.
+  // Update layout tree before traversal of document so that we inspect a
+  // current and consistent state of all trees. No need to do this if paint
+  // order was calculated, since layout trees were already updated during
+  // TraversePaintLayerTree().
+  if (node->IsDocumentNode() && !paint_order_map_)
     node->GetDocument().UpdateStyleAndLayoutTree();
-  }
 
   String node_value;
   switch (node->getNodeType()) {
@@ -363,6 +390,16 @@
   if (style_index != -1)
     layout_tree_node->setStyleIndex(style_index);
 
+  if (paint_order_map_) {
+    PaintLayer* paint_layer = layout_object->EnclosingLayer();
+
+    // We visited all PaintLayers when building |paint_order_map_|.
+    DCHECK(paint_order_map_->Contains(paint_layer));
+
+    if (int paint_order = paint_order_map_->at(paint_layer))
+      layout_tree_node->setPaintOrder(paint_order);
+  }
+
   if (layout_object->IsText()) {
     LayoutText* layout_text = ToLayoutText(layout_object);
     layout_tree_node->setLayoutText(layout_text->GetText());
@@ -435,6 +472,41 @@
   return index;
 }
 
+void InspectorDOMSnapshotAgent::TraversePaintLayerTree(Document* document) {
+  // Update layout tree before traversal of document so that we inspect a
+  // current and consistent state of all trees.
+  document->UpdateStyleAndLayoutTree();
+
+  PaintLayer* root_layer = document->GetLayoutView()->Layer();
+  // LayoutView requires a PaintLayer.
+  DCHECK(root_layer);
+
+  VisitPaintLayer(root_layer);
+}
+
+void InspectorDOMSnapshotAgent::VisitPaintLayer(PaintLayer* layer) {
+  DCHECK(!paint_order_map_->Contains(layer));
+
+  paint_order_map_->Set(layer, next_paint_order_index_);
+  next_paint_order_index_++;
+
+  // If there is an embedded document, integrate it into the painting order.
+  Document* embedded_document = GetEmbeddedDocument(layer);
+  if (embedded_document)
+    TraversePaintLayerTree(embedded_document);
+
+  // If there's an embedded document, there shouldn't be any children.
+  DCHECK(!embedded_document || !layer->FirstChild());
+
+  if (!embedded_document) {
+    PaintLayerStackingNode* node = layer->StackingNode();
+    PaintLayerStackingNodeIterator iterator(*node, kAllChildren);
+    while (PaintLayerStackingNode* child_node = iterator.Next()) {
+      VisitPaintLayer(child_node->Layer());
+    }
+  }
+}
+
 void InspectorDOMSnapshotAgent::Trace(blink::Visitor* visitor) {
   visitor->Trace(inspected_frames_);
   visitor->Trace(dom_debugger_agent_);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h
index 102f100..ae8ee5a 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h
@@ -14,9 +14,11 @@
 
 namespace blink {
 
+class Document;
 class Element;
 class InspectedFrames;
 class Node;
+class PaintLayer;
 
 class CORE_EXPORT InspectorDOMSnapshotAgent final
     : public InspectorBaseAgent<protocol::DOMSnapshot::Metainfo> {
@@ -32,7 +34,8 @@
 
   protocol::Response getSnapshot(
       std::unique_ptr<protocol::Array<String>> style_whitelist,
-      protocol::Maybe<bool> get_dom_listeners,
+      protocol::Maybe<bool> include_event_listeners,
+      protocol::Maybe<bool> include_paint_order,
       std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>>*
           dom_nodes,
       std::unique_ptr<protocol::Array<protocol::DOMSnapshot::LayoutTreeNode>>*
@@ -65,12 +68,17 @@
   // styles in |style_whitelist_|.
   int GetStyleIndexForNode(Node*);
 
+  // Traverses the PaintLayer tree in paint order to fill |paint_order_map_|.
+  void TraversePaintLayerTree(Document*);
+  void VisitPaintLayer(PaintLayer*);
+
   struct VectorStringHashTraits;
   using ComputedStylesMap = WTF::HashMap<Vector<String>,
                                          int,
                                          VectorStringHashTraits,
                                          VectorStringHashTraits>;
   using CSSPropertyWhitelist = Vector<std::pair<String, CSSPropertyID>>;
+  using PaintOrderMap = WTF::HashMap<PaintLayer*, int>;
 
   // State of current snapshot.
   std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>> dom_nodes_;
@@ -83,6 +91,9 @@
   std::unique_ptr<ComputedStylesMap> computed_styles_map_;
   std::unique_ptr<Vector<std::pair<String, CSSPropertyID>>>
       css_property_whitelist_;
+  // Maps a PaintLayer to its paint order index.
+  std::unique_ptr<PaintOrderMap> paint_order_map_;
+  int next_paint_order_index_ = 0;
 
   Member<InspectedFrames> inspected_frames_;
   Member<InspectorDOMDebuggerAgent> dom_debugger_agent_;
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index 33c5b81..ab21ef8 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4439,12 +4439,12 @@
                         },
                         {
                             "name": "startCharacterIndex",
-                            "description": "The starting index in characters, for this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.",
+                            "description": "The starting index in characters, for this post layout textbox substring. Characters that\nwould be represented as a surrogate pair in UTF-16 have length 2.",
                             "type": "integer"
                         },
                         {
                             "name": "numCharacters",
-                            "description": "The number of characters in this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.",
+                            "description": "The number of characters in this post layout textbox substring. Characters that would be\nrepresented as a surrogate pair in UTF-16 have length 2.",
                             "type": "integer"
                         }
                     ]
@@ -4484,6 +4484,12 @@
                             "description": "Index into the `computedStyles` array returned by `getSnapshot`.",
                             "optional": true,
                             "type": "integer"
+                        },
+                        {
+                            "name": "paintOrder",
+                            "description": "Global paint order index, which is determined by the stacking order of the nodes. Nodes\nthat are painted together will have the same index. Only provided if includePaintOrder in\ngetSnapshot was true.",
+                            "optional": true,
+                            "type": "integer"
                         }
                     ]
                 },
@@ -4538,6 +4544,12 @@
                             "description": "Whether or not to retrieve details of DOM listeners (default false).",
                             "optional": true,
                             "type": "boolean"
+                        },
+                        {
+                            "name": "includePaintOrder",
+                            "description": "Whether to determine and include the paint order index of LayoutTreeNodes (default false).",
+                            "optional": true,
+                            "type": "boolean"
                         }
                     ],
                     "returns": [
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
index 0d3e6a03..4cddd342 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
@@ -2031,9 +2031,11 @@
     properties
       # The absolute position bounding box.
       DOM.Rect boundingBox
-      # The starting index in characters, for this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.
+      # The starting index in characters, for this post layout textbox substring. Characters that
+      # would be represented as a surrogate pair in UTF-16 have length 2.
       integer startCharacterIndex
-      # The number of characters in this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.
+      # The number of characters in this post layout textbox substring. Characters that would be
+      # represented as a surrogate pair in UTF-16 have length 2.
       integer numCharacters
 
   # Details of an element in the DOM tree with a LayoutObject.
@@ -2049,6 +2051,10 @@
       optional array of InlineTextBox inlineTextNodes
       # Index into the `computedStyles` array returned by `getSnapshot`.
       optional integer styleIndex
+      # Global paint order index, which is determined by the stacking order of the nodes. Nodes
+      # that are painted together will have the same index. Only provided if includePaintOrder in
+      # getSnapshot was true.
+      optional integer paintOrder
 
   # A subset of the full ComputedStyle as defined by the request whitelist.
   type ComputedStyle extends object
@@ -2074,6 +2080,8 @@
       array of string computedStyleWhitelist
       # Whether or not to retrieve details of DOM listeners (default false).
       optional boolean includeEventListeners
+      # Whether to determine and include the paint order index of LayoutTreeNodes (default false).
+      optional boolean includePaintOrder
     returns
       # The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document.
       array of DOMNode domNodes
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
index 6622188..b7c24a4e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -9,6 +9,7 @@
 #include "core/layout/LayoutTestHelper.h"
 #include "core/layout/LayoutTextFragment.h"
 #include "core/layout/LayoutView.h"
+#include "core/svg/SVGGElement.h"
 #include "platform/json/JSONValues.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -705,4 +706,22 @@
              "\\u0440\\u043E\\u0434\\u0435\\u043D\\u0434\\u0435\\u043D\\n\""));
 }
 
+TEST_F(LayoutObjectTest, DisplayContentsSVGGElementInHTML) {
+  SetBodyInnerHTML(R"HTML(
+    <style>*|g { display:contents}</style>
+    <span id=span></span>
+  )HTML");
+
+  Element* span = GetDocument().getElementById("span");
+  SVGGElement* svg_element = SVGGElement::Create(GetDocument());
+  Text* text = Text::Create(GetDocument(), "text");
+  svg_element->appendChild(text);
+  span->appendChild(svg_element);
+
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  ASSERT_FALSE(svg_element->GetLayoutObject());
+  ASSERT_FALSE(text->GetLayoutObject());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index 00be139..d4043b30 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -926,6 +926,10 @@
     abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty();
     if (child_space->FloatsBfcOffset())
       DCHECK(layout_result->UnpositionedFloats().IsEmpty());
+    // If our BFC offset is unknown, and the child got pushed down by floats, so
+    // will we.
+    if (layout_result->IsPushedByFloats())
+      container_builder_.SetIsPushedByFloats();
   }
 
   // A child may have aborted its layout if it resolved its BFC offset. If
@@ -1413,10 +1417,14 @@
     }
   }
 
-  if (!has_processed_first_child_ && !is_pushed_by_floats) {
+  if (!has_processed_first_child_ &&
+      (container_builder_.IsPushedByFloats() || !is_pushed_by_floats)) {
     // We're breaking before the first piece of in-flow content inside this
     // block, even if it's not a valid class C break point [1] in this case. We
-    // really don't want to break here, if we can find something better.
+    // really don't want to break here, if we can find something better. A class
+    // C break point occurs if a first child has been pushed by floats, but this
+    // only applies to the outermost block that gets pushed (in case this parent
+    // and the child have adjoining top margins).
     //
     // [1] https://www.w3.org/TR/css-break-3/#possible-breaks
     container_builder_.SetHasLastResortBreak();
@@ -1608,16 +1616,23 @@
   }
 
   WritingMode writing_mode;
+  Optional<LayoutUnit> clearance_offset;
+  if (!constraint_space_.IsNewFormattingContext())
+    clearance_offset = ConstraintSpace().ClearanceOffset();
   if (child.IsInline()) {
-    space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset());
     writing_mode = Style().GetWritingMode();
   } else {
     const ComputedStyle& child_style = child.Style();
-    space_builder
-        .SetClearanceOffset(
-            exclusion_space_->ClearanceOffset(child_style.Clear()))
-        .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style))
-        .SetTextDirection(child_style.Direction());
+    LayoutUnit child_clearance_offset =
+        exclusion_space_->ClearanceOffset(child_style.Clear());
+    if (clearance_offset) {
+      clearance_offset =
+          std::max(clearance_offset.value(), child_clearance_offset);
+    } else {
+      clearance_offset = child_clearance_offset;
+    }
+    space_builder.SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style));
+    space_builder.SetTextDirection(child_style.Direction());
     writing_mode = child_style.GetWritingMode();
 
     // PositionListMarker() requires a first line baseline.
@@ -1629,6 +1644,7 @@
                : kIdeographicBaseline});
     }
   }
+  space_builder.SetClearanceOffset(clearance_offset);
 
   LayoutUnit space_available;
   if (ConstraintSpace().HasBlockFragmentation()) {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
index 5289870..e2f0f4f 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -2566,12 +2566,6 @@
 }
 
 TEST_F(NGColumnLayoutAlgorithmTest, NoClassCBreakPointBeforeBfc) {
-  // TODO(mstensho): Get rid of #workaround below. It's needed because clearance
-  // is applied after layout, with no second layout pass. A second pass is
-  // really needed by fragmentation, since the amount of remaining space may
-  // have decreased so much that we need to break inside (while we didn't have
-  // to in the first pass). Ideally, we'd specify clear:both on #container
-  // instead, but that doesn't work currently.
   SetBodyInnerHTML(R"HTML(
     <style>
       #parent {
@@ -2586,8 +2580,7 @@
       <div id="parent">
         <div style="width:50px; height:50px;"></div>
         <div style="float:left; width:100%; height:40px;"></div>
-        <div id="workaround" style="clear:both; width:1px;"></div>
-        <div id="container" style="width:55px;">
+        <div id="container" style="clear:both; width:55px;">
           <div style="display:flow-root; break-inside:avoid; width:44px; height:60px;"></div>
         </div>
       </div>
@@ -2601,7 +2594,6 @@
       offset:0,0 size:100x100
         offset:0,0 size:50x50
         offset:0,50 size:100x40
-        offset:0,90 size:1x0
       offset:110,0 size:100x60
         offset:0,0 size:55x60
           offset:0,0 size:44x60
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
index 59cddb2..b80bb9a 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
@@ -117,6 +117,7 @@
     is_pushed_by_floats_ = true;
     return *this;
   }
+  bool IsPushedByFloats() const { return is_pushed_by_floats_; }
 
 #ifndef NDEBUG
   String ToString() const;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
index 0f6fbcf..bc8948d3 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
@@ -21,7 +21,6 @@
 
 #include "core/layout/svg/SVGResources.h"
 #include "core/layout/svg/SVGResourcesCache.h"
-#include "core/svg/SVGElementProxy.h"
 #include "core/svg/SVGResource.h"
 #include "core/svg/SVGTreeScopeResources.h"
 #include "platform/wtf/AutoReset.h"
@@ -63,17 +62,6 @@
   ClearInvalidationMask();
 }
 
-SVGElementProxySet* LayoutSVGResourceContainer::ElementProxySet() {
-  return GetElement()->ElementProxySet();
-}
-
-void LayoutSVGResourceContainer::NotifyContentChanged() {
-  if (LocalSVGResource* resource = ResourceForContainer(*this))
-    resource->NotifyContentChanged();
-  if (SVGElementProxySet* proxy_set = ElementProxySet())
-    proxy_set->NotifyContentChanged(GetElement()->GetTreeScope());
-}
-
 void LayoutSVGResourceContainer::WillBeDestroyed() {
   LayoutSVGHiddenContainer::WillBeDestroyed();
   // The resource is being torn down. If we have any clients, move those to be
@@ -117,9 +105,7 @@
   if (is_invalidating_)
     return;
   LocalSVGResource* resource = ResourceForContainer(*this);
-  SVGElementProxySet* proxy_set = ElementProxySet();
-  if (clients_.IsEmpty() && (!proxy_set || proxy_set->IsEmpty()) &&
-      (!resource || !resource->HasClients()))
+  if (clients_.IsEmpty() && (!resource || !resource->HasClients()))
     return;
   // Remove modes for which invalidations have already been
   // performed. If no modes remain we are done.
@@ -147,8 +133,9 @@
     MarkForLayoutAndParentResourceInvalidation(*client, needs_layout);
   }
 
-  // Invalidate clients registered via an SVGElementProxy/SVGResource.
-  NotifyContentChanged();
+  // Invalidate clients registered via an SVGResource.
+  if (resource)
+    resource->NotifyContentChanged();
 
   is_invalidating_ = false;
 }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
index ed3170a..4fcefdc7 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
@@ -25,7 +25,6 @@
 namespace blink {
 
 class LocalSVGResource;
-class SVGElementProxySet;
 
 enum LayoutSVGResourceType {
   kMaskerResourceType,
@@ -93,9 +92,6 @@
   // Used from RemoveAllClientsFromCache methods.
   void MarkAllClientsForInvalidation(InvalidationModeMask);
 
-  void NotifyContentChanged();
-  SVGElementProxySet* ElementProxySet();
-
   void WillBeDestroyed() override;
 
   bool is_in_layout_;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
index 914743c..996dd3884 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
@@ -25,6 +25,7 @@
 
 #include "core/svg/SVGFilterElement.h"
 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
+#include "core/svg/SVGResource.h"
 #include "core/svg/graphics/filters/SVGFilterBuilder.h"
 
 namespace blink {
@@ -129,7 +130,9 @@
     // Issue paint invalidations for the image on the screen.
     MarkClientForInvalidation(*filter.key, kPaintInvalidation);
   }
-  NotifyContentChanged();
+  if (LocalSVGResource* resource =
+          ToSVGFilterElement(GetElement())->AssociatedResource())
+    resource->NotifyContentChanged();
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
index f73be70..635b7be 100644
--- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
@@ -28,9 +28,9 @@
 
 #include <algorithm>
 #include "core/style/FilterOperations.h"
-#include "core/svg/SVGElementProxy.h"
 #include "core/svg/SVGFilterElement.h"
 #include "core/svg/SVGLengthContext.h"
+#include "core/svg/SVGResource.h"
 #include "core/svg/graphics/filters/SVGFilterBuilder.h"
 #include "platform/LengthFunctions.h"
 #include "platform/graphics/CompositorFilterOperations.h"
@@ -124,19 +124,7 @@
                                          float zoom,
                                          const PaintFlags* fill_flags,
                                          const PaintFlags* stroke_flags)
-    : FilterEffectBuilder(nullptr,
-                          reference_box,
-                          zoom,
-                          fill_flags,
-                          stroke_flags) {}
-
-FilterEffectBuilder::FilterEffectBuilder(Node* target,
-                                         const FloatRect& reference_box,
-                                         float zoom,
-                                         const PaintFlags* fill_flags,
-                                         const PaintFlags* stroke_flags)
-    : target_context_(target),
-      reference_box_(reference_box),
+    : reference_box_(reference_box),
       zoom_(zoom),
       fill_flags_(fill_flags),
       stroke_flags_(stroke_flags) {}
@@ -420,10 +408,9 @@
 Filter* FilterEffectBuilder::BuildReferenceFilter(
     const ReferenceFilterOperation& reference_operation,
     FilterEffect* previous_effect) const {
-  DCHECK(target_context_);
-  Element* filter_element = reference_operation.ElementProxy().FindElement(
-      target_context_->GetTreeScope());
-  if (auto* filter = ToSVGFilterElementOrNull(filter_element))
+  SVGResource* resource = reference_operation.Resource();
+  if (auto* filter =
+          ToSVGFilterElementOrNull(resource ? resource->Target() : nullptr))
     return BuildReferenceFilter(*filter, previous_effect);
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h
index 8349dfa..72aa4b8 100644
--- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h
+++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h
@@ -39,7 +39,6 @@
 class FilterEffect;
 class FilterOperations;
 class FloatRect;
-class Node;
 class ReferenceFilterOperation;
 class SVGFilterElement;
 class SVGFilterGraphNodeMap;
@@ -52,11 +51,6 @@
                       float zoom,
                       const PaintFlags* fill_flags = nullptr,
                       const PaintFlags* stroke_flags = nullptr);
-  FilterEffectBuilder(Node*,
-                      const FloatRect& reference_box,
-                      float zoom,
-                      const PaintFlags* fill_flags = nullptr,
-                      const PaintFlags* stroke_flags = nullptr);
 
   Filter* BuildReferenceFilter(SVGFilterElement&,
                                FilterEffect* previous_effect,
@@ -71,7 +65,6 @@
   Filter* BuildReferenceFilter(const ReferenceFilterOperation&,
                                FilterEffect* previous_effect) const;
 
-  Member<Node> target_context_;
   FloatRect reference_box_;
   float zoom_;
   const PaintFlags* fill_flags_;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index dc0c2f6..18f04390 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -189,7 +189,7 @@
   if (rare_data_ && rare_data_->resource_info) {
     const ComputedStyle& style = GetLayoutObject().StyleRef();
     if (style.HasFilter())
-      style.Filter().RemoveClient(rare_data_->resource_info);
+      style.Filter().RemoveClient(*rare_data_->resource_info);
     if (IsReferenceClipPath(style.ClipPath())) {
       ToReferenceClipPathOperation(style.ClipPath())
           ->RemoveClient(*rare_data_->resource_info);
@@ -2908,15 +2908,10 @@
     return;
 
   const bool had_resource_info = ResourceInfo();
-  if (new_style.HasFilterInducingProperty()) {
-    new_style.Filter().AddClient(&EnsureResourceInfo(),
-                                 GetLayoutObject()
-                                     .GetDocument()
-                                     .GetTaskRunner(TaskType::kUnspecedLoading)
-                                     .get());
-  }
+  if (new_style.HasFilterInducingProperty())
+    new_style.Filter().AddClient(EnsureResourceInfo());
   if (had_resource_info && old_style)
-    old_style->Filter().RemoveClient(ResourceInfo());
+    old_style->Filter().RemoveClient(*ResourceInfo());
   if (PaintLayerResourceInfo* resource_info = ResourceInfo())
     resource_info->InvalidateFilterChain();
 }
@@ -3084,8 +3079,8 @@
       reference_box == operations.ReferenceBox())
     return;
 
-  operations = FilterEffectBuilder(EnclosingNode(), reference_box, zoom)
-                   .BuildFilterOperations(filter);
+  operations =
+      FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter);
 }
 
 CompositorFilterOperations
@@ -3093,7 +3088,7 @@
   const auto& style = GetLayoutObject().StyleRef();
   float zoom = style.EffectiveZoom();
   FloatRect reference_box = FilterReferenceBox(style.BackdropFilter(), zoom);
-  return FilterEffectBuilder(EnclosingNode(), reference_box, zoom)
+  return FilterEffectBuilder(reference_box, zoom)
       .BuildFilterOperations(style.BackdropFilter());
 }
 
@@ -3148,8 +3143,7 @@
 
   const auto& style = GetLayoutObject().StyleRef();
   float zoom = style.EffectiveZoom();
-  FilterEffectBuilder builder(EnclosingNode(),
-                              FilterReferenceBox(style.Filter(), zoom), zoom);
+  FilterEffectBuilder builder(FilterReferenceBox(style.Filter(), zoom), zoom);
   resource_info->SetLastEffect(
       builder.BuildFilterEffect(FilterOperationsIncludingReflection()));
   return resource_info->LastEffect();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
index 07950084..44571167 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
@@ -41,12 +41,6 @@
   DCHECK(!layer_);
 }
 
-TreeScope* PaintLayerResourceInfo::GetTreeScope() {
-  DCHECK(layer_);
-  Node* node = layer_->GetLayoutObject().GetNode();
-  return node ? &node->GetTreeScope() : nullptr;
-}
-
 void PaintLayerResourceInfo::ResourceContentChanged() {
   DCHECK(layer_);
   LayoutObject& layout_object = layer_->GetLayoutObject();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
index cdda9f7..8f05371 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
@@ -63,8 +63,6 @@
 
   void ClearLayer() { layer_ = nullptr; }
 
-  TreeScope* GetTreeScope() override;
-
   void ResourceContentChanged() override;
   void ResourceElementChanged() override;
 
diff --git a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp
index 03509b1c..4719f6f 100644
--- a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp
@@ -99,7 +99,7 @@
   }
 
   SVGFilterGraphNodeMap* node_map = SVGFilterGraphNodeMap::Create();
-  FilterEffectBuilder builder(nullptr, object.ObjectBoundingBox(), 1);
+  FilterEffectBuilder builder(object.ObjectBoundingBox(), 1);
   Filter* filter = builder.BuildReferenceFilter(
       ToSVGFilterElement(*filter_.GetElement()), nullptr, node_map);
   if (!filter || !filter->LastEffect())
diff --git a/third_party/WebKit/Source/core/style/FilterOperation.cpp b/third_party/WebKit/Source/core/style/FilterOperation.cpp
index 02cec41..eea10d30 100644
--- a/third_party/WebKit/Source/core/style/FilterOperation.cpp
+++ b/third_party/WebKit/Source/core/style/FilterOperation.cpp
@@ -25,7 +25,7 @@
 
 #include "core/style/FilterOperation.h"
 
-#include "core/svg/SVGElementProxy.h"
+#include "core/svg/SVGResource.h"
 #include "platform/LengthFunctions.h"
 #include "platform/animation/AnimationUtilities.h"
 #include "platform/graphics/filters/FEDropShadow.h"
@@ -45,7 +45,7 @@
 }
 
 void ReferenceFilterOperation::Trace(blink::Visitor* visitor) {
-  visitor->Trace(element_proxy_);
+  visitor->Trace(resource_);
   visitor->Trace(filter_);
   FilterOperation::Trace(visitor);
 }
@@ -57,26 +57,25 @@
   return last_effect->MapRect(rect);
 }
 
-ReferenceFilterOperation::ReferenceFilterOperation(
-    const String& url,
-    SVGElementProxy& element_proxy)
-    : FilterOperation(REFERENCE), url_(url), element_proxy_(&element_proxy) {}
+ReferenceFilterOperation::ReferenceFilterOperation(const String& url,
+                                                   SVGResource* resource)
+    : FilterOperation(REFERENCE), url_(url), resource_(resource) {}
 
-void ReferenceFilterOperation::AddClient(
-    SVGResourceClient* client,
-    base::SingleThreadTaskRunner* task_runner) {
-  element_proxy_->AddClient(client, task_runner);
+void ReferenceFilterOperation::AddClient(SVGResourceClient& client) {
+  if (resource_)
+    resource_->AddClient(client);
 }
 
-void ReferenceFilterOperation::RemoveClient(SVGResourceClient* client) {
-  element_proxy_->RemoveClient(client);
+void ReferenceFilterOperation::RemoveClient(SVGResourceClient& client) {
+  if (resource_)
+    resource_->RemoveClient(client);
 }
 
 bool ReferenceFilterOperation::operator==(const FilterOperation& o) const {
   if (!IsSameType(o))
     return false;
   const ReferenceFilterOperation& other = ToReferenceFilterOperation(o);
-  return url_ == other.url_ && element_proxy_ == other.element_proxy_;
+  return url_ == other.url_ && resource_ == other.resource_;
 }
 
 FilterOperation* BasicColorMatrixFilterOperation::Blend(
diff --git a/third_party/WebKit/Source/core/style/FilterOperation.h b/third_party/WebKit/Source/core/style/FilterOperation.h
index 35c53a8..2b7fe6d 100644
--- a/third_party/WebKit/Source/core/style/FilterOperation.h
+++ b/third_party/WebKit/Source/core/style/FilterOperation.h
@@ -27,7 +27,6 @@
 #define FilterOperation_h
 
 #include "base/macros.h"
-#include "base/single_thread_task_runner.h"
 #include "core/CoreExport.h"
 #include "core/style/ShadowData.h"
 #include "platform/Length.h"
@@ -40,8 +39,8 @@
 namespace blink {
 
 class Filter;
+class SVGResource;
 class SVGResourceClient;
-class SVGElementProxy;
 
 // CSS Filters
 
@@ -132,8 +131,8 @@
 class CORE_EXPORT ReferenceFilterOperation : public FilterOperation {
  public:
   static ReferenceFilterOperation* Create(const String& url,
-                                          SVGElementProxy& element_proxy) {
-    return new ReferenceFilterOperation(url, element_proxy);
+                                          SVGResource* resource) {
+    return new ReferenceFilterOperation(url, resource);
   }
 
   bool AffectsOpacity() const override { return true; }
@@ -145,15 +144,15 @@
   Filter* GetFilter() const { return filter_.Get(); }
   void SetFilter(Filter* filter) { filter_ = filter; }
 
-  SVGElementProxy& ElementProxy() const { return *element_proxy_; }
+  SVGResource* Resource() const { return resource_; }
 
-  void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*);
-  void RemoveClient(SVGResourceClient*);
+  void AddClient(SVGResourceClient&);
+  void RemoveClient(SVGResourceClient&);
 
   virtual void Trace(blink::Visitor*);
 
  private:
-  ReferenceFilterOperation(const String& url, SVGElementProxy&);
+  ReferenceFilterOperation(const String& url, SVGResource*);
 
   FilterOperation* Blend(const FilterOperation* from,
                          double progress) const override {
@@ -164,7 +163,7 @@
   bool operator==(const FilterOperation&) const override;
 
   String url_;
-  Member<SVGElementProxy> element_proxy_;
+  Member<SVGResource> resource_;
   Member<Filter> filter_;
 };
 
diff --git a/third_party/WebKit/Source/core/style/FilterOperations.cpp b/third_party/WebKit/Source/core/style/FilterOperations.cpp
index 32d137f..0a30d49 100644
--- a/third_party/WebKit/Source/core/style/FilterOperations.cpp
+++ b/third_party/WebKit/Source/core/style/FilterOperations.cpp
@@ -104,16 +104,14 @@
   return false;
 }
 
-void FilterOperations::AddClient(
-    SVGResourceClient* client,
-    base::SingleThreadTaskRunner* task_runner) const {
+void FilterOperations::AddClient(SVGResourceClient& client) const {
   for (FilterOperation* operation : operations_) {
     if (operation->GetType() == FilterOperation::REFERENCE)
-      ToReferenceFilterOperation(*operation).AddClient(client, task_runner);
+      ToReferenceFilterOperation(*operation).AddClient(client);
   }
 }
 
-void FilterOperations::RemoveClient(SVGResourceClient* client) const {
+void FilterOperations::RemoveClient(SVGResourceClient& client) const {
   for (FilterOperation* operation : operations_) {
     if (operation->GetType() == FilterOperation::REFERENCE)
       ToReferenceFilterOperation(*operation).RemoveClient(client);
diff --git a/third_party/WebKit/Source/core/style/FilterOperations.h b/third_party/WebKit/Source/core/style/FilterOperations.h
index fdf0ca6..8adb5b0 100644
--- a/third_party/WebKit/Source/core/style/FilterOperations.h
+++ b/third_party/WebKit/Source/core/style/FilterOperations.h
@@ -71,8 +71,8 @@
 
   bool HasReferenceFilter() const;
 
-  void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*) const;
-  void RemoveClient(SVGResourceClient*) const;
+  void AddClient(SVGResourceClient&) const;
+  void RemoveClient(SVGResourceClient&) const;
 
   void Trace(blink::Visitor*);
 
diff --git a/third_party/WebKit/Source/core/svg/BUILD.gn b/third_party/WebKit/Source/core/svg/BUILD.gn
index 749f9593..669bf38 100644
--- a/third_party/WebKit/Source/core/svg/BUILD.gn
+++ b/third_party/WebKit/Source/core/svg/BUILD.gn
@@ -82,8 +82,6 @@
     "SVGDocumentExtensions.h",
     "SVGElement.cpp",
     "SVGElement.h",
-    "SVGElementProxy.cpp",
-    "SVGElementProxy.h",
     "SVGElementRareData.cpp",
     "SVGElementRareData.h",
     "SVGEllipseElement.cpp",
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 82c83e1..dbbca123 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -1244,13 +1244,6 @@
 }
 #endif  // DCHECK_IS_ON()
 
-SVGElementProxySet* SVGElement::ElementProxySet() {
-  // Limit to specific element types.
-  if (!IsSVGFilterElement(*this) && !IsSVGClipPathElement(*this))
-    return nullptr;
-  return &EnsureSVGRareData()->EnsureElementProxySet();
-}
-
 SVGElementSet* SVGElement::SetOfIncomingReferences() const {
   if (!HasSVGRareData())
     return nullptr;
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h
index 41f13787..10a1593 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -40,7 +40,6 @@
 class SubtreeLayoutScope;
 class SVGAnimatedString;
 class SVGElement;
-class SVGElementProxySet;
 class SVGElementRareData;
 class SVGPropertyBase;
 class SVGSVGElement;
@@ -171,8 +170,6 @@
 
   bool InUseShadowTree() const;
 
-  SVGElementProxySet* ElementProxySet();
-
   void AddReferenceTo(SVGElement*);
   void NotifyIncomingReferences(bool needs_layout);
   void RebuildAllIncomingReferences();
diff --git a/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp b/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp
deleted file mode 100644
index 14b8488..0000000
--- a/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp
+++ /dev/null
@@ -1,207 +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 "core/svg/SVGElementProxy.h"
-
-#include "core/dom/Document.h"
-#include "core/dom/IdTargetObserver.h"
-#include "core/svg/SVGElement.h"
-#include "core/svg/SVGResourceClient.h"
-#include "platform/loader/fetch/FetchParameters.h"
-#include "platform/loader/fetch/ResourceFetcher.h"
-#include "platform/loader/fetch/ResourceLoaderOptions.h"
-#include "platform/loader/fetch/fetch_initiator_type_names.h"
-
-namespace blink {
-
-class SVGElementProxy::IdObserver : public IdTargetObserver {
- public:
-  IdObserver(TreeScope& tree_scope, SVGElementProxy& proxy)
-      : IdTargetObserver(tree_scope.GetIdTargetObserverRegistry(), proxy.Id()),
-        tree_scope_(&tree_scope) {}
-
-  void AddClient(SVGResourceClient* client) { clients_.insert(client); }
-  bool RemoveClient(SVGResourceClient* client) {
-    return clients_.erase(client);
-  }
-  bool HasClients() const { return !clients_.IsEmpty(); }
-
-  TreeScope* GetTreeScope() const { return tree_scope_; }
-  void TransferClients(IdObserver& observer) {
-    for (const auto& client : clients_)
-      observer.clients_.insert(client.key, client.value);
-    clients_.clear();
-  }
-
-  virtual void Trace(blink::Visitor* visitor) {
-    visitor->Trace(clients_);
-    visitor->Trace(tree_scope_);
-    IdTargetObserver::Trace(visitor);
-  }
-
-  void ContentChanged() {
-    DCHECK(Lifecycle().GetState() != DocumentLifecycle::kInPrePaint &&
-           Lifecycle().GetState() != DocumentLifecycle::kInPaint);
-    HeapVector<Member<SVGResourceClient>> clients;
-    CopyToVector(clients_, clients);
-    for (SVGResourceClient* client : clients)
-      client->ResourceContentChanged();
-  }
-
- private:
-  const DocumentLifecycle& Lifecycle() const {
-    return tree_scope_->GetDocument().Lifecycle();
-  }
-  void IdTargetChanged() override {
-    DCHECK(Lifecycle().StateAllowsTreeMutations());
-    HeapVector<Member<SVGResourceClient>> clients;
-    CopyToVector(clients_, clients);
-    for (SVGResourceClient* client : clients)
-      client->ResourceElementChanged();
-  }
-  HeapHashCountedSet<Member<SVGResourceClient>> clients_;
-  Member<TreeScope> tree_scope_;
-};
-
-SVGElementProxy::SVGElementProxy(const AtomicString& id)
-    : id_(id), is_local_(true) {}
-
-SVGElementProxy::SVGElementProxy(const String& url, const AtomicString& id)
-    : id_(id), url_(url), is_local_(false) {}
-
-SVGElementProxy::~SVGElementProxy() = default;
-
-void SVGElementProxy::AddClient(SVGResourceClient* client,
-                                base::SingleThreadTaskRunner* task_runner) {
-  // An empty id will never be a valid element reference.
-  if (id_.IsEmpty())
-    return;
-  if (!is_local_) {
-    if (document_) {
-      DCHECK(!client->GetResource());
-      client->SetResource(document_, task_runner);
-    }
-    return;
-  }
-  TreeScope* client_scope = client->GetTreeScope();
-  if (!client_scope)
-    return;
-  // Ensure sure we have an observer registered for this tree scope.
-  auto& scope_observer =
-      observers_.insert(client_scope, nullptr).stored_value->value;
-  if (!scope_observer)
-    scope_observer = new IdObserver(*client_scope, *this);
-
-  auto& observer = clients_.insert(client, nullptr).stored_value->value;
-  if (!observer)
-    observer = scope_observer;
-
-  DCHECK(observer && scope_observer);
-
-  // If the client moved to a different scope, we need to unregister the old
-  // observer and transfer any clients from it before replacing it. Thus any
-  // clients that remain to be removed will be transferred to the new observer,
-  // and hence removed from it instead.
-  if (observer != scope_observer) {
-    observer->Unregister();
-    observer->TransferClients(*scope_observer);
-    observer = scope_observer;
-  }
-  observer->AddClient(client);
-}
-
-void SVGElementProxy::RemoveClient(SVGResourceClient* client) {
-  // An empty id will never be a valid element reference.
-  if (id_.IsEmpty())
-    return;
-  if (!is_local_) {
-    DCHECK_EQ(client->GetResource(), document_);
-    client->ClearResource();
-    return;
-  }
-  auto entry = clients_.find(client);
-  if (entry == clients_.end())
-    return;
-  IdObserver* observer = entry->value;
-  DCHECK(observer);
-  // If the client is not the last client in the scope, then no further action
-  // needs to be taken.
-  if (!observer->RemoveClient(client))
-    return;
-  // Unregister and drop the scope association, then drop the client.
-  if (!observer->HasClients()) {
-    observer->Unregister();
-    observers_.erase(observer->GetTreeScope());
-  }
-  clients_.erase(entry);
-}
-
-void SVGElementProxy::Resolve(Document& document) {
-  if (is_local_ || id_.IsEmpty() || url_.IsEmpty())
-    return;
-  ResourceLoaderOptions options;
-  options.initiator_info.name = FetchInitiatorTypeNames::css;
-  FetchParameters params(ResourceRequest(url_), options);
-  document_ =
-      DocumentResource::FetchSVGDocument(params, document.Fetcher(), nullptr);
-  url_ = String();
-}
-
-TreeScope* SVGElementProxy::TreeScopeForLookup(TreeScope& tree_scope) const {
-  if (is_local_)
-    return &tree_scope;
-  if (!document_)
-    return nullptr;
-  return document_->GetDocument();
-}
-
-SVGElement* SVGElementProxy::FindElement(TreeScope& tree_scope) {
-  // An empty id will never be a valid element reference.
-  if (id_.IsEmpty())
-    return nullptr;
-  TreeScope* lookup_scope = TreeScopeForLookup(tree_scope);
-  if (!lookup_scope)
-    return nullptr;
-  if (Element* target_element = lookup_scope->getElementById(id_)) {
-    SVGElementProxySet* proxy_set =
-        target_element->IsSVGElement()
-            ? ToSVGElement(target_element)->ElementProxySet()
-            : nullptr;
-    if (proxy_set) {
-      proxy_set->Add(*this);
-      return ToSVGElement(target_element);
-    }
-  }
-  return nullptr;
-}
-
-void SVGElementProxy::ContentChanged(TreeScope& tree_scope) {
-  if (auto* observer = observers_.at(&tree_scope))
-    observer->ContentChanged();
-}
-
-void SVGElementProxy::Trace(blink::Visitor* visitor) {
-  visitor->Trace(clients_);
-  visitor->Trace(observers_);
-  visitor->Trace(document_);
-}
-
-void SVGElementProxySet::Add(SVGElementProxy& element_proxy) {
-  element_proxies_.insert(&element_proxy);
-}
-
-bool SVGElementProxySet::IsEmpty() const {
-  return element_proxies_.IsEmpty();
-}
-
-void SVGElementProxySet::NotifyContentChanged(TreeScope& tree_scope) {
-  for (SVGElementProxy* proxy : element_proxies_)
-    proxy->ContentChanged(tree_scope);
-}
-
-void SVGElementProxySet::Trace(blink::Visitor* visitor) {
-  visitor->Trace(element_proxies_);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElementProxy.h b/third_party/WebKit/Source/core/svg/SVGElementProxy.h
deleted file mode 100644
index 0e286a58..0000000
--- a/third_party/WebKit/Source/core/svg/SVGElementProxy.h
+++ /dev/null
@@ -1,138 +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 SVGElementProxy_h
-#define SVGElementProxy_h
-
-#include "core/loader/resource/DocumentResource.h"
-#include "platform/heap/Handle.h"
-#include "platform/wtf/text/AtomicString.h"
-#include "platform/wtf/text/WTFString.h"
-
-namespace blink {
-
-class Document;
-class SVGElement;
-class SVGResourceClient;
-class TreeScope;
-
-// A proxy to an SVGElement. Allows access to an element with a certain 'id',
-// and provides its clients with notifications when the proxied element
-// changes.
-//
-// SVGElements can be referenced using CSS, for example like:
-//
-//   filter: url(#baz);
-//
-//    or
-//
-//   filter: url(foo.com/bar.svg#baz);
-//
-// SVGElementProxy provide a mechanism to persistently reference an SVGElement
-// in such cases - regardless of if the proxied element reside in the same
-// document (read: tree scope) or in an external (resource) document. Loading
-// events related to external documents case needs be handled by the clients
-// (SVGResourceClient's default implementation does this.)
-//
-// The proxy uses an 'id' (c.f getElementById) to determine which element to
-// proxy. The id is looked up in the TreeScope provided by the client for a
-// same-document reference and in the TreeScope of the Document for a external
-// document reference.
-//
-// For same document references, the proxy will track changes that could affect
-// the 'id' lookup, to handle elements being added, removed or having their
-// 'id' mutated. (This does not apply for the external document case because
-// it's assumed they will not mutate after load, due to scripts not being run
-// etc.)
-//
-// SVGElementProxys are created by CSSURIValue, and have SVGResourceClients as
-// a means to deliver change notifications. Clients that are interested in
-// change notifications hence need to register a SVGResourceClient with the
-// proxy. Most commonly this registration would take place when the
-// ComputedStyle changes.
-//
-// Registration of a client does not establish a link to the proxied element
-// right away. That is instead deferred until findElement(...) is called on the
-// SVGElementProxy. At this point, the proxy will be registered with the
-// element if the lookup is successful. (For external references lookups will
-// not be registered, per the same assumption as mentioned above.)
-//
-// As content is mutated, clients will get notified via the proxied element
-// which in turn will notify all registered proxies, which will notify all
-// registered clients.
-//
-// <event> -> SVG...Element -> SVGElementProxy(0..N) -> SVGResourceClient(0..N)
-//
-class SVGElementProxy : public GarbageCollectedFinalized<SVGElementProxy> {
- public:
-  // Create a proxy to an element in the same document. (See also
-  // SVGURLReferenceResolver and the definition of 'local url'.)
-  static SVGElementProxy* Create(const AtomicString& id) {
-    return new SVGElementProxy(id);
-  }
-
-  // Create a proxy to an element in a different document (indicated by |url|.)
-  static SVGElementProxy* Create(const String& url, const AtomicString& id) {
-    return new SVGElementProxy(url, id);
-  }
-  virtual ~SVGElementProxy();
-
-  void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*);
-  void RemoveClient(SVGResourceClient*);
-
-  // Resolve a potentially external document reference.
-  void Resolve(Document&);
-
-  // Returns the proxied element, or null if the proxy is invalid.
-  SVGElement* FindElement(TreeScope&);
-
-  // Notify the proxy that the structure of the subtree rooted at the proxied
-  // element has mutated. This should generally only be called via a proxy set.
-  void ContentChanged(TreeScope&);
-
-  const AtomicString& Id() const { return id_; }
-
-  virtual void Trace(blink::Visitor*);
-
- private:
-  explicit SVGElementProxy(const AtomicString&);
-  SVGElementProxy(const String&, const AtomicString&);
-
-  TreeScope* TreeScopeForLookup(TreeScope&) const;
-
-  class IdObserver;
-
-  HeapHashMap<Member<SVGResourceClient>, Member<IdObserver>> clients_;
-  HeapHashMap<Member<TreeScope>, Member<IdObserver>> observers_;
-  Member<DocumentResource> document_;
-  AtomicString id_;
-  // URL for resolving references to external resource documents. Contains an
-  // absolute URL to the resource to load. Cleared when a load has been
-  // initiated. Ignored if m_isLocal is true.
-  String url_;
-  bool is_local_;
-};
-
-// Collection of SVGElementProxys. This is hosted by elements that can be
-// subject to proxies (see SVGElement::elementProxySet), and is mainly a helper
-// for dealing with the many-to-one structure of SVGElementProxy.
-class SVGElementProxySet : public GarbageCollected<SVGElementProxySet> {
- public:
-  void Add(SVGElementProxy&);
-  bool IsEmpty() const;
-
-  // Notify proxy clients that the (content of the) proxied element has
-  // changed.
-  void NotifyContentChanged(TreeScope&);
-
-  void Trace(blink::Visitor*);
-
- private:
-  using ProxySet = HeapHashSet<WeakMember<SVGElementProxy>>;
-  ProxySet element_proxies_;
-};
-
-}  // namespace blink
-
-#endif  // SVGElementProxy_h
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
index 730147f6..53a70fe 100644
--- a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
@@ -6,7 +6,6 @@
 
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/Document.h"
-#include "core/svg/SVGElementProxy.h"
 
 namespace blink {
 
@@ -41,7 +40,6 @@
 void SVGElementRareData::Trace(blink::Visitor* visitor) {
   visitor->Trace(outgoing_references_);
   visitor->Trace(incoming_references_);
-  visitor->Trace(element_proxy_set_);
   visitor->Trace(animated_smil_style_properties_);
   visitor->Trace(element_instances_);
   visitor->Trace(corresponding_element_);
@@ -51,10 +49,4 @@
   return &animate_motion_transform_;
 }
 
-SVGElementProxySet& SVGElementRareData::EnsureElementProxySet() {
-  if (!element_proxy_set_)
-    element_proxy_set_ = new SVGElementProxySet;
-  return *element_proxy_set_;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.h b/third_party/WebKit/Source/core/svg/SVGElementRareData.h
index 967308b..060100b 100644
--- a/third_party/WebKit/Source/core/svg/SVGElementRareData.h
+++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.h
@@ -29,8 +29,6 @@
 
 namespace blink {
 
-class SVGElementProxySet;
-
 class SVGElementRareData
     : public GarbageCollectedFinalized<SVGElementRareData> {
  public:
@@ -50,8 +48,6 @@
     return incoming_references_;
   }
 
-  SVGElementProxySet& EnsureElementProxySet();
-
   HeapHashSet<WeakMember<SVGElement>>& ElementInstances() {
     return element_instances_;
   }
@@ -105,7 +101,6 @@
   SVGElementSet outgoing_references_;
   SVGElementSet incoming_references_;
   HeapHashSet<WeakMember<SVGElement>> element_instances_;
-  Member<SVGElementProxySet> element_proxy_set_;
   Member<SVGElement> corresponding_element_;
   bool instances_updates_blocked_ : 1;
   bool use_override_computed_style_ : 1;
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
index edc4439..85dfcda8 100644
--- a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
@@ -24,7 +24,8 @@
 #include "core/svg/SVGFilterElement.h"
 
 #include "core/layout/svg/LayoutSVGResourceFilter.h"
-#include "core/svg/SVGElementProxy.h"
+#include "core/svg/SVGResource.h"
+#include "core/svg/SVGTreeScopeResources.h"
 
 namespace blink {
 
@@ -103,22 +104,27 @@
   SVGElement::SvgAttributeChanged(attr_name);
 }
 
+LocalSVGResource* SVGFilterElement::AssociatedResource() const {
+  return GetTreeScope().EnsureSVGTreeScopedResources().ExistingResourceForId(
+      GetIdAttribute());
+}
+
 void SVGFilterElement::PrimitiveAttributeChanged(
     SVGFilterPrimitiveStandardAttributes& primitive,
     const QualifiedName& attribute) {
   if (LayoutObject* layout_object = GetLayoutObject()) {
     ToLayoutSVGResourceFilter(layout_object)
         ->PrimitiveAttributeChanged(primitive, attribute);
-  } else if (SVGElementProxySet* proxy_set = ElementProxySet()) {
-    proxy_set->NotifyContentChanged(GetTreeScope());
+  } else if (LocalSVGResource* resource = AssociatedResource()) {
+    resource->NotifyContentChanged();
   }
 }
 
 void SVGFilterElement::InvalidateFilterChain() {
   if (LayoutObject* layout_object = GetLayoutObject())
     ToLayoutSVGResourceFilter(layout_object)->RemoveAllClientsFromCache();
-  else if (SVGElementProxySet* proxy_set = ElementProxySet())
-    proxy_set->NotifyContentChanged(GetTreeScope());
+  else if (LocalSVGResource* resource = AssociatedResource())
+    resource->NotifyContentChanged();
 }
 
 void SVGFilterElement::ChildrenChanged(const ChildrenChange& change) {
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.h b/third_party/WebKit/Source/core/svg/SVGFilterElement.h
index c2e7f2b2..23c9a04 100644
--- a/third_party/WebKit/Source/core/svg/SVGFilterElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.h
@@ -34,6 +34,7 @@
 namespace blink {
 
 class SVGFilterPrimitiveStandardAttributes;
+class LocalSVGResource;
 
 class CORE_EXPORT SVGFilterElement final : public SVGElement,
                                            public SVGURIReference {
@@ -64,6 +65,9 @@
   // Invalidate the entire filter chain.
   void InvalidateFilterChain();
 
+  // Get the associated SVGResource object, if any.
+  LocalSVGResource* AssociatedResource() const;
+
  private:
   explicit SVGFilterElement(Document&);
 
diff --git a/third_party/WebKit/Source/core/svg/SVGGElement.h b/third_party/WebKit/Source/core/svg/SVGGElement.h
index c56302d..3b21d53 100644
--- a/third_party/WebKit/Source/core/svg/SVGGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGGElement.h
@@ -25,7 +25,7 @@
 
 namespace blink {
 
-class SVGGElement final : public SVGGraphicsElement {
+class CORE_EXPORT SVGGElement final : public SVGGraphicsElement {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.cpp b/third_party/WebKit/Source/core/svg/SVGResource.cpp
index 966036b..95b186d 100644
--- a/third_party/WebKit/Source/core/svg/SVGResource.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGResource.cpp
@@ -4,15 +4,21 @@
 
 #include "core/svg/SVGResource.h"
 
+#include "core/dom/Document.h"
 #include "core/dom/Element.h"
 #include "core/dom/IdTargetObserver.h"
 #include "core/dom/TreeScope.h"
 #include "core/layout/svg/LayoutSVGResourceContainer.h"
 #include "core/layout/svg/SVGResources.h"
 #include "core/layout/svg/SVGResourcesCache.h"
+#include "core/loader/resource/DocumentResource.h"
 #include "core/svg/SVGElement.h"
 #include "core/svg/SVGResourceClient.h"
 #include "core/svg/SVGURIReference.h"
+#include "platform/loader/fetch/FetchParameters.h"
+#include "platform/loader/fetch/ResourceFetcher.h"
+#include "platform/loader/fetch/ResourceLoaderOptions.h"
+#include "platform/loader/fetch/fetch_initiator_type_names.h"
 
 namespace blink {
 
@@ -33,6 +39,14 @@
   clients_.erase(&client);
 }
 
+void SVGResource::NotifyElementChanged() {
+  HeapVector<Member<SVGResourceClient>> clients;
+  CopyToVector(clients_, clients);
+
+  for (SVGResourceClient* client : clients)
+    client->ResourceElementChanged();
+}
+
 LayoutSVGResourceContainer* SVGResource::ResourceContainer() const {
   if (!target_)
     return nullptr;
@@ -88,14 +102,6 @@
     client->ResourceContentChanged();
 }
 
-void LocalSVGResource::NotifyElementChanged() {
-  HeapVector<Member<SVGResourceClient>> clients;
-  CopyToVector(clients_, clients);
-
-  for (SVGResourceClient* client : clients)
-    client->ResourceElementChanged();
-}
-
 void LocalSVGResource::TargetChanged(const AtomicString& id) {
   Element* new_target = tree_scope_->getElementById(id);
   if (new_target == target_)
@@ -116,4 +122,47 @@
   SVGResource::Trace(visitor);
 }
 
+ExternalSVGResource::ExternalSVGResource(const KURL& url) : url_(url) {}
+
+void ExternalSVGResource::Load(const Document& document) {
+  if (resource_document_)
+    return;
+  ResourceLoaderOptions options;
+  options.initiator_info.name = FetchInitiatorTypeNames::css;
+  FetchParameters params(ResourceRequest(url_), options);
+  resource_document_ =
+      DocumentResource::FetchSVGDocument(params, document.Fetcher(), this);
+  target_ = ResolveTarget();
+}
+
+void ExternalSVGResource::NotifyFinished(Resource*) {
+  Element* new_target = ResolveTarget();
+  if (new_target == target_)
+    return;
+  target_ = new_target;
+  NotifyElementChanged();
+}
+
+String ExternalSVGResource::DebugName() const {
+  return "ExternalSVGResource";
+}
+
+Element* ExternalSVGResource::ResolveTarget() {
+  if (!resource_document_)
+    return nullptr;
+  if (!url_.HasFragmentIdentifier())
+    return nullptr;
+  Document* external_document = resource_document_->GetDocument();
+  if (!external_document)
+    return nullptr;
+  return external_document->getElementById(
+      AtomicString(url_.FragmentIdentifier()));
+}
+
+void ExternalSVGResource::Trace(Visitor* visitor) {
+  visitor->Trace(resource_document_);
+  SVGResource::Trace(visitor);
+  ResourceClient::Trace(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.h b/third_party/WebKit/Source/core/svg/SVGResource.h
index 95fbcdd..a4d4d35 100644
--- a/third_party/WebKit/Source/core/svg/SVGResource.h
+++ b/third_party/WebKit/Source/core/svg/SVGResource.h
@@ -7,11 +7,16 @@
 
 #include "base/macros.h"
 #include "platform/heap/Handle.h"
+#include "platform/loader/fetch/ResourceClient.h"
+#include "platform/weborigin/KURL.h"
 #include "platform/wtf/HashCountedSet.h"
 #include "platform/wtf/HashSet.h"
+#include "platform/wtf/text/AtomicString.h"
 
 namespace blink {
 
+class Document;
+class DocumentResource;
 class Element;
 class IdTargetObserver;
 class LayoutSVGResourceContainer;
@@ -21,10 +26,46 @@
 
 // A class tracking a reference to an SVG resource (an element that constitutes
 // a paint server, mask, clip-path, filter et.c.)
+//
+// Elements can be referenced using CSS, for example like:
+//
+//   filter: url(#baz);                             ("local")
+//
+//    or
+//
+//   filter: url(foo.com/bar.svg#baz);              ("external")
+//
+// SVGResource provide a mechanism to persistently reference an element in such
+// cases - regardless of if the element reside in the same document (read: tree
+// scope) or in an external (resource) document. Loading events related to the
+// external documents case are handled by the SVGResource.
+//
+// For same document references, changes that could affect the 'id' lookup will
+// be tracked, to handle elements being added, removed or having their 'id'
+// mutated. (This does not apply for the external document case because it's
+// assumed they will not mutate after load, due to scripts not being run etc.)
+//
+// SVGResources are created, and managed, either by SVGTreeScopeResources
+// (local) or CSSURIValue (external), and have SVGResourceClients as a means to
+// deliver change notifications. Clients that are interested in change
+// notifications hence need to register a SVGResourceClient with the
+// SVGResource. Most commonly this registration would take place when the
+// computed style changes.
+//
+// The element is bound either when the SVGResource is created (for local
+// resources) or after the referenced resource has completed loading (for
+// external resources.)
+//
+// As content is mutated, clients will get notified via the SVGResource.
+//
+// <event> -> SVG...Element -> SVGResource -> SVGResourceClient(0..N)
+//
 class SVGResource : public GarbageCollectedFinalized<SVGResource> {
  public:
   virtual ~SVGResource();
 
+  virtual void Load(const Document&) {}
+
   Element* Target() const { return target_; }
   LayoutSVGResourceContainer* ResourceContainer() const;
 
@@ -38,6 +79,8 @@
  protected:
   SVGResource();
 
+  void NotifyElementChanged();
+
   Member<Element> target_;
   HeapHashCountedSet<Member<SVGResourceClient>> clients_;
 
@@ -64,13 +107,34 @@
 
  private:
   void TargetChanged(const AtomicString& id);
-  void NotifyElementChanged();
 
   Member<TreeScope> tree_scope_;
   Member<IdTargetObserver> id_observer_;
   HeapHashSet<Member<SVGElement>> pending_clients_;
 };
 
+// External resource reference (see SVGResource.)
+class ExternalSVGResource final : public SVGResource, private ResourceClient {
+  USING_GARBAGE_COLLECTED_MIXIN(ExternalSVGResource);
+
+ public:
+  explicit ExternalSVGResource(const KURL&);
+
+  void Load(const Document&) override;
+
+  void Trace(Visitor*) override;
+
+ private:
+  Element* ResolveTarget();
+
+  // ResourceClient implementation
+  String DebugName() const override;
+  void NotifyFinished(Resource*) override;
+
+  KURL url_;
+  Member<DocumentResource> resource_document_;
+};
+
 }  // namespace blink
 
 #endif  // SVGResource_h
diff --git a/third_party/WebKit/Source/core/svg/SVGResourceClient.h b/third_party/WebKit/Source/core/svg/SVGResourceClient.h
index a2e6be1..81e938aa 100644
--- a/third_party/WebKit/Source/core/svg/SVGResourceClient.h
+++ b/third_party/WebKit/Source/core/svg/SVGResourceClient.h
@@ -6,27 +6,19 @@
 #define SVGResourceClient_h
 
 #include "core/CoreExport.h"
-#include "core/loader/resource/DocumentResource.h"
 #include "platform/heap/Handle.h"
 
 namespace blink {
 
-class TreeScope;
-
-class CORE_EXPORT SVGResourceClient : public ResourceClient {
+class CORE_EXPORT SVGResourceClient : public GarbageCollectedMixin {
  public:
   virtual ~SVGResourceClient() = default;
 
-  virtual TreeScope* GetTreeScope() = 0;
-
   virtual void ResourceContentChanged() = 0;
   virtual void ResourceElementChanged() = 0;
 
  protected:
   SVGResourceClient() = default;
-
-  String DebugName() const override { return "SVGResourceClient"; }
-  void NotifyFinished(Resource*) override { ResourceElementChanged(); }
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 5b05957a..23157ec 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -873,17 +873,11 @@
   return nullptr;
 }
 
-bool AXObject::DispatchEventToAOMEventListeners(Event& event,
-                                                Element* target_element) {
+bool AXObject::DispatchEventToAOMEventListeners(Event& event) {
   HeapVector<Member<AccessibleNode>> event_path;
   for (AXObject* ancestor = this; ancestor;
        ancestor = ancestor->ParentObject()) {
-    Element* ancestor_element = ancestor->GetElement();
-    if (!ancestor_element)
-      continue;
-
-    AccessibleNode* ancestor_accessible_node =
-        ancestor_element->ExistingAccessibleNode();
+    AccessibleNode* ancestor_accessible_node = ancestor->GetAccessibleNode();
     if (!ancestor_accessible_node)
       continue;
 
@@ -916,13 +910,13 @@
   // AccessibleNode for the target element and create it if necessary -
   // otherwise we wouldn't be able to set the event target. However note
   // that if it didn't previously exist it won't be part of the event path.
-  if (!target_element)
-    target_element = GetElement();
-  AccessibleNode* target = nullptr;
-  if (target_element) {
-    target = target_element->accessibleNode();
-    event.SetTarget(target);
+  AccessibleNode* target = GetAccessibleNode();
+  if (!target) {
+    Element* element = GetElement();
+    if (element)
+      target = element->accessibleNode();
   }
+  event.SetTarget(target);
 
   // Capturing phase.
   event.SetEventPhase(Event::kCapturingPhase);
@@ -1133,6 +1127,7 @@
   return IsSubWidget(RoleValue()) && Restriction() != kDisabled;
 }
 
+// static
 bool AXObject::IsSubWidget(AccessibilityRole role) {
   switch (role) {
     case kCellRole:
@@ -1640,9 +1635,8 @@
   int child_count = siblings.size();
 
   for (int index = 0; index < child_count; ++index) {
-    if (siblings[index].Get() == this) {
+    if (siblings[index].Get() == this)
       return index;
-    }
   }
   return 0;
 }
@@ -2263,24 +2257,17 @@
 //
 
 bool AXObject::RequestDecrementAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event = Event::CreateCancelable(EventTypeNames::accessibledecrement);
-    if (DispatchEventToAOMEventListeners(*event, element)) {
-      return true;
-    }
-  }
+  Event* event = Event::CreateCancelable(EventTypeNames::accessibledecrement);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeDecrementAction();
 }
 
 bool AXObject::RequestClickAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event = Event::CreateCancelable(EventTypeNames::accessibleclick);
-    if (DispatchEventToAOMEventListeners(*event, element))
-      return true;
-  }
+  Event* event = Event::CreateCancelable(EventTypeNames::accessibleclick);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeClickAction();
 }
@@ -2310,23 +2297,17 @@
 }
 
 bool AXObject::RequestFocusAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event = Event::CreateCancelable(EventTypeNames::accessiblefocus);
-    if (DispatchEventToAOMEventListeners(*event, element))
-      return true;
-  }
+  Event* event = Event::CreateCancelable(EventTypeNames::accessiblefocus);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeFocusAction();
 }
 
 bool AXObject::RequestIncrementAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event = Event::CreateCancelable(EventTypeNames::accessibleincrement);
-    if (DispatchEventToAOMEventListeners(*event, element))
-      return true;
-  }
+  Event* event = Event::CreateCancelable(EventTypeNames::accessibleincrement);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeIncrementAction();
 }
@@ -2336,13 +2317,10 @@
 }
 
 bool AXObject::RequestScrollToMakeVisibleAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event =
-        Event::CreateCancelable(EventTypeNames::accessiblescrollintoview);
-    if (DispatchEventToAOMEventListeners(*event, element))
-      return true;
-  }
+  Event* event =
+      Event::CreateCancelable(EventTypeNames::accessiblescrollintoview);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeScrollToMakeVisibleAction();
 }
@@ -2369,13 +2347,9 @@
 }
 
 bool AXObject::RequestShowContextMenuAction() {
-  Element* element = GetElement();
-  if (element) {
-    Event* event =
-        Event::CreateCancelable(EventTypeNames::accessiblecontextmenu);
-    if (DispatchEventToAOMEventListeners(*event, element))
-      return true;
-  }
+  Event* event = Event::CreateCancelable(EventTypeNames::accessiblecontextmenu);
+  if (DispatchEventToAOMEventListeners(*event))
+    return true;
 
   return OnNativeShowContextMenuAction();
 }
@@ -2526,11 +2500,13 @@
   return line_count;
 }
 
+// static
 bool AXObject::IsARIAControl(AccessibilityRole aria_role) {
   return IsARIAInput(aria_role) || aria_role == kButtonRole ||
          aria_role == kComboBoxMenuButtonRole || aria_role == kSliderRole;
 }
 
+// static
 bool AXObject::IsARIAInput(AccessibilityRole aria_role) {
   return aria_role == kRadioButtonRole || aria_role == kCheckBoxRole ||
          aria_role == kTextFieldRole || aria_role == kSwitchRole ||
@@ -2757,12 +2733,14 @@
   return kButtonRole;
 }
 
+// static
 const AtomicString& AXObject::RoleName(AccessibilityRole role) {
   static const Vector<AtomicString>* role_name_vector = CreateRoleNameVector();
 
   return role_name_vector->at(role);
 }
 
+// static
 const AtomicString& AXObject::InternalRoleName(AccessibilityRole role) {
   static const Vector<AtomicString>* internal_role_name_vector =
       CreateInternalRoleNameVector();
@@ -2770,10 +2748,102 @@
   return internal_role_name_vector->at(role);
 }
 
+// static
+const AXObject* AXObject::LowestCommonAncestor(const AXObject& first,
+                                               const AXObject& second,
+                                               int* index_in_ancestor1,
+                                               int* index_in_ancestor2) {
+  *index_in_ancestor1 = -1;
+  *index_in_ancestor2 = -1;
+
+  if (first.IsDetached() || second.IsDetached())
+    return nullptr;
+
+  if (first == second)
+    return &first;
+
+  HeapVector<Member<const AXObject>> ancestors1;
+  ancestors1.push_back(&first);
+  while (ancestors1.back())
+    ancestors1.push_back(ancestors1.back()->ParentObjectUnignored());
+
+  HeapVector<Member<const AXObject>> ancestors2;
+  ancestors2.push_back(&second);
+  while (ancestors2.back())
+    ancestors2.push_back(ancestors2.back()->ParentObjectUnignored());
+
+  const AXObject* common_ancestor = nullptr;
+  while (!ancestors1.IsEmpty() && !ancestors2.IsEmpty() &&
+         ancestors1.back() == ancestors2.back()) {
+    common_ancestor = ancestors1.back();
+    ancestors1.pop_back();
+    ancestors2.pop_back();
+  }
+
+  if (common_ancestor) {
+    if (!ancestors1.IsEmpty())
+      *index_in_ancestor1 = ancestors1.back()->IndexInParent();
+    if (!ancestors2.IsEmpty())
+      *index_in_ancestor2 = ancestors2.back()->IndexInParent();
+  }
+
+  return common_ancestor;
+}
+
 VisiblePosition AXObject::VisiblePositionForIndex(int) const {
   return VisiblePosition();
 }
 
+bool operator==(const AXObject& first, const AXObject& second) {
+  if (first.IsDetached() || second.IsDetached())
+    return false;
+  if (&first == &second) {
+    DCHECK_EQ(first.AXObjectID(), second.AXObjectID());
+    return true;
+  }
+  return false;
+}
+
+bool operator!=(const AXObject& first, const AXObject& second) {
+  return !(first == second);
+}
+
+bool operator<(const AXObject& first, const AXObject& second) {
+  if (first.IsDetached() || second.IsDetached())
+    return false;
+
+  int index_in_ancestor1, index_in_ancestor2;
+  const AXObject* ancestor = AXObject::LowestCommonAncestor(
+      first, second, &index_in_ancestor1, &index_in_ancestor2);
+  DCHECK_GE(index_in_ancestor1, -1);
+  DCHECK_GE(index_in_ancestor2, -1);
+  if (!ancestor)
+    return false;
+  return index_in_ancestor1 < index_in_ancestor2;
+}
+
+bool operator<=(const AXObject& first, const AXObject& second) {
+  return first == second || first < second;
+}
+
+bool operator>(const AXObject& first, const AXObject& second) {
+  if (first.IsDetached() || second.IsDetached())
+    return false;
+
+  int index_in_ancestor1, index_in_ancestor2;
+  const AXObject* ancestor = AXObject::LowestCommonAncestor(
+      first, second, &index_in_ancestor1, &index_in_ancestor2);
+  DCHECK_GE(index_in_ancestor1, -1);
+  DCHECK_GE(index_in_ancestor2, -1);
+  if (!ancestor)
+    return false;
+  return index_in_ancestor1 > index_in_ancestor2;
+}
+
+bool operator>=(const AXObject& first, const AXObject& second) {
+  return first == second || first > second;
+}
+
 std::ostream& operator<<(std::ostream& stream, const AXObject& obj) {
   return stream << AXObject::InternalRoleName(obj.RoleValue()) << ": "
                 << obj.ComputedName();
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h
index 8dc2266..c2d90dc 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -766,7 +766,7 @@
   // Static helper functions.
   static bool IsARIAControl(AccessibilityRole);
   static bool IsARIAInput(AccessibilityRole);
-  // Is this a widget that requires container widget
+  // Is this a widget that requires container widget.
   static bool IsSubWidget(AccessibilityRole);
   static AccessibilityRole AriaRoleToWebCoreRole(const String&);
   static const AtomicString& RoleName(AccessibilityRole);
@@ -774,6 +774,15 @@
   static void AccessibleNodeListToElementVector(const AccessibleNodeList&,
                                                 HeapVector<Member<Element>>&);
 
+  // Given two AX objects, returns the lowest common ancestor and the child
+  // indices in that ancestor corresponding to the branch under which each
+  // object is to be found. If the lowest common ancestor is the same as either
+  // of the objects, the corresponding index is set to -1 to indicate this.
+  static const AXObject* LowestCommonAncestor(const AXObject& first,
+                                              const AXObject& second,
+                                              int* index_in_ancestor1,
+                                              int* index_in_ancestor2);
+
  protected:
   AXID id_;
   AXObjectVector children_;
@@ -828,7 +837,7 @@
   const AXObject* InertRoot() const;
 
   // Returns true if the event was handled.
-  bool DispatchEventToAOMEventListeners(Event&, Element*);
+  bool DispatchEventToAOMEventListeners(Event&);
 
   mutable Member<AXObject> parent_;
 
@@ -866,6 +875,12 @@
   DISALLOW_COPY_AND_ASSIGN(AXObject);
 };
 
+MODULES_EXPORT bool operator==(const AXObject& first, const AXObject& second);
+MODULES_EXPORT bool operator!=(const AXObject& first, const AXObject& second);
+MODULES_EXPORT bool operator<(const AXObject& first, const AXObject& second);
+MODULES_EXPORT bool operator<=(const AXObject& first, const AXObject& second);
+MODULES_EXPORT bool operator>(const AXObject& first, const AXObject& second);
+MODULES_EXPORT bool operator>=(const AXObject& first, const AXObject& second);
 MODULES_EXPORT std::ostream& operator<<(std::ostream&, const AXObject&);
 
 #define DEFINE_AX_OBJECT_TYPE_CASTS(thisType, predicate)           \
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
index c4701f5..911b73f 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
@@ -78,4 +78,46 @@
             br->PreviousSibling()->RoleValue());
 }
 
+TEST_F(AccessibilityTest, ComparisonOperators) {
+  SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>"
+                   R"<p id='paragraph'>hello<br id='br'>there</p>"
+                   R"<button id='button'>button</button>)HTML");
+
+  const AXObject* root = GetAXRootObject();
+  ASSERT_NE(nullptr, root);
+  const AXObject* input = GetAXObjectByElementId("input");
+  ASSERT_NE(nullptr, input);
+  const AXObject* paragraph = GetAXObjectByElementId("paragraph");
+  ASSERT_NE(nullptr, paragraph);
+  const AXObject* br = GetAXObjectByElementId("br");
+  ASSERT_NE(nullptr, br);
+  const AXObject* button = GetAXObjectByElementId("button");
+  ASSERT_NE(nullptr, button);
+
+  EXPECT_TRUE(*root == *root);
+  EXPECT_FALSE(*root != *root);
+  EXPECT_FALSE(*root < *root);
+  EXPECT_TRUE(*root <= *root);
+  EXPECT_FALSE(*root > *root);
+  EXPECT_TRUE(*root >= *root);
+
+  EXPECT_TRUE(*input > *root);
+  EXPECT_TRUE(*input >= *root);
+  EXPECT_FALSE(*input < *root);
+  EXPECT_FALSE(*input <= *root);
+
+  EXPECT_TRUE(*input != *root);
+  EXPECT_TRUE(*input < *paragraph);
+  EXPECT_TRUE(*br > *input);
+  EXPECT_TRUE(*paragraph < *br);
+  EXPECT_TRUE(*br >= *paragraph);
+
+  EXPECT_TRUE(*paragraph < *button);
+  EXPECT_TRUE(*button > *br);
+  EXPECT_FALSE(*button < *button);
+  EXPECT_TRUE(*button <= *button);
+  EXPECT_TRUE(*button >= *button);
+  EXPECT_FALSE(*button > *button);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp
index ed23b7d..69885bd 100644
--- a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp
@@ -61,10 +61,9 @@
 
   stream << std::string(level * 2, '+');
   stream << *root << std::endl;
-  for (const auto child : const_cast<AXObject*>(root)->Children()) {
+  for (const Member<AXObject> child : root->Children()) {
     DCHECK(child);
     PrintAXTreeHelper(stream, child.Get(), level + 1);
-    stream << std::endl;
   }
   return stream;
 }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
index 92ad1a0..b7ec51d 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
@@ -580,21 +580,15 @@
   PruneLocalFontCache(0);
 }
 
-TreeScope* CanvasRenderingContext2D::GetTreeScope() {
-  return &canvas()->GetTreeScope();
-}
-
 void CanvasRenderingContext2D::ClearFilterReferences() {
-  filter_operations_.RemoveClient(this);
+  filter_operations_.RemoveClient(*this);
   filter_operations_.clear();
 }
 
 void CanvasRenderingContext2D::UpdateFilterReferences(
     const FilterOperations& filters) {
   ClearFilterReferences();
-  filters.AddClient(
-      this,
-      canvas()->GetDocument().GetTaskRunner(TaskType::kUnspecedLoading).get());
+  filters.AddClient(*this);
   filter_operations_ = filters;
 }
 
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
index 31ffaa7e..f329a03 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
@@ -150,7 +150,6 @@
   String GetIdFromControl(const Element*) override;
 
   // SVGResourceClient implementation
-  TreeScope* GetTreeScope() override;
   void ResourceContentChanged() override;
   void ResourceElementChanged() override;
 
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp
index 3b6fdfd1..f2f1cf1 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp
@@ -352,7 +352,6 @@
     stroke_flags_for_filter.setColor(stroke_style_->PaintColor());
 
     FilterEffectBuilder filter_effect_builder(
-        style_resolution_host,
         FloatRect((FloatPoint()), FloatSize(canvas_size)),
         1.0f,  // Deliberately ignore zoom on the canvas element.
         &fill_flags_for_filter, &stroke_flags_for_filter);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
index 31e4afe..1482e9b 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
@@ -41,7 +41,6 @@
 #include "modules/EventTargetModules.h"
 #include "modules/serviceworkers/ServiceWorkerContainerClient.h"
 #include "platform/bindings/ScriptState.h"
-#include "public/platform/WebSecurityOrigin.h"
 #include "public/platform/WebString.h"
 #include "third_party/WebKit/public/mojom/service_worker/service_worker_state.mojom-blink.h"
 
@@ -78,9 +77,8 @@
     return;
   }
 
-  handle_->ServiceWorker()->PostMessage(
-      ToTransferableMessage(std::move(msg)),
-      WebSecurityOrigin(GetExecutionContext()->GetSecurityOrigin()));
+  handle_->ServiceWorker()->PostMessageToServiceWorker(
+      ToTransferableMessage(std::move(msg)));
 }
 
 ScriptPromise ServiceWorker::InternalsTerminate(ScriptState* script_state) {
diff --git a/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp b/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
index 76c98e8..03b53ac 100644
--- a/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
@@ -39,8 +39,8 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkDrawLooper.h"
+#include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 
 namespace blink {
 
@@ -93,11 +93,9 @@
 
   if (blur) {
     const SkScalar sigma = SkBlurRadiusToSigma(blur);
-    uint32_t mf_flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
-    if (shadow_transform_mode == kShadowIgnoresTransforms)
-      mf_flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
+    const bool respectCTM = shadow_transform_mode != kShadowIgnoresTransforms;
     paint->setMaskFilter(
-        SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma, mf_flags));
+        SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, respectCTM));
   }
 
   paint->setColorFilter(
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index b5b0f74c..719289b7 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -808,14 +808,14 @@
 }
 
 void ThreadHeap::WriteBarrier(const void* value) {
-  if (!value || !ThreadState::Current()->IsIncrementalMarking())
+  if (!value || !thread_state_->IsIncrementalMarking())
     return;
 
   WriteBarrierInternal(PageFromObject(value), value);
 }
 
 void ThreadHeap::WriteBarrierInternal(BasePage* page, const void* value) {
-  DCHECK(ThreadState::Current()->IsIncrementalMarking());
+  DCHECK(thread_state_->IsIncrementalMarking());
   DCHECK(page->IsIncrementalMarking());
   DCHECK(value);
   HeapObjectHeader* const header =
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
index 12182fb..e29a6a56 100644
--- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h
+++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -130,7 +130,10 @@
 
   static void BackingWriteBarrier(void* address) {
 #if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
-    ThreadState::Current()->Heap().WriteBarrier(address);
+    if (!address)
+      return;
+    ThreadState* state = PageFromObject(address)->Arena()->GetThreadState();
+    state->Heap().WriteBarrier(address);
 #endif
   }
 
@@ -171,11 +174,6 @@
     return ThreadHeap::IsHeapObjectAlive(object);
   }
 
-  template <typename VisitorDispatcher>
-  static void MarkNoTracing(VisitorDispatcher visitor, const void* t) {
-    visitor->MarkNoTracing(t);
-  }
-
   template <typename VisitorDispatcher, typename T, typename Traits>
   static void Trace(VisitorDispatcher visitor, T& t) {
     TraceCollectionIfEnabled<Traits::kWeakHandlingFlag, T, Traits>::Trace(
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h
index e8bae87..0d3c8dc 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.h
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.h
@@ -205,6 +205,7 @@
   bool IsMarked() const;
   void Mark();
   void Unmark();
+  bool TryMark();
 
   // The payload starts directly after the HeapObjectHeader, and the payload
   // size does not include the sizeof(HeapObjectHeader).
@@ -1102,6 +1103,14 @@
   encoded_ &= ~kHeaderMarkBitMask;
 }
 
+NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::TryMark() {
+  CheckHeader();
+  if (encoded_ & kHeaderMarkBitMask)
+    return false;
+  encoded_ |= kHeaderMarkBitMask;
+  return true;
+}
+
 NO_SANITIZE_ADDRESS inline bool BasePage::IsValid() const {
   return GetMagic() == magic_;
 }
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
index 4ed55c4..3273925 100644
--- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
+++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
@@ -27,21 +27,20 @@
 MarkingVisitor::~MarkingVisitor() = default;
 
 void MarkingVisitor::MarkNoTracingCallback(Visitor* visitor, void* object) {
-  // TODO(mlippautz): Remove cast;
-  reinterpret_cast<MarkingVisitor*>(visitor)->MarkNoTracing(object);
+  reinterpret_cast<MarkingVisitor*>(visitor)->MarkHeaderNoTracing(
+      HeapObjectHeader::FromPayload(object));
 }
 
 void MarkingVisitor::RegisterWeakCallback(void* closure,
                                           WeakCallback callback) {
-  DCHECK(GetMarkingMode() != kWeakProcessing);
   // We don't want to run weak processings when taking a snapshot.
-  if (GetMarkingMode() == kSnapshotMarking)
+  if (marking_mode_ == kSnapshotMarking)
     return;
   Heap().PushWeakCallback(closure, callback);
 }
 
 void MarkingVisitor::RegisterBackingStoreReference(void* slot) {
-  if (GetMarkingMode() != kGlobalMarkingWithCompaction)
+  if (marking_mode_ != kGlobalMarkingWithCompaction)
     return;
   Heap().RegisterMovingObjectReference(
       reinterpret_cast<MovableReference*>(slot));
@@ -50,7 +49,7 @@
 void MarkingVisitor::RegisterBackingStoreCallback(void* backing_store,
                                                   MovingObjectCallback callback,
                                                   void* callback_data) {
-  if (GetMarkingMode() != kGlobalMarkingWithCompaction)
+  if (marking_mode_ != kGlobalMarkingWithCompaction)
     return;
   Heap().RegisterMovingObjectCallback(
       reinterpret_cast<MovableReference>(backing_store), callback,
@@ -61,7 +60,6 @@
     const void* closure,
     EphemeronCallback iteration_callback,
     EphemeronCallback iteration_done_callback) {
-  DCHECK(GetMarkingMode() != kWeakProcessing);
   Heap().RegisterWeakTable(const_cast<void*>(closure), iteration_callback,
                            iteration_done_callback);
   return true;
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
index 7d2b146..8bb0f97 100644
--- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
+++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
@@ -21,9 +21,6 @@
     // This visitor just marks objects and ignores weak processing.
     // This is used for GCType=TakeSnapshot.
     kSnapshotMarking,
-    // This visitor is used to trace objects during weak processing.
-    // This visitor is allowed to trace only already marked objects.
-    kWeakProcessing,
     // Perform global marking along with preparing for additional sweep
     // compaction of heap arenas afterwards. Compared to the GlobalMarking
     // visitor, this visitor will also register references to objects
@@ -38,33 +35,20 @@
   MarkingVisitor(ThreadState*, MarkingMode);
   virtual ~MarkingVisitor();
 
-  inline MarkingMode GetMarkingMode() const { return marking_mode_; }
-
   // Marking implementation.
 
-  // This method marks an object and adds it to the set of objects that should
-  // have their trace method called. Since not all objects have vtables we have
-  // to have the callback as an explicit argument, but we can use the templated
-  // one-argument mark method above to automatically provide the callback
-  // function.
-  inline void Mark(const void* object_pointer, TraceCallback);
-
-  // Used to mark objects during conservative scanning.
+  // Marks an object and adds a tracing callback for processing of the object.
   inline void MarkHeader(HeapObjectHeader*, TraceCallback);
-  inline void MarkHeaderNoTracing(HeapObjectHeader*);
 
-  // Marks the header of an object. Is used for eagerly tracing of objects.
-  inline bool EnsureMarked(const void* pointer);
-
-  // Used for eagerly marking objects and for delayed marking of backing stores
-  // when the actual payload is processed differently, e.g., by weak handling.
-  inline void MarkNoTracing(const void* pointer) {
-    Mark(pointer, reinterpret_cast<TraceCallback>(0));
-  }
+  // Try to mark an object without tracing. Returns true when the object was not
+  // marked upon calling.
+  inline bool MarkHeaderNoTracing(HeapObjectHeader*);
 
   // Implementation of the visitor interface. See above for descriptions.
 
   void Visit(void* object, TraceDescriptor desc) final {
+    DCHECK(object);
+    DCHECK(desc.base_object_payload);
     // Default mark method of the trait just calls the two-argument mark
     // method on the visitor. The second argument is the static trace method
     // of the trait, which by default calls the instance method
@@ -87,13 +71,15 @@
       // that lead to many recursions.
       DCHECK(Heap().GetStackFrameDepth().IsAcceptableStackUse());
       if (LIKELY(Heap().GetStackFrameDepth().IsSafeToRecurse())) {
-        if (EnsureMarked(desc.base_object_payload)) {
+        if (MarkHeaderNoTracing(
+                HeapObjectHeader::FromPayload(desc.base_object_payload))) {
           desc.callback(this, desc.base_object_payload);
         }
         return;
       }
     }
-    Mark(desc.base_object_payload, desc.callback);
+    MarkHeader(HeapObjectHeader::FromPayload(desc.base_object_payload),
+               desc.callback);
   }
 
   void VisitBackingStoreStrongly(void* object,
@@ -112,7 +98,6 @@
   void VisitBackingStoreWeakly(void* object,
                                void** object_slot,
                                TraceDescriptor desc) final {
-    DCHECK(GetMarkingMode() != kWeakProcessing);
     RegisterBackingStoreReference(object_slot);
     Heap().PushPostMarkingCallback(object, &MarkNoTracingCallback);
   }
@@ -136,54 +121,25 @@
   const MarkingMode marking_mode_;
 };
 
+inline bool MarkingVisitor::MarkHeaderNoTracing(HeapObjectHeader* header) {
+  DCHECK(header);
+  DCHECK(State()->IsInGC() || State()->IsIncrementalMarking());
+  // A GC should only mark the objects that belong in its heap.
+  DCHECK_EQ(State(),
+            PageFromObject(header->Payload())->Arena()->GetThreadState());
+
+  return header->TryMark();
+}
+
 inline void MarkingVisitor::MarkHeader(HeapObjectHeader* header,
                                        TraceCallback callback) {
   DCHECK(header);
-  if (header->IsMarked())
-    return;
+  DCHECK(callback);
 
-  DCHECK(ThreadState::Current()->IsInGC() ||
-         ThreadState::Current()->IsIncrementalMarking());
-  DCHECK(GetMarkingMode() != kWeakProcessing);
-
-  const void* object_pointer = header->Payload();
-  // A GC should only mark the objects that belong in its heap.
-  DCHECK(&PageFromObject(object_pointer)->Arena()->GetThreadState()->Heap() ==
-         &Heap());
-
-  header->Mark();
-
-  if (callback)
-    Heap().PushTraceCallback(const_cast<void*>(object_pointer), callback);
-}
-
-inline void MarkingVisitor::Mark(const void* object_pointer,
-                                 TraceCallback callback) {
-  if (!object_pointer)
-    return;
-  HeapObjectHeader* header = HeapObjectHeader::FromPayload(object_pointer);
-  MarkHeader(header, callback);
-}
-
-inline void MarkingVisitor::MarkHeaderNoTracing(HeapObjectHeader* header) {
-  MarkHeader(header, reinterpret_cast<TraceCallback>(0));
-}
-
-inline bool MarkingVisitor::EnsureMarked(const void* object_pointer) {
-  if (!object_pointer)
-    return false;
-
-  HeapObjectHeader* header = HeapObjectHeader::FromPayload(object_pointer);
-  if (header->IsMarked())
-    return false;
-#if DCHECK_IS_ON()
-  MarkNoTracing(object_pointer);
-#else
-  // Inline what the above markNoTracing() call expands to,
-  // so as to make sure that we do get all the benefits (asserts excepted.)
-  header->Mark();
-#endif
-  return true;
+  if (MarkHeaderNoTracing(header)) {
+    Heap().PushTraceCallback(reinterpret_cast<void*>(header->Payload()),
+                             callback);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/Visitor.h b/third_party/WebKit/Source/platform/heap/Visitor.h
index 79e1d81..f2aa3cd 100644
--- a/third_party/WebKit/Source/platform/heap/Visitor.h
+++ b/third_party/WebKit/Source/platform/heap/Visitor.h
@@ -73,8 +73,8 @@
   explicit Visitor(ThreadState* state) : state_(state) {}
   virtual ~Visitor() = default;
 
-  inline ThreadState* GetState() const { return state_; }
-  inline ThreadHeap& Heap() const { return GetState()->Heap(); }
+  inline ThreadState* State() const { return state_; }
+  inline ThreadHeap& Heap() const { return state_->Heap(); }
 
   // Static visitor implementation forwarding to dynamic interface.
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index 3d97b82..509e384 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1301,8 +1301,22 @@
         """Whether a test is considered a web-platform-tests test."""
         return re.match(r'(virtual/[^/]+/)?external/wpt/', test)
 
-    def should_use_wptserve(self, test):
-        return self.is_wpt_test(test)
+    @staticmethod
+    def should_use_wptserve(test):
+        return Port.is_wpt_test(test)
+
+    @staticmethod
+    def should_run_in_wpt_mode(test):
+        """Whether content_shell should run a test in the WPT mode.
+
+        Some tests outside external/wpt should also be run in the WPT mode in
+        content_shell, namely: harness-tests/wpt/ (tests for console log
+        filtering).
+        """
+        # Note: match rules in TestInterfaces::ConfigureForTestWithURL in
+        # //src/content/shell/test_runner/test_interfaces.cc.
+        return (Port.is_wpt_test(test) or
+                re.match(r'harness-tests/wpt/', test))
 
     def start_wptserve(self):
         """Starts a WPT web server.
@@ -1814,12 +1828,19 @@
         return []
 
     def should_run_as_pixel_test(self, test_input):
+        """Whether a test should run as pixel test (when there is no reference).
+
+        This provides the *default* value for whether a test should run as
+        pixel test. When reference files exist (checked by layout_test_runner
+        before calling this method), the test always runs as pixel test.
+        """
         if not self._options.pixel_tests:
             return False
         if self._options.pixel_test_directories:
             return any(test_input.test_name.startswith(directory) for directory in self._options.pixel_test_directories)
-        # TODO(burnik): Make sure this is the right way to do it.
-        if self.should_use_wptserve(test_input.test_name):
+        if self.should_run_in_wpt_mode(test_input.test_name):
+            # WPT should not run as pixel test by default, except reftests
+            # (for which reference files would exist).
             return False
         return True
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 56c91da..9c087b63 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -38,6 +38,7 @@
 from webkitpy.common.system.system_host import SystemHost
 from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.common.path_finder import PathFinder
+from webkitpy.layout_tests.models.test_input import TestInput
 from webkitpy.layout_tests.port.base import Port, VirtualTestSuite
 from webkitpy.layout_tests.port.test import add_unit_tests_to_mock_filesystem, LAYOUT_TEST_DIR, TestPort
 
@@ -586,18 +587,42 @@
         self.assertTrue(port.is_test_file(filesystem, LAYOUT_TEST_DIR + '/external/wpt_automation', 'foo.html'))
 
     def test_is_wpt_test(self):
-        port = self.make_port(with_tests=True)
-        filesystem = port.host.filesystem
-        PortTest._add_manifest_to_mock_file_system(filesystem)
+        self.assertTrue(Port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html'))
+        self.assertTrue(Port.is_wpt_test('external/wpt/html/dom/elements/global-attributes/dir_auto-EN-L.html'))
+        self.assertFalse(Port.is_wpt_test('dom/domparsing/namespaces-1.html'))
+        self.assertFalse(Port.is_wpt_test('rutabaga'))
 
-        self.assertTrue(port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html'))
-        self.assertTrue(port.is_wpt_test('external/wpt/html/dom/elements/global-attributes/dir_auto-EN-L.html'))
-        self.assertFalse(port.is_wpt_test('dom/domparsing/namespaces-1.html'))
-        self.assertFalse(port.is_wpt_test('rutabaga'))
+        self.assertTrue(Port.is_wpt_test('virtual/a-name/external/wpt/baz/qux.htm'))
+        self.assertFalse(Port.is_wpt_test('virtual/external/wpt/baz/qux.htm'))
+        self.assertFalse(Port.is_wpt_test('not-virtual/a-name/external/wpt/baz/qux.htm'))
 
-        self.assertTrue(port.is_wpt_test('virtual/a-name/external/wpt/baz/qux.htm'))
-        self.assertFalse(port.is_wpt_test('virtual/external/wpt/baz/qux.htm'))
-        self.assertFalse(port.is_wpt_test('not-virtual/a-name/external/wpt/baz/qux.htm'))
+    def test_should_use_wptserve(self):
+        self.assertTrue(Port.should_use_wptserve('external/wpt/dom/interfaces.html'))
+        self.assertTrue(Port.should_use_wptserve('virtual/a-name/external/wpt/dom/interfaces.html'))
+        self.assertFalse(Port.should_use_wptserve('harness-tests/wpt/console_logging.html'))
+        self.assertFalse(Port.should_use_wptserve('dom/domparsing/namespaces-1.html'))
+
+    def test_should_run_as_pixel_test_with_no_pixel_tests_in_args(self):
+        # With the --no-pixel-tests flag, no tests should run as pixel tests.
+        options = optparse.Values({'pixel_tests': False})
+        port = self.make_port(options=options)
+        self.assertFalse(port.should_run_as_pixel_test(TestInput('fast/css/001.html')))
+
+    def test_should_run_as_pixel_test_with_pixel_test_directories(self):
+        # When --pixel-test-directory is supplied, only tests in those
+        # directories are allowed to run as pixel tests.
+        options = optparse.Values({'pixel_tests': True, 'pixel_test_directories': ['foo']})
+        port = self.make_port(options=options)
+        self.assertTrue(port.should_run_as_pixel_test(TestInput('foo/bar.html')))
+        self.assertFalse(port.should_run_as_pixel_test(TestInput('bar/baz.html')))
+
+    def test_should_run_as_pixel_test_default(self):
+        options = optparse.Values({'pixel_tests': True, 'pixel_test_directories': None})
+        port = self.make_port(options=options)
+        self.assertFalse(port.should_run_as_pixel_test(TestInput('external/wpt/dom/interfaces.html')))
+        self.assertFalse(port.should_run_as_pixel_test(TestInput('virtual/a-name/external/wpt/dom/interfaces.html')))
+        self.assertFalse(port.should_run_as_pixel_test(TestInput('harness-tests/wpt/console_logging.html')))
+        self.assertTrue(port.should_run_as_pixel_test(TestInput('fast/css/001.html')))
 
     def test_is_slow_wpt_test(self):
         port = self.make_port(with_tests=True)
diff --git a/third_party/WebKit/public/mojom/BUILD.gn b/third_party/WebKit/public/mojom/BUILD.gn
index 3ee6b12..14dc0cd 100644
--- a/third_party/WebKit/public/mojom/BUILD.gn
+++ b/third_party/WebKit/public/mojom/BUILD.gn
@@ -73,7 +73,6 @@
     ":mojom_platform",
     "//skia/public/interfaces",
     "//url/mojom:url_mojom_gurl",
-    "//url/mojom:url_mojom_origin",
   ]
 
   overridden_deps_blink = [ ":mojom_platform" ]
diff --git a/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom b/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom
index d7a07cd..a83d183c7 100644
--- a/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom
+++ b/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom
@@ -6,7 +6,6 @@
 
 import "third_party/WebKit/public/mojom/message_port/message_port.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_state.mojom";
-import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 
 const int32 kInvalidServiceWorkerHandleId = -1;
@@ -38,12 +37,7 @@
 // implement ServiceWorker methods.
 interface ServiceWorkerObjectHost {
   // Corresponds to ServiceWorker#postMessage().
-  // TODO(leonhsl): Remove |source_origin| by having the browser process keep
-  // track of the origin of this endpoint at binding time. The original legacy
-  // IPC code this is converted from sent the origin in the IPC message, so it
-  // was kept as a convenience during migration to Mojo, but we should remove it
-  // now.
-  PostMessage(TransferableMessage message, url.mojom.Origin source_origin);
+  PostMessageToServiceWorker(TransferableMessage message);
 
   // Tells the browser process to terminate the service worker. Used in layout
   // tests to verify behavior when a service worker isn't running. The callback
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
index 072885d6..812807a 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
@@ -41,7 +41,6 @@
 
 namespace blink {
 
-class WebSecurityOrigin;
 class WebServiceWorkerProxy;
 
 class WebServiceWorker {
@@ -70,7 +69,7 @@
     return mojom::ServiceWorkerState::kUnknown;
   }
 
-  virtual void PostMessage(TransferableMessage, const WebSecurityOrigin&) = 0;
+  virtual void PostMessageToServiceWorker(TransferableMessage) = 0;
 
   using TerminateForTestingCallback = WebCallbacks<void, void>;
   virtual void TerminateForTesting(
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h
index 4416d015..e2d195b 100644
--- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h
+++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h
@@ -42,6 +42,7 @@
 struct WebBackgroundFetchSettledFetch;
 struct WebCanMakePaymentEventData;
 class WebDataConsumerHandle;
+class WebSecurityOrigin;
 class WebServiceWorkerRequest;
 class WebString;
 struct WebNotificationData;
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index dc3244d..93e01fa 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: a8ecdbc973d969a87aaa2efffb1668efb52b799d
+Revision: c27a1aaea0861852c6d92945b68856586e0cd51d
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
@@ -37,9 +37,3 @@
 Local Modifications:
  - codereview.settings has been excluded.
  - thread_log_messages.cc (using ThreadLocalStorage::Slot instead of StaticSlot)
- - util/linux/memory_map.cc
- - util/mach/symbolic_constants_mach.cc
- - util/posix/symbolic_constants_posix.cc
- - util/stdlib/string_number_conversion.h
- - util/stdlib/string_number_conversion.cc
- - util/stdlib/string_number_conversion_test.cc
diff --git a/third_party/crashpad/crashpad/.gitignore b/third_party/crashpad/crashpad/.gitignore
index e6daaab..d225542 100644
--- a/third_party/crashpad/crashpad/.gitignore
+++ b/third_party/crashpad/crashpad/.gitignore
@@ -15,6 +15,9 @@
 /third_party/fuchsia/qemu
 /third_party/fuchsia/sdk
 /third_party/gtest/gtest
+/third_party/linux/.cipd
+/third_party/linux/clang
+/third_party/linux/sysroot
 /third_party/gyp/gyp
 /third_party/mini_chromium/mini_chromium
 /third_party/zlib/zlib
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
index 6936f9f..d118f600 100644
--- a/third_party/crashpad/crashpad/DEPS
+++ b/third_party/crashpad/crashpad/DEPS
@@ -14,6 +14,7 @@
 
 vars = {
   'chromium_git': 'https://chromium.googlesource.com',
+  'pull_linux_clang': False
 }
 
 deps = {
@@ -28,7 +29,7 @@
       '5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f',
   'crashpad/third_party/mini_chromium/mini_chromium':
       Var('chromium_git') + '/chromium/mini_chromium@' +
-      '3b953302848580cdf23b50402befc0ae09d03ff9',
+      'ef0df1119b40cfa2773d5960e239d4b960310869',
   'crashpad/third_party/zlib/zlib':
       Var('chromium_git') + '/chromium/src/third_party/zlib@' +
       '13dc246a58e4b72104d35f9b1809af95221ebda7',
@@ -115,8 +116,37 @@
   },
   {
     # This uses “cipd install” so that mac-amd64 and linux-amd64 can coexist
-    # peacefully. “cipd ensure” would remove the Linux package when running on a
-    # macOS build host and vice-versa. https://crbug.com/789364.
+    # peacefully. “cipd ensure” would remove the macOS package when running on a
+    # Linux build host and vice-versa. https://crbug.com/789364. This package is
+    # only updated when the solution in .gclient includes an entry like:
+    #   "custom_vars": { "pull_linux_clang": True }
+    'name': 'clang_linux',
+    'pattern': '.',
+    'condition': 'checkout_linux and pull_linux_clang',
+    'action': [
+      'cipd',
+      'install',
+      # sic, using Fuchsia team's generic build of clang for linux-amd64 to
+      # build for linux-amd64 target too.
+      'fuchsia/clang/linux-amd64',
+      'latest',
+      '-root', 'crashpad/third_party/linux/clang/linux-amd64',
+      '-log-level', 'info',
+    ],
+  },
+  {
+    # If using a local clang ("pull_linux_clang" above), also pull down a
+    # sysroot.
+    'name': 'clang_linux',
+    'pattern': '.',
+    'condition': 'checkout_linux and pull_linux_clang',
+    'action': [
+      'crashpad/build/install_linux_sysroot.py',
+    ],
+  },
+  {
+    # Same rationale for using "install" rather than "ensure" as for first clang
+    # package. https://crbug.com/789364.
     'name': 'fuchsia_clang_mac',
     'pattern': '.',
     'condition': 'checkout_fuchsia and host_os == "mac"',
@@ -130,9 +160,8 @@
     ],
   },
   {
-    # This uses “cipd install” so that mac-amd64 and linux-amd64 can coexist
-    # peacefully. “cipd ensure” would remove the macOS package when running on a
-    # Linux build host and vice-versa. https://crbug.com/789364.
+    # Same rationale for using "install" rather than "ensure" as for first clang
+    # package. https://crbug.com/789364.
     'name': 'fuchsia_clang_linux',
     'pattern': '.',
     'condition': 'checkout_fuchsia and host_os == "linux"',
diff --git a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn
index 67d56ae..0e6da16 100644
--- a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn
+++ b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn
@@ -35,7 +35,7 @@
 
 if (current_os == "win") {
   set_default_toolchain(
-      "//third_party/mini_chromium/mini_chromium/build:msvc_toolchain")
+      "//third_party/mini_chromium/mini_chromium/build:msvc_toolchain_$current_cpu")
 } else {
   set_default_toolchain(
       "//third_party/mini_chromium/mini_chromium/build:gcc_like_toolchain")
@@ -54,8 +54,10 @@
 ]
 
 _default_executable_configs =
-    _default_configs +
-    [ "//third_party/mini_chromium/mini_chromium/build:executable" ]
+    _default_configs + [
+      "//third_party/mini_chromium/mini_chromium/build:executable",
+      "//third_party/mini_chromium/mini_chromium/build:win_console",
+    ]
 
 set_defaults("source_set") {
   configs = _default_configs
diff --git a/third_party/crashpad/crashpad/build/install_linux_sysroot.py b/third_party/crashpad/crashpad/build/install_linux_sysroot.py
new file mode 100755
index 0000000..afa8815
--- /dev/null
+++ b/third_party/crashpad/crashpad/build/install_linux_sysroot.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+
+# Copyright 2018 The Crashpad Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Various code adapted from:
+# https://cs.chromium.org/chromium/src/build/linux/sysroot_scripts/install-sysroot.py
+
+import os
+import shutil
+import subprocess
+import sys
+import urllib2
+
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+# Sysroot revision from:
+# https://cs.chromium.org/chromium/src/build/linux/sysroot_scripts/sysroots.json
+SERVER = 'https://commondatastorage.googleapis.com'
+PATH = 'chrome-linux-sysroot/toolchain'
+REVISION = '3c248ba4290a5ad07085b7af07e6785bf1ae5b66'
+FILENAME = 'debian_stretch_amd64_sysroot.tar.xz'
+
+def main():
+  url = '%s/%s/%s/%s' % (SERVER, PATH, REVISION, FILENAME)
+
+  sysroot = os.path.join(SCRIPT_DIR, os.pardir,
+                         'third_party', 'linux', 'sysroot')
+
+  stamp = os.path.join(sysroot, '.stamp')
+  if os.path.exists(stamp):
+    with open(stamp) as s:
+      if s.read() == url:
+        return
+
+  print 'Installing Debian root image from %s' % url
+
+  if os.path.isdir(sysroot):
+    shutil.rmtree(sysroot)
+  os.mkdir(sysroot)
+  tarball = os.path.join(sysroot, FILENAME)
+  print 'Downloading %s' % url
+
+  for _ in range(3):
+    response = urllib2.urlopen(url)
+    with open(tarball, 'wb') as f:
+      f.write(response.read())
+    break
+  else:
+    raise Exception('Failed to download %s' % url)
+
+  subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot])
+
+  os.remove(tarball)
+
+  with open(stamp, 'w') as s:
+    s.write(url)
+
+
+if __name__ == '__main__':
+  main()
+  sys.exit(0)
diff --git a/third_party/crashpad/crashpad/build/run_tests.py b/third_party/crashpad/crashpad/build/run_tests.py
index 6c2dacf4..efd0aa4 100755
--- a/third_party/crashpad/crashpad/build/run_tests.py
+++ b/third_party/crashpad/crashpad/build/run_tests.py
@@ -70,10 +70,11 @@
 
   if gn_path:
     # Look for a GN “target_os”.
-    popen = subprocess.Popen(
-        [gn_path, 'args', binary_dir, '--list=target_os', '--short'],
-        shell=IS_WINDOWS_HOST, stdout=subprocess.PIPE, stderr=open(os.devnull),
-        cwd=CRASHPAD_DIR)
+    popen = subprocess.Popen([gn_path, '--root=' + CRASHPAD_DIR,
+                              'args', binary_dir,
+                              '--list=target_os', '--short'],
+                              shell=IS_WINDOWS_HOST,
+                              stdout=subprocess.PIPE, stderr=open(os.devnull))
     value = popen.communicate()[0]
     if popen.returncode == 0:
       match = re.match('target_os = "(.*)"$', value.decode('utf-8'))
@@ -310,13 +311,18 @@
 
 def _GenerateFuchsiaRuntimeDepsFiles(binary_dir, tests):
   """Ensures a <binary_dir>/<test>.runtime_deps file exists for each test."""
-  targets_file = os.path.abspath(os.path.join(binary_dir, 'targets.txt'))
+  targets_file = os.path.join(binary_dir, 'targets.txt')
   with open(targets_file, 'wb') as f:
     f.write('//:' + '\n//:'.join(tests) + '\n')
   gn_path = _FindGNFromBinaryDir(binary_dir)
   subprocess.check_call(
-      [gn_path, 'gen', binary_dir, '--runtime-deps-list-file=' + targets_file],
-      cwd=CRASHPAD_DIR)
+      [gn_path,  '--root=' + CRASHPAD_DIR, 'gen', binary_dir,
+       '--runtime-deps-list-file=' + targets_file])
+
+  # Run again so that --runtime-deps-list-file isn't in the regen rule. See
+  # https://crbug.com/814816.
+  subprocess.check_call(
+      [gn_path,  '--root=' + CRASHPAD_DIR, 'gen', binary_dir])
 
 
 def _HandleOutputFromFuchsiaLogListener(process, done_message):
@@ -373,7 +379,8 @@
     staging_root = test_root + '/pkg'
 
     # Make a staging directory tree on the target.
-    directories_to_create = [tmp_root, '%s/bin' % staging_root,
+    directories_to_create = [tmp_root,
+                             '%s/bin' % staging_root,
                              '%s/assets' % staging_root]
     netruncmd(['mkdir', '-p'] + directories_to_create)
 
@@ -396,7 +403,8 @@
           target_path = os.path.join(
               staging_root, 'bin', local_path[len(binary_dir)+1:])
       else:
-        target_path = os.path.join(staging_root, 'assets', local_path)
+        relative_path = os.path.relpath(local_path, CRASHPAD_DIR)
+        target_path = os.path.join(staging_root, 'assets', relative_path)
       netcp_path = os.path.join(sdk_root, 'tools', 'netcp')
       subprocess.check_call([netcp_path, local_path,
                              device_name + ':' + target_path],
diff --git a/third_party/crashpad/crashpad/client/BUILD.gn b/third_party/crashpad/crashpad/client/BUILD.gn
index f054e7ca..cb4161f50 100644
--- a/third_party/crashpad/crashpad/client/BUILD.gn
+++ b/third_party/crashpad/crashpad/client/BUILD.gn
@@ -36,8 +36,6 @@
 
   if (crashpad_is_mac) {
     sources += [
-      "capture_context_mac.S",
-      "capture_context_mac.h",
       "crash_report_database_mac.mm",
       "crashpad_client_mac.cc",
       "simulate_crash_mac.cc",
@@ -46,7 +44,14 @@
   }
 
   if (crashpad_is_linux || crashpad_is_android) {
-    sources += [ "crashpad_client_linux.cc" ]
+    sources += [
+      "crashpad_client_linux.cc",
+      "simulate_crash_linux.h",
+    ]
+  }
+
+  if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
+    sources += [ "crashpad_info_note.S" ]
   }
 
   if (crashpad_is_win) {
@@ -59,11 +64,14 @@
 
   if (crashpad_is_fuchsia) {
     sources += [
-      "crash_report_database_fuchsia.cc",
       "crashpad_client_fuchsia.cc",
     ]
   }
 
+  if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
+    sources += [ "crash_report_database_generic.cc" ]
+  }
+
   public_configs = [ "..:crashpad_config" ]
 
   deps = [
@@ -92,16 +100,17 @@
   ]
 
   if (crashpad_is_mac) {
-    sources += [
-      "capture_context_mac_test.cc",
-      "simulate_crash_mac_test.cc",
-    ]
+    sources += [ "simulate_crash_mac_test.cc" ]
   }
 
   if (crashpad_is_win) {
     sources += [ "crashpad_client_win_test.cc" ]
   }
 
+  if (crashpad_is_linux || crashpad_is_android) {
+    sources += [ "crashpad_client_linux_test.cc" ]
+  }
+
   deps = [
     ":client",
     "../compat",
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac.h b/third_party/crashpad/crashpad/client/capture_context_mac.h
deleted file mode 100644
index 74e440e..0000000
--- a/third_party/crashpad/crashpad/client/capture_context_mac.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
-#define CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
-
-#include <mach/mach.h>
-
-#include "build/build_config.h"
-
-namespace crashpad {
-
-#if defined(ARCH_CPU_X86_FAMILY)
-using NativeCPUContext = x86_thread_state;
-#endif
-
-//! \brief Saves the CPU context.
-//!
-//! The CPU context will be captured as accurately and completely as possible,
-//! containing an atomic snapshot at the point of this function’s return. This
-//! function does not modify any registers.
-//!
-//! \param[out] cpu_context The structure to store the context in.
-//!
-//! \note On x86_64, the value for `%%rdi` will be populated with the address of
-//!     this function’s argument, as mandated by the ABI. If the value of
-//!     `%%rdi` prior to calling this function is needed, it must be obtained
-//!     separately prior to calling this function. For example:
-//!     \code
-//!       uint64_t rdi;
-//!       asm("movq %%rdi, %0" : "=m"(rdi));
-//!     \endcode
-void CaptureContext(NativeCPUContext* cpu_context);
-
-}  // namespace crashpad
-
-#endif  // CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc b/third_party/crashpad/crashpad/client/capture_context_mac_test.cc
deleted file mode 100644
index 15640210..0000000
--- a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2014 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "client/capture_context_mac.h"
-
-#include <mach/mach.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "build/build_config.h"
-#include "gtest/gtest.h"
-#include "util/misc/address_sanitizer.h"
-#include "util/misc/implicit_cast.h"
-
-namespace crashpad {
-namespace test {
-namespace {
-
-// If the context structure has fields that tell whether it’s valid, such as
-// magic numbers or size fields, sanity-checks those fields for validity with
-// fatal gtest assertions. For other fields, where it’s possible to reason about
-// their validity based solely on their contents, sanity-checks via nonfatal
-// gtest assertions.
-void SanityCheckContext(const NativeCPUContext& context) {
-#if defined(ARCH_CPU_X86)
-  ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor),
-            implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32));
-  ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count),
-            implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT));
-#elif defined(ARCH_CPU_X86_64)
-  ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor),
-            implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64));
-  ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count),
-            implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT));
-#endif
-
-#if defined(ARCH_CPU_X86_FAMILY)
-  // The segment registers are only capable of storing 16-bit quantities, but
-  // the context structure provides native integer-width fields for them. Ensure
-  // that the high bits are all clear.
-  //
-  // Many bit positions in the flags register are reserved and will always read
-  // a known value. Most reserved bits are always 0, but bit 1 is always 1.
-  // Check that the reserved bits are all set to their expected values. Note
-  // that the set of reserved bits may be relaxed over time with newer CPUs, and
-  // that this test may need to be changed to reflect these developments. The
-  // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel
-  // Software Developer’s Manual, Volume 1: Basic Architecture (253665-051),
-  // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume
-  // 2: System Programming (24593-3.24), 3.1.6 “RFLAGS Register”.
-#if defined(ARCH_CPU_X86)
-  EXPECT_EQ(context.uts.ts32.__cs & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__ds & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__es & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__fs & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__gs & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__ss & ~0xffff, 0u);
-  EXPECT_EQ(context.uts.ts32.__eflags & 0xffc0802a, 2u);
-#elif defined(ARCH_CPU_X86_64)
-  EXPECT_EQ(context.uts.ts64.__cs & ~UINT64_C(0xffff), 0u);
-  EXPECT_EQ(context.uts.ts64.__fs & ~UINT64_C(0xffff), 0u);
-  EXPECT_EQ(context.uts.ts64.__gs & ~UINT64_C(0xffff), 0u);
-  EXPECT_EQ(context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a), 2u);
-#endif
-#endif
-}
-
-// A CPU-independent function to return the program counter.
-uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
-#if defined(ARCH_CPU_X86)
-  return context.uts.ts32.__eip;
-#elif defined(ARCH_CPU_X86_64)
-  return context.uts.ts64.__rip;
-#endif
-}
-
-// A CPU-independent function to return the stack pointer.
-uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
-#if defined(ARCH_CPU_X86)
-  return context.uts.ts32.__esp;
-#elif defined(ARCH_CPU_X86_64)
-  return context.uts.ts64.__rsp;
-#endif
-}
-
-void TestCaptureContext() {
-  NativeCPUContext context_1;
-  CaptureContext(&context_1);
-
-  {
-    SCOPED_TRACE("context_1");
-    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1));
-  }
-
-  // The program counter reference value is this function’s address. The
-  // captured program counter should be slightly greater than or equal to the
-  // reference program counter.
-  uintptr_t pc = ProgramCounterFromContext(context_1);
-
-#if !defined(ADDRESS_SANITIZER)
-  // AddressSanitizer can cause enough code bloat that the “nearby” check would
-  // likely fail.
-  const uintptr_t kReferencePC =
-      reinterpret_cast<uintptr_t>(TestCaptureContext);
-  EXPECT_LT(pc - kReferencePC, 64u);
-#endif  // !defined(ADDRESS_SANITIZER)
-
-  // Declare sp and context_2 here because all local variables need to be
-  // declared before computing the stack pointer reference value, so that the
-  // reference value can be the lowest value possible.
-  uintptr_t sp;
-  NativeCPUContext context_2;
-
-  // The stack pointer reference value is the lowest address of a local variable
-  // in this function. The captured program counter will be slightly less than
-  // or equal to the reference stack pointer.
-  const uintptr_t kReferenceSP =
-      std::min(std::min(reinterpret_cast<uintptr_t>(&context_1),
-                        reinterpret_cast<uintptr_t>(&context_2)),
-               std::min(reinterpret_cast<uintptr_t>(&pc),
-                        reinterpret_cast<uintptr_t>(&sp)));
-  sp = StackPointerFromContext(context_1);
-  EXPECT_LT(kReferenceSP - sp, 512u);
-
-  // Capture the context again, expecting that the stack pointer stays the same
-  // and the program counter increases. Strictly speaking, there’s no guarantee
-  // that these conditions will hold, although they do for known compilers even
-  // under typical optimization.
-  CaptureContext(&context_2);
-
-  {
-    SCOPED_TRACE("context_2");
-    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2));
-  }
-
-  EXPECT_EQ(StackPointerFromContext(context_2), sp);
-  EXPECT_GT(ProgramCounterFromContext(context_2), pc);
-}
-
-TEST(CaptureContextMac, CaptureContext) {
-  ASSERT_NO_FATAL_FAILURE(TestCaptureContext());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/client.gyp b/third_party/crashpad/crashpad/client/client.gyp
index f75f9c4..e149a2c 100644
--- a/third_party/crashpad/crashpad/client/client.gyp
+++ b/third_party/crashpad/crashpad/client/client.gyp
@@ -33,8 +33,6 @@
         'annotation.h',
         'annotation_list.cc',
         'annotation_list.h',
-        'capture_context_mac.S',
-        'capture_context_mac.h',
         'crash_report_database.cc',
         'crash_report_database.h',
         'crash_report_database_mac.mm',
@@ -52,6 +50,7 @@
         'simple_string_dictionary.h',
         'simple_address_range_bag.h',
         'simulate_crash.h',
+        'simulate_crash_linux.h',
         'simulate_crash_mac.cc',
         'simulate_crash_mac.h',
         'simulate_crash_win.h',
@@ -64,9 +63,18 @@
             ],
           },
         }],
-        ['OS!="mac"', {
-          'sources!': [
-            'capture_context_mac.S',
+        ['OS=="linux" or OS=="android"', {
+          'sources': [
+            'crashpad_info_note.S',
+            'crash_report_database_generic.cc',
+          ],
+        }],
+      ],
+      'target_conditions': [
+        ['OS=="android"', {
+          'sources/': [
+            ['include', '^crashpad_client_linux\\.cc$'],
+            ['include', '^simulate_crash_linux\\.h$'],
           ],
         }],
       ],
diff --git a/third_party/crashpad/crashpad/client/client_test.gyp b/third_party/crashpad/crashpad/client/client_test.gyp
index 4ea4ef2..61a4a7e 100644
--- a/third_party/crashpad/crashpad/client/client_test.gyp
+++ b/third_party/crashpad/crashpad/client/client_test.gyp
@@ -37,9 +37,9 @@
       'sources': [
         'annotation_test.cc',
         'annotation_list_test.cc',
-        'capture_context_mac_test.cc',
         'crash_report_database_test.cc',
         'crashpad_client_win_test.cc',
+        'crashpad_client_linux_test.cc',
         'prune_crash_reports_test.cc',
         'settings_test.cc',
         'simple_address_range_bag_test.cc',
@@ -53,6 +53,13 @@
           ],
         }],
       ],
+      'target_conditions': [
+        ['OS=="android"', {
+          'sources/': [
+            ['include', '^crashpad_client_linux_test\\.cc$'],
+          ],
+        }],
+      ],
     },
   ],
 }
diff --git a/third_party/crashpad/crashpad/client/crash_report_database.cc b/third_party/crashpad/crashpad/client/crash_report_database.cc
index 8451e469..afd751d 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database.cc
+++ b/third_party/crashpad/crashpad/client/crash_report_database.cc
@@ -14,6 +14,8 @@
 
 #include "client/crash_report_database.h"
 
+#include "build/build_config.h"
+
 namespace crashpad {
 
 CrashReportDatabase::Report::Report()
@@ -26,22 +28,55 @@
       upload_attempts(0),
       upload_explicitly_requested(false) {}
 
-CrashReportDatabase::CallErrorWritingCrashReport::CallErrorWritingCrashReport(
-    CrashReportDatabase* database,
-    NewReport* new_report)
-    : database_(database),
-      new_report_(new_report) {
+CrashReportDatabase::NewReport::NewReport()
+    : writer_(std::make_unique<FileWriter>()), uuid_(), file_remover_() {}
+
+CrashReportDatabase::NewReport::~NewReport() = default;
+
+bool CrashReportDatabase::NewReport::Initialize(
+    const base::FilePath& directory,
+    const base::FilePath::StringType& extension) {
+  if (!uuid_.InitializeWithNew()) {
+    return false;
+  }
+
+#if defined(OS_WIN)
+  const std::wstring uuid_string = uuid_.ToString16();
+#else
+  const std::string uuid_string = uuid_.ToString();
+#endif
+
+  const base::FilePath path = directory.Append(uuid_string + extension);
+  if (!writer_->Open(
+          path, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly)) {
+    return false;
+  }
+  file_remover_.reset(path);
+  return true;
 }
 
-CrashReportDatabase::CallErrorWritingCrashReport::
-    ~CallErrorWritingCrashReport() {
-  if (new_report_) {
-    database_->ErrorWritingCrashReport(new_report_);
+CrashReportDatabase::UploadReport::UploadReport()
+    : Report(), reader_(std::make_unique<FileReader>()), database_(nullptr) {}
+
+CrashReportDatabase::UploadReport::~UploadReport() {
+  if (database_) {
+    database_->RecordUploadAttempt(this, false, std::string());
   }
 }
 
-void CrashReportDatabase::CallErrorWritingCrashReport::Disarm() {
-  new_report_ = nullptr;
+bool CrashReportDatabase::UploadReport::Initialize(const base::FilePath path,
+                                                   CrashReportDatabase* db) {
+  database_ = db;
+  return reader_->Open(path);
+}
+
+CrashReportDatabase::OperationStatus CrashReportDatabase::RecordUploadComplete(
+    std::unique_ptr<const UploadReport> report_in,
+    const std::string& id) {
+  UploadReport* report = const_cast<UploadReport*>(report_in.get());
+
+  report->database_ = nullptr;
+  return RecordUploadAttempt(report, true, id);
 }
 
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database.h b/third_party/crashpad/crashpad/client/crash_report_database.h
index 6211789..efa7a770 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database.h
+++ b/third_party/crashpad/crashpad/client/crash_report_database.h
@@ -24,6 +24,9 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "util/file/file_io.h"
+#include "util/file/file_reader.h"
+#include "util/file/file_writer.h"
+#include "util/file/scoped_remove_file.h"
 #include "util/misc/metrics.h"
 #include "util/misc/uuid.h"
 
@@ -47,7 +50,7 @@
 //!      processed, or it was has been brought back from 'Completed' state by
 //!      user request.
 //!   3. Completed: The report has been locally processed, either by uploading
-//!      it to a collection server and calling RecordUploadAttempt(), or by
+//!      it to a collection server and calling RecordUploadComplete(), or by
 //!      calling SkipReportUpload().
 class CrashReportDatabase {
  public:
@@ -98,44 +101,57 @@
 
   //! \brief A crash report that is in the process of being written.
   //!
-  //! An instance of this struct should be created via PrepareNewCrashReport()
-  //! and destroyed with FinishedWritingCrashReport().
-  struct NewReport {
-    //! The file handle to which the report should be written.
-    FileHandle handle;
+  //! An instance of this class should be created via PrepareNewCrashReport().
+  class NewReport {
+   public:
+    NewReport();
+    ~NewReport();
+
+    //! An open FileWriter with which to write the report.
+    FileWriter* Writer() const { return writer_.get(); }
 
     //! A unique identifier by which this report will always be known to the
     //! database.
-    UUID uuid;
-
-    //! The path to the crash report being written.
-    base::FilePath path;
-  };
-
-  //! \brief A scoper to cleanly handle the interface requirement imposed by
-  //!     PrepareNewCrashReport().
-  //!
-  //! Calls ErrorWritingCrashReport() upon destruction unless disarmed by
-  //! calling Disarm(). Armed upon construction.
-  class CallErrorWritingCrashReport {
-   public:
-    //! \brief Arms the object to call ErrorWritingCrashReport() on \a database
-    //!     with an argument of \a new_report on destruction.
-    CallErrorWritingCrashReport(CrashReportDatabase* database,
-                                NewReport* new_report);
-
-    //! \brief Calls ErrorWritingCrashReport() if the object is armed.
-    ~CallErrorWritingCrashReport();
-
-    //! \brief Disarms the object so that CallErrorWritingCrashReport() will not
-    //!     be called upon destruction.
-    void Disarm();
+    const UUID& ReportID() { return uuid_; }
 
    private:
-    CrashReportDatabase* database_;  // weak
-    NewReport* new_report_;  // weak
+    friend class CrashReportDatabaseGeneric;
+    friend class CrashReportDatabaseMac;
+    friend class CrashReportDatabaseWin;
 
-    DISALLOW_COPY_AND_ASSIGN(CallErrorWritingCrashReport);
+    bool Initialize(const base::FilePath& directory,
+                    const base::FilePath::StringType& extension);
+
+    std::unique_ptr<FileWriter> writer_;
+    UUID uuid_;
+    ScopedRemoveFile file_remover_;
+
+    DISALLOW_COPY_AND_ASSIGN(NewReport);
+  };
+
+  //! \brief A crash report that is in the process of being uploaded.
+  //!
+  //! An instance of this class should be created via GetReportForUploading().
+  class UploadReport : public Report {
+   public:
+    UploadReport();
+    virtual ~UploadReport();
+
+    // An open FileReader with which to read the report.
+    FileReader* Reader() const { return reader_.get(); }
+
+   private:
+    friend class CrashReportDatabase;
+    friend class CrashReportDatabaseGeneric;
+    friend class CrashReportDatabaseMac;
+    friend class CrashReportDatabaseWin;
+
+    bool Initialize(const base::FilePath path, CrashReportDatabase* database);
+
+    std::unique_ptr<FileReader> reader_;
+    CrashReportDatabase* database_;
+
+    DISALLOW_COPY_AND_ASSIGN(UploadReport);
   };
 
   //! \brief The result code for operations performed on a database.
@@ -217,49 +233,31 @@
 
   //! \brief Creates a record of a new crash report.
   //!
-  //! Callers can then write the crash report using the file handle provided.
-  //! The caller does not own the new crash report record or its file handle,
-  //! both of which must be explicitly disposed of by calling
-  //! FinishedWritingCrashReport() or ErrorWritingCrashReport().
+  //! Callers should write the crash report using the FileWriter provided.
+  //! Callers should then call FinishedWritingCrashReport() to complete report
+  //! creation. If an error is encountered while writing the crash report, no
+  //! special action needs to be taken. If FinishedWritingCrashReport() is not
+  //! called, the report will be removed from the database when \a report is
+  //! destroyed.
   //!
-  //! To arrange to call ErrorWritingCrashReport() during any early return, use
-  //! CallErrorWritingCrashReport.
-  //!
-  //! \param[out] report A NewReport object containing a file handle to which
-  //!     the crash report data should be written. Only valid if this returns
-  //!     #kNoError. The caller must not delete the NewReport object or close
-  //!     the file handle within.
+  //! \param[out] report A NewReport object containing a FileWriter with which
+  //!     to write the report data. Only valid if this returns #kNoError.
   //!
   //! \return The operation status code.
-  virtual OperationStatus PrepareNewCrashReport(NewReport** report) = 0;
+  virtual OperationStatus PrepareNewCrashReport(
+      std::unique_ptr<NewReport>* report) = 0;
 
-  //! \brief Informs the database that a crash report has been written.
-  //!
-  //! After calling this method, the database is permitted to move and rename
-  //! the file at NewReport::path.
+  //! \brief Informs the database that a crash report has been successfully
+  //!     written.
   //!
   //! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
-  //!     NewReport object and file handle within will be invalidated as part of
-  //!     this call.
+  //!     NewReport object will be invalidated as part of this call.
   //! \param[out] uuid The UUID of this crash report.
   //!
   //! \return The operation status code.
-  virtual OperationStatus FinishedWritingCrashReport(NewReport* report,
-                                                     UUID* uuid) = 0;
-
-  //! \brief Informs the database that an error occurred while attempting to
-  //!     write a crash report, and that any resources associated with it should
-  //!     be cleaned up.
-  //!
-  //! After calling this method, the database is permitted to remove the file at
-  //! NewReport::path.
-  //!
-  //! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
-  //!     NewReport object and file handle within will be invalidated as part of
-  //!     this call.
-  //!
-  //! \return The operation status code.
-  virtual OperationStatus ErrorWritingCrashReport(NewReport* report) = 0;
+  virtual OperationStatus FinishedWritingCrashReport(
+      std::unique_ptr<NewReport> report,
+      UUID* uuid) = 0;
 
   //! \brief Returns the crash report record for the unique identifier.
   //!
@@ -288,42 +286,38 @@
   //! \return The operation status code.
   virtual OperationStatus GetCompletedReports(std::vector<Report>* reports) = 0;
 
-  //! \brief Obtains a report object for uploading to a collection server.
+  //! \brief Obtains and locks a report object for uploading to a collection
+  //!     server.
   //!
-  //! The file at Report::file_path should be uploaded by the caller, and then
-  //! the returned Report object must be disposed of via a call to
-  //! RecordUploadAttempt().
-  //!
-  //! A subsequent call to this method with the same \a uuid is illegal until
-  //! RecordUploadAttempt() has been called.
+  //! Callers should upload the crash report using the FileReader provided.
+  //! Callers should then call RecordUploadComplete() to record a successful
+  //! upload. If RecordUploadComplete() is not called, the upload attempt will
+  //! be recorded as unsuccessful and the report lock released when \a report is
+  //! destroyed.
   //!
   //! \param[in] uuid The unique identifier for the crash report record.
   //! \param[out] report A crash report record for the report to be uploaded.
-  //!     The caller does not own this object. Only valid if this returns
-  //!     #kNoError.
+  //!     Only valid if this returns #kNoError.
   //!
   //! \return The operation status code.
-  virtual OperationStatus GetReportForUploading(const UUID& uuid,
-                                                const Report** report) = 0;
+  virtual OperationStatus GetReportForUploading(
+      const UUID& uuid,
+      std::unique_ptr<const UploadReport>* report) = 0;
 
-  //! \brief Adjusts a crash report record’s metadata to account for an upload
-  //!     attempt, and updates the last upload attempt time as returned by
+  //! \brief Records a successful upload for a report and updates the last
+  //!     upload attempt time as returned by
   //!     Settings::GetLastUploadAttemptTime().
   //!
-  //! After calling this method, the database is permitted to move and rename
-  //! the file at Report::file_path.
-  //!
-  //! \param[in] report The report object obtained from
-  //!     GetReportForUploading(). This object is invalidated after this call.
-  //! \param[in] successful Whether the upload attempt was successful.
-  //! \param[in] id The identifier assigned to this crash report by the
-  //!     collection server. Must be empty if \a successful is `false`; may be
-  //!     empty if it is `true`.
+  //! \param[in] report A UploadReport object obtained from
+  //!     GetReportForUploading(). The UploadReport object will be invalidated
+  //!     and the report unlocked as part of this call.
+  //! \param[in] id The possibly empty identifier assigned to this crash report
+  //!     by the collection server.
   //!
   //! \return The operation status code.
-  virtual OperationStatus RecordUploadAttempt(const Report* report,
-                                              bool successful,
-                                              const std::string& id) = 0;
+  OperationStatus RecordUploadComplete(
+      std::unique_ptr<const UploadReport> report,
+      const std::string& id);
 
   //! \brief Moves a report from the pending state to the completed state, but
   //!     without the report being uploaded.
@@ -355,10 +349,37 @@
   //! \return The operation status code.
   virtual OperationStatus RequestUpload(const UUID& uuid) = 0;
 
+  //! \brief Cleans the database of expired lockfiles, metadata without report
+  //!     files, and report files without metadata.
+  //!
+  //! This method does nothing on the macOS and Windows implementations of the
+  //! database.
+  //!
+  //! \param[in] lockfile_ttl The number of seconds at which lockfiles or new
+  //!     report files are considered expired.
+  //! \return The number of reports cleaned.
+  virtual int CleanDatabase(time_t lockfile_ttl) { return 0; }
+
  protected:
   CrashReportDatabase() {}
 
  private:
+  //! \brief Adjusts a crash report record’s metadata to account for an upload
+  //!     attempt, and updates the last upload attempt time as returned by
+  //!     Settings::GetLastUploadAttemptTime().
+  //!
+  //! \param[in] report The report object obtained from
+  //!     GetReportForUploading().
+  //! \param[in] successful Whether the upload attempt was successful.
+  //! \param[in] id The identifier assigned to this crash report by the
+  //!     collection server. Must be empty if \a successful is `false`; may be
+  //!     empty if it is `true`.
+  //!
+  //! \return The operation status code.
+  virtual OperationStatus RecordUploadAttempt(UploadReport* report,
+                                              bool successful,
+                                              const std::string& id) = 0;
+
   DISALLOW_COPY_AND_ASSIGN(CrashReportDatabase);
 };
 
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc b/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc
deleted file mode 100644
index 0a7157c8..0000000
--- a/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "client/crash_report_database.h"
-
-#include "base/logging.h"
-
-namespace crashpad {
-
-// static
-std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
-    const base::FilePath& path) {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
-  return std::unique_ptr<CrashReportDatabase>();
-}
-
-// static
-std::unique_ptr<CrashReportDatabase>
-CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
-  return std::unique_ptr<CrashReportDatabase>();
-}
-
-}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_generic.cc b/third_party/crashpad/crashpad/client/crash_report_database_generic.cc
new file mode 100644
index 0000000..fc1d04e
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/crash_report_database_generic.cc
@@ -0,0 +1,843 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/crash_report_database.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utility>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "client/settings.h"
+#include "util/file/directory_reader.h"
+#include "util/file/filesystem.h"
+#include "util/misc/initialization_state_dcheck.h"
+
+namespace crashpad {
+
+namespace {
+
+// Reads from the current file position to EOF and returns as a string of bytes.
+bool ReadRestOfFileAsString(FileHandle handle, std::string* contents) {
+  char buffer[4096];
+  FileOperationResult rv;
+  std::string local_contents;
+  while ((rv = ReadFile(handle, buffer, sizeof(buffer))) > 0) {
+    local_contents.append(buffer, rv);
+  }
+  if (rv < 0) {
+    PLOG(ERROR) << "ReadFile";
+    return false;
+  }
+  contents->swap(local_contents);
+  return true;
+}
+
+base::FilePath ReplaceFinalExtension(
+    const base::FilePath& path,
+    const base::FilePath::StringType extension) {
+  return base::FilePath(path.RemoveFinalExtension().value() + extension);
+}
+
+using OperationStatus = CrashReportDatabase::OperationStatus;
+
+constexpr base::FilePath::CharType kSettings[] =
+    FILE_PATH_LITERAL("settings.dat");
+
+constexpr base::FilePath::CharType kCrashReportExtension[] =
+    FILE_PATH_LITERAL(".dmp");
+constexpr base::FilePath::CharType kMetadataExtension[] =
+    FILE_PATH_LITERAL(".meta");
+constexpr base::FilePath::CharType kLockExtension[] =
+    FILE_PATH_LITERAL(".lock");
+
+constexpr base::FilePath::CharType kNewDirectory[] = FILE_PATH_LITERAL("new");
+constexpr base::FilePath::CharType kPendingDirectory[] =
+    FILE_PATH_LITERAL("pending");
+constexpr base::FilePath::CharType kCompletedDirectory[] =
+    FILE_PATH_LITERAL("completed");
+
+constexpr const base::FilePath::CharType* kReportDirectories[] = {
+    kNewDirectory,
+    kPendingDirectory,
+    kCompletedDirectory,
+};
+
+enum {
+  //! \brief Corresponds to uploaded bit of the report state.
+  kAttributeUploaded = 1 << 0,
+
+  //! \brief Corresponds to upload_explicity_requested bit of the report state.
+  kAttributeUploadExplicitlyRequested = 1 << 1,
+};
+
+struct ReportMetadata {
+  static constexpr int32_t kVersion = 1;
+
+  int32_t version = kVersion;
+  int32_t upload_attempts = 0;
+  int64_t last_upload_attempt_time = 0;
+  time_t creation_time = 0;
+  uint8_t attributes = 0;
+};
+
+// A lock held while using database resources.
+class ScopedLockFile {
+ public:
+  ScopedLockFile() = default;
+  ~ScopedLockFile() = default;
+
+  ScopedLockFile& operator=(ScopedLockFile&& other) {
+    lock_file_.reset(other.lock_file_.release());
+    return *this;
+  }
+
+  // Attempt to acquire a lock for the report at report_path.
+  // Return `true` on success, otherwise `false`.
+  bool ResetAcquire(const base::FilePath& report_path) {
+    lock_file_.reset();
+
+    base::FilePath lock_path(report_path.RemoveFinalExtension().value() +
+                             kLockExtension);
+    ScopedFileHandle lock_fd(LoggingOpenFileForWrite(
+        lock_path, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly));
+    if (!lock_fd.is_valid()) {
+      return false;
+    }
+    lock_file_.reset(lock_path);
+
+    time_t timestamp = time(nullptr);
+    if (!LoggingWriteFile(lock_fd.get(), &timestamp, sizeof(timestamp))) {
+      return false;
+    }
+
+    return true;
+  }
+
+  // Returns `true` if the lock is held.
+  bool is_valid() const { return lock_file_.is_valid(); }
+
+  // Returns `true` if the lockfile at lock_path has expired.
+  static bool IsExpired(const base::FilePath& lock_path, time_t lockfile_ttl) {
+    time_t now = time(nullptr);
+
+    timespec filetime;
+    if (FileModificationTime(lock_path, &filetime) &&
+        filetime.tv_sec > now + lockfile_ttl) {
+      return false;
+    }
+
+    ScopedFileHandle lock_fd(LoggingOpenFileForReadAndWrite(
+        lock_path, FileWriteMode::kReuseOrFail, FilePermissions::kOwnerOnly));
+    if (!lock_fd.is_valid()) {
+      return false;
+    }
+
+    time_t timestamp;
+    if (!LoggingReadFileExactly(lock_fd.get(), &timestamp, sizeof(timestamp))) {
+      return false;
+    }
+
+    return now >= timestamp + lockfile_ttl;
+  }
+
+ private:
+  ScopedRemoveFile lock_file_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedLockFile);
+};
+
+}  // namespace
+
+class CrashReportDatabaseGeneric : public CrashReportDatabase {
+ public:
+  CrashReportDatabaseGeneric();
+  ~CrashReportDatabaseGeneric() override;
+
+  bool Initialize(const base::FilePath& path, bool may_create);
+
+  // CrashReportDatabase:
+  Settings* GetSettings() override;
+  OperationStatus PrepareNewCrashReport(
+      std::unique_ptr<NewReport>* report) override;
+  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
+                                             UUID* uuid) override;
+  OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override;
+  OperationStatus GetPendingReports(std::vector<Report>* reports) override;
+  OperationStatus GetCompletedReports(std::vector<Report>* reports) override;
+  OperationStatus GetReportForUploading(
+      const UUID& uuid,
+      std::unique_ptr<const UploadReport>* report) override;
+  OperationStatus SkipReportUpload(const UUID& uuid,
+                                   Metrics::CrashSkippedReason reason) override;
+  OperationStatus DeleteReport(const UUID& uuid) override;
+  OperationStatus RequestUpload(const UUID& uuid) override;
+  int CleanDatabase(time_t lockfile_ttl) override;
+
+ private:
+  struct LockfileUploadReport : public UploadReport {
+    ScopedLockFile lock_file;
+  };
+
+  enum ReportState : int32_t {
+    kUninitialized = -1,
+
+    // Being created by a caller of PrepareNewCrashReport().
+    kNew,
+
+    // Created by FinishedWritingCrashReport(), but not yet uploaded.
+    kPending,
+
+    // Upload completed or skipped.
+    kCompleted,
+
+    // Specifies either kPending or kCompleted.
+    kSearchable,
+  };
+
+  // CrashReportDatabase:
+  OperationStatus RecordUploadAttempt(UploadReport* report,
+                                      bool successful,
+                                      const std::string& id) override;
+
+  // Builds a filepath for the report with the specified uuid and state.
+  base::FilePath ReportPath(const UUID& uuid, ReportState state);
+
+  // Locates the report with id uuid and returns its file path in path and a
+  // lock for the report in lock_file. This method succeeds as long as the
+  // report file exists and the lock can be acquired. No validation is done on
+  // the existence or content of the metadata file.
+  OperationStatus LocateAndLockReport(const UUID& uuid,
+                                      ReportState state,
+                                      base::FilePath* path,
+                                      ScopedLockFile* lock_file);
+
+  // Locates, locks, and reads the metadata for the report with the specified
+  // uuid and state. This method will fail and may remove reports if invalid
+  // metadata is detected. state may be kPending, kCompleted, or kSearchable.
+  OperationStatus CheckoutReport(const UUID& uuid,
+                                 ReportState state,
+                                 base::FilePath* path,
+                                 ScopedLockFile* lock_file,
+                                 Report* report);
+
+  // Reads metadata for all reports in state and returns it in reports.
+  OperationStatus ReportsInState(ReportState state,
+                                 std::vector<Report>* reports);
+
+  // Cleans lone metadata, reports, or expired locks in a particular state.
+  int CleanReportsInState(ReportState state, time_t lockfile_ttl);
+
+  // Reads the metadata for a report from path and returns it in report.
+  static bool ReadMetadata(const base::FilePath& path, Report* report);
+
+  // Wraps ReadMetadata and removes the report from the database on failure.
+  static bool CleaningReadMetadata(const base::FilePath& path, Report* report);
+
+  // Writes metadata for a new report to the filesystem at path.
+  static bool WriteNewMetadata(const base::FilePath& path);
+
+  // Writes the metadata for report to the filesystem at path.
+  static bool WriteMetadata(const base::FilePath& path, const Report& report);
+
+  base::FilePath base_dir_;
+  Settings settings_;
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseGeneric);
+};
+
+CrashReportDatabaseGeneric::CrashReportDatabaseGeneric() = default;
+
+CrashReportDatabaseGeneric::~CrashReportDatabaseGeneric() = default;
+
+bool CrashReportDatabaseGeneric::Initialize(const base::FilePath& path,
+                                            bool may_create) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+  base_dir_ = path;
+
+  if (!IsDirectory(base_dir_, true) &&
+      !(may_create &&
+        LoggingCreateDirectory(base_dir_, FilePermissions::kOwnerOnly, true))) {
+    return false;
+  }
+
+  for (const base::FilePath::CharType* subdir : kReportDirectories) {
+    if (!LoggingCreateDirectory(base_dir_.Append(subdir),
+                                FilePermissions::kOwnerOnly,
+                                true)) {
+      return false;
+    }
+  }
+
+  if (!settings_.Initialize(base_dir_.Append(kSettings))) {
+    return false;
+  }
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+// static
+std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
+    const base::FilePath& path) {
+  auto database = std::make_unique<CrashReportDatabaseGeneric>();
+  return database->Initialize(path, true) ? std::move(database) : nullptr;
+}
+
+// static
+std::unique_ptr<CrashReportDatabase>
+CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) {
+  auto database = std::make_unique<CrashReportDatabaseGeneric>();
+  return database->Initialize(path, false) ? std::move(database) : nullptr;
+}
+
+Settings* CrashReportDatabaseGeneric::GetSettings() {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return &settings_;
+}
+
+OperationStatus CrashReportDatabaseGeneric::PrepareNewCrashReport(
+    std::unique_ptr<NewReport>* report) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  auto new_report = std::make_unique<NewReport>();
+  if (!new_report->Initialize(base_dir_.Append(kNewDirectory),
+                              kCrashReportExtension)) {
+    return kFileSystemError;
+  }
+
+  report->reset(new_report.release());
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::FinishedWritingCrashReport(
+    std::unique_ptr<NewReport> report,
+    UUID* uuid) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  base::FilePath path = ReportPath(report->ReportID(), kPending);
+  ScopedLockFile lock_file;
+  if (!lock_file.ResetAcquire(path)) {
+    return kBusyError;
+  }
+
+  if (!WriteNewMetadata(ReplaceFinalExtension(path, kMetadataExtension))) {
+    return kDatabaseError;
+  }
+
+  FileOffset size = report->Writer()->Seek(0, SEEK_END);
+
+  report->Writer()->Close();
+  if (!MoveFileOrDirectory(report->file_remover_.get(), path)) {
+    return kFileSystemError;
+  }
+  // We've moved the report to pending, so it no longer needs to be removed.
+  ignore_result(report->file_remover_.release());
+
+  *uuid = report->ReportID();
+
+  Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated);
+  Metrics::CrashReportSize(size);
+
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::LookUpCrashReport(const UUID& uuid,
+                                                              Report* report) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  ScopedLockFile lock_file;
+  base::FilePath path;
+  return CheckoutReport(uuid, kSearchable, &path, &lock_file, report);
+}
+
+OperationStatus CrashReportDatabaseGeneric::GetPendingReports(
+    std::vector<Report>* reports) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return ReportsInState(kPending, reports);
+}
+
+OperationStatus CrashReportDatabaseGeneric::GetCompletedReports(
+    std::vector<Report>* reports) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return ReportsInState(kCompleted, reports);
+}
+
+OperationStatus CrashReportDatabaseGeneric::GetReportForUploading(
+    const UUID& uuid,
+    std::unique_ptr<const UploadReport>* report) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  auto upload_report = std::make_unique<LockfileUploadReport>();
+
+  base::FilePath path;
+  OperationStatus os = CheckoutReport(
+      uuid, kPending, &path, &upload_report->lock_file, upload_report.get());
+  if (os != kNoError) {
+    return os;
+  }
+
+  if (!upload_report->Initialize(path, this)) {
+    return kFileSystemError;
+  }
+
+  report->reset(upload_report.release());
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::SkipReportUpload(
+    const UUID& uuid,
+    Metrics::CrashSkippedReason reason) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  Metrics::CrashUploadSkipped(reason);
+
+  base::FilePath path;
+  ScopedLockFile lock_file;
+  Report report;
+  OperationStatus os =
+      CheckoutReport(uuid, kPending, &path, &lock_file, &report);
+  if (os != kNoError) {
+    return os;
+  }
+
+  base::FilePath completed_path(ReportPath(uuid, kCompleted));
+  ScopedLockFile completed_lock_file;
+  if (!completed_lock_file.ResetAcquire(completed_path)) {
+    return kBusyError;
+  }
+
+  report.upload_explicitly_requested = false;
+  if (!WriteMetadata(completed_path, report)) {
+    return kDatabaseError;
+  }
+
+  if (!MoveFileOrDirectory(path, completed_path)) {
+    return kFileSystemError;
+  }
+
+  if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) {
+    return kDatabaseError;
+  }
+
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::DeleteReport(const UUID& uuid) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  base::FilePath path;
+  ScopedLockFile lock_file;
+  OperationStatus os =
+      LocateAndLockReport(uuid, kSearchable, &path, &lock_file);
+  if (os != kNoError) {
+    return os;
+  }
+
+  if (!LoggingRemoveFile(path)) {
+    return kFileSystemError;
+  }
+
+  if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) {
+    return kDatabaseError;
+  }
+
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::RequestUpload(const UUID& uuid) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  base::FilePath path;
+  ScopedLockFile lock_file;
+  Report report;
+  OperationStatus os =
+      CheckoutReport(uuid, kSearchable, &path, &lock_file, &report);
+  if (os != kNoError) {
+    return os;
+  }
+
+  if (report.uploaded) {
+    return kCannotRequestUpload;
+  }
+
+  report.upload_explicitly_requested = true;
+  base::FilePath pending_path = ReportPath(uuid, kPending);
+  if (!MoveFileOrDirectory(path, pending_path)) {
+    return kFileSystemError;
+  }
+
+  if (!WriteMetadata(pending_path, report)) {
+    return kDatabaseError;
+  }
+
+  if (pending_path != path) {
+    if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) {
+      return kDatabaseError;
+    }
+  }
+
+  Metrics::CrashReportPending(Metrics::PendingReportReason::kUserInitiated);
+  return kNoError;
+}
+
+int CrashReportDatabaseGeneric::CleanDatabase(time_t lockfile_ttl) {
+  int removed = 0;
+  time_t now = time(nullptr);
+
+  DirectoryReader reader;
+  const base::FilePath new_dir(base_dir_.Append(kNewDirectory));
+  if (reader.Open(new_dir)) {
+    base::FilePath filename;
+    DirectoryReader::Result result;
+    while ((result = reader.NextFile(&filename)) ==
+           DirectoryReader::Result::kSuccess) {
+      const base::FilePath filepath(new_dir.Append(filename));
+      timespec filetime;
+      if (!FileModificationTime(filepath, &filetime)) {
+        continue;
+      }
+      if (filetime.tv_sec <= now - lockfile_ttl) {
+        if (LoggingRemoveFile(filepath)) {
+          ++removed;
+        }
+      }
+    }
+  }
+
+  removed += CleanReportsInState(kPending, lockfile_ttl);
+  removed += CleanReportsInState(kCompleted, lockfile_ttl);
+  return removed;
+}
+
+OperationStatus CrashReportDatabaseGeneric::RecordUploadAttempt(
+    UploadReport* report,
+    bool successful,
+    const std::string& id) {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  Metrics::CrashUploadAttempted(successful);
+  time_t now = time(nullptr);
+
+  report->id = id;
+  report->uploaded = successful;
+  report->last_upload_attempt_time = now;
+  ++report->upload_attempts;
+
+  base::FilePath report_path(report->file_path);
+
+  ScopedLockFile lock_file;
+  if (successful) {
+    report->upload_explicitly_requested = false;
+
+    base::FilePath completed_report_path = ReportPath(report->uuid, kCompleted);
+
+    if (!lock_file.ResetAcquire(completed_report_path)) {
+      return kBusyError;
+    }
+
+    report->Reader()->Close();
+    if (!MoveFileOrDirectory(report_path, completed_report_path)) {
+      return kFileSystemError;
+    }
+
+    LoggingRemoveFile(ReplaceFinalExtension(report_path, kMetadataExtension));
+    report_path = completed_report_path;
+  }
+
+  if (!WriteMetadata(report_path, *report)) {
+    return kDatabaseError;
+  }
+
+  if (!settings_.SetLastUploadAttemptTime(now)) {
+    return kDatabaseError;
+  }
+
+  return kNoError;
+}
+
+base::FilePath CrashReportDatabaseGeneric::ReportPath(const UUID& uuid,
+                                                      ReportState state) {
+  DCHECK_NE(state, kUninitialized);
+  DCHECK_NE(state, kSearchable);
+
+#if defined(OS_WIN)
+  const std::wstring uuid_string = uuid.ToString16();
+#else
+  const std::string uuid_string = uuid.ToString();
+#endif
+
+  return base_dir_.Append(kReportDirectories[state])
+      .Append(uuid_string + kCrashReportExtension);
+}
+
+OperationStatus CrashReportDatabaseGeneric::LocateAndLockReport(
+    const UUID& uuid,
+    ReportState desired_state,
+    base::FilePath* path,
+    ScopedLockFile* lock_file) {
+  std::vector<ReportState> searchable_states;
+  if (desired_state == kSearchable) {
+    searchable_states.push_back(kPending);
+    searchable_states.push_back(kCompleted);
+  } else {
+    DCHECK(desired_state == kPending || desired_state == kCompleted);
+    searchable_states.push_back(desired_state);
+  }
+
+  for (const ReportState state : searchable_states) {
+    base::FilePath local_path(ReportPath(uuid, state));
+    ScopedLockFile local_lock;
+    if (!local_lock.ResetAcquire(local_path)) {
+      return kBusyError;
+    }
+
+    if (!IsRegularFile(local_path)) {
+      continue;
+    }
+
+    *path = local_path;
+    *lock_file = std::move(local_lock);
+    return kNoError;
+  }
+
+  return kReportNotFound;
+}
+
+OperationStatus CrashReportDatabaseGeneric::CheckoutReport(
+    const UUID& uuid,
+    ReportState state,
+    base::FilePath* path,
+    ScopedLockFile* lock_file,
+    Report* report) {
+  ScopedLockFile local_lock;
+  base::FilePath local_path;
+  OperationStatus os =
+      LocateAndLockReport(uuid, state, &local_path, &local_lock);
+  if (os != kNoError) {
+    return os;
+  }
+
+  if (!CleaningReadMetadata(local_path, report)) {
+    return kDatabaseError;
+  }
+
+  *path = local_path;
+  *lock_file = std::move(local_lock);
+  return kNoError;
+}
+
+OperationStatus CrashReportDatabaseGeneric::ReportsInState(
+    ReportState state,
+    std::vector<Report>* reports) {
+  DCHECK(reports->empty());
+  DCHECK_NE(state, kUninitialized);
+  DCHECK_NE(state, kSearchable);
+  DCHECK_NE(state, kNew);
+
+  const base::FilePath dir_path(base_dir_.Append(kReportDirectories[state]));
+  DirectoryReader reader;
+  if (!reader.Open(dir_path)) {
+    return kDatabaseError;
+  }
+
+  base::FilePath filename;
+  DirectoryReader::Result result;
+  while ((result = reader.NextFile(&filename)) ==
+         DirectoryReader::Result::kSuccess) {
+    const base::FilePath::StringType extension(filename.FinalExtension());
+    if (extension.compare(kCrashReportExtension) != 0) {
+      continue;
+    }
+
+    const base::FilePath filepath(dir_path.Append(filename));
+    ScopedLockFile lock_file;
+    if (!lock_file.ResetAcquire(filepath)) {
+      continue;
+    }
+
+    Report report;
+    if (!CleaningReadMetadata(filepath, &report)) {
+      continue;
+    }
+    reports->push_back(report);
+    reports->back().file_path = filepath;
+  }
+  return kNoError;
+}
+
+int CrashReportDatabaseGeneric::CleanReportsInState(ReportState state,
+                                                    time_t lockfile_ttl) {
+  const base::FilePath dir_path(base_dir_.Append(kReportDirectories[state]));
+  DirectoryReader reader;
+  if (!reader.Open(dir_path)) {
+    return 0;
+  }
+
+  int removed = 0;
+  base::FilePath filename;
+  DirectoryReader::Result result;
+  while ((result = reader.NextFile(&filename)) ==
+         DirectoryReader::Result::kSuccess) {
+    const base::FilePath::StringType extension(filename.FinalExtension());
+    const base::FilePath filepath(dir_path.Append(filename));
+
+    // Remove any report files without metadata.
+    if (extension.compare(kCrashReportExtension) == 0) {
+      const base::FilePath metadata_path(
+          ReplaceFinalExtension(filepath, kMetadataExtension));
+      ScopedLockFile report_lock;
+      if (report_lock.ResetAcquire(filepath) && !IsRegularFile(metadata_path) &&
+          LoggingRemoveFile(filepath)) {
+        ++removed;
+      }
+      continue;
+    }
+
+    // Remove any metadata files without report files.
+    if (extension.compare(kMetadataExtension) == 0) {
+      const base::FilePath report_path(
+          ReplaceFinalExtension(filepath, kCrashReportExtension));
+      ScopedLockFile report_lock;
+      if (report_lock.ResetAcquire(report_path) &&
+          !IsRegularFile(report_path) && LoggingRemoveFile(filepath)) {
+        ++removed;
+      }
+      continue;
+    }
+
+    // Remove any expired locks only if we can remove the report and metadata.
+    if (extension.compare(kLockExtension) == 0 &&
+        ScopedLockFile::IsExpired(filepath, lockfile_ttl)) {
+      const base::FilePath no_ext(filepath.RemoveFinalExtension());
+      const base::FilePath report_path(no_ext.value() + kCrashReportExtension);
+      const base::FilePath metadata_path(no_ext.value() + kMetadataExtension);
+      if ((IsRegularFile(report_path) && !LoggingRemoveFile(report_path)) ||
+          (IsRegularFile(metadata_path) && !LoggingRemoveFile(metadata_path))) {
+        continue;
+      }
+
+      if (LoggingRemoveFile(filepath)) {
+        ++removed;
+      }
+      continue;
+    }
+  }
+
+  return removed;
+}
+
+// static
+bool CrashReportDatabaseGeneric::ReadMetadata(const base::FilePath& path,
+                                              Report* report) {
+  const base::FilePath metadata_path(
+      ReplaceFinalExtension(path, kMetadataExtension));
+
+  ScopedFileHandle handle(LoggingOpenFileForRead(metadata_path));
+  if (!handle.is_valid()) {
+    return false;
+  }
+
+  if (!report->uuid.InitializeFromString(
+          path.BaseName().RemoveFinalExtension().value())) {
+    LOG(ERROR) << "Couldn't interpret report uuid";
+    return false;
+  }
+
+  ReportMetadata metadata;
+  if (!LoggingReadFileExactly(handle.get(), &metadata, sizeof(metadata))) {
+    return false;
+  }
+
+  if (metadata.version != ReportMetadata::kVersion) {
+    LOG(ERROR) << "metadata version mismatch";
+    return false;
+  }
+
+  if (!ReadRestOfFileAsString(handle.get(), &report->id)) {
+    return false;
+  }
+
+  report->upload_attempts = metadata.upload_attempts;
+  report->last_upload_attempt_time = metadata.last_upload_attempt_time;
+  report->creation_time = metadata.creation_time;
+  report->uploaded = (metadata.attributes & kAttributeUploaded) != 0;
+  report->upload_explicitly_requested =
+      (metadata.attributes & kAttributeUploadExplicitlyRequested) != 0;
+  report->file_path = path;
+  return true;
+}
+
+// static
+bool CrashReportDatabaseGeneric::CleaningReadMetadata(
+    const base::FilePath& path,
+    Report* report) {
+  if (ReadMetadata(path, report)) {
+    return true;
+  }
+
+  LoggingRemoveFile(path);
+  LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension));
+  return false;
+}
+
+// static
+bool CrashReportDatabaseGeneric::WriteNewMetadata(const base::FilePath& path) {
+  const base::FilePath metadata_path(
+      ReplaceFinalExtension(path, kMetadataExtension));
+
+  ScopedFileHandle handle(LoggingOpenFileForWrite(metadata_path,
+                                                  FileWriteMode::kCreateOrFail,
+                                                  FilePermissions::kOwnerOnly));
+  if (!handle.is_valid()) {
+    return false;
+  }
+
+  ReportMetadata metadata;
+  metadata.creation_time = time(nullptr);
+
+  return LoggingWriteFile(handle.get(), &metadata, sizeof(metadata));
+}
+
+// static
+bool CrashReportDatabaseGeneric::WriteMetadata(const base::FilePath& path,
+                                               const Report& report) {
+  const base::FilePath metadata_path(
+      ReplaceFinalExtension(path, kMetadataExtension));
+
+  ScopedFileHandle handle(
+      LoggingOpenFileForWrite(metadata_path,
+                              FileWriteMode::kTruncateOrCreate,
+                              FilePermissions::kOwnerOnly));
+  if (!handle.is_valid()) {
+    return false;
+  }
+
+  ReportMetadata metadata;
+  metadata.creation_time = report.creation_time;
+  metadata.last_upload_attempt_time = report.last_upload_attempt_time;
+  metadata.upload_attempts = report.upload_attempts;
+  metadata.attributes =
+      (report.uploaded ? kAttributeUploaded : 0) |
+      (report.upload_explicitly_requested ? kAttributeUploadExplicitlyRequested
+                                          : 0);
+
+  return LoggingWriteFile(handle.get(), &metadata, sizeof(metadata)) &&
+         LoggingWriteFile(handle.get(), report.id.c_str(), report.id.size());
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm
index 7a9154b..d0197fc 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm
+++ b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm
@@ -107,6 +107,8 @@
                             name.data());
 }
 
+}  // namespace
+
 //! \brief A CrashReportDatabase that uses HFS+ extended attributes to store
 //!     report metadata.
 //!
@@ -130,24 +132,27 @@
 
   // CrashReportDatabase:
   Settings* GetSettings() override;
-  OperationStatus PrepareNewCrashReport(NewReport** report) override;
-  OperationStatus FinishedWritingCrashReport(NewReport* report,
+  OperationStatus PrepareNewCrashReport(
+      std::unique_ptr<NewReport>* report) override;
+  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
                                              UUID* uuid) override;
-  OperationStatus ErrorWritingCrashReport(NewReport* report) override;
   OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override;
   OperationStatus GetPendingReports(std::vector<Report>* reports) override;
   OperationStatus GetCompletedReports(std::vector<Report>* reports) override;
-  OperationStatus GetReportForUploading(const UUID& uuid,
-                                        const Report** report) override;
-  OperationStatus RecordUploadAttempt(const Report* report,
-                                      bool successful,
-                                      const std::string& id) override;
+  OperationStatus GetReportForUploading(
+      const UUID& uuid,
+      std::unique_ptr<const UploadReport>* report) override;
   OperationStatus SkipReportUpload(const UUID& uuid,
                                    Metrics::CrashSkippedReason reason) override;
   OperationStatus DeleteReport(const UUID& uuid) override;
   OperationStatus RequestUpload(const UUID& uuid) override;
 
  private:
+  // CrashReportDatabase:
+  OperationStatus RecordUploadAttempt(UploadReport* report,
+                                      bool successful,
+                                      const std::string& id) override;
+
   //! \brief Report states for use with LocateCrashReport().
   //!
   //! ReportState may be considered to be a bitfield.
@@ -161,10 +166,10 @@
 
   //! \brief A private extension of the Report class that maintains bookkeeping
   //!    information of the database.
-  struct UploadReport : public Report {
+  struct UploadReportMac : public UploadReport {
     //! \brief Stores the flock of the file for the duration of
     //!     GetReportForUploading() and RecordUploadAttempt().
-    int lock_fd;
+    base::ScopedFD lock_fd;
   };
 
   //! \brief Locates a crash report in the database by UUID.
@@ -243,7 +248,7 @@
 CrashReportDatabaseMac::CrashReportDatabaseMac(const base::FilePath& path)
     : CrashReportDatabase(),
       base_dir_(path),
-      settings_(base_dir_.Append(kSettings)),
+      settings_(),
       xattr_new_names_(false),
       initialized_() {
 }
@@ -268,7 +273,7 @@
       return false;
   }
 
-  if (!settings_.Initialize())
+  if (!settings_.Initialize(base_dir_.Append(kSettings)))
     return false;
 
   // Do an xattr operation as the last step, to ensure the filesystem has
@@ -301,103 +306,67 @@
 }
 
 CrashReportDatabase::OperationStatus
-CrashReportDatabaseMac::PrepareNewCrashReport(NewReport** out_report) {
+CrashReportDatabaseMac::PrepareNewCrashReport(
+    std::unique_ptr<NewReport>* out_report) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   std::unique_ptr<NewReport> report(new NewReport());
-
-  uuid_t uuid_gen;
-  uuid_generate(uuid_gen);
-  report->uuid.InitializeFromBytes(uuid_gen);
-
-  report->path =
-      base_dir_.Append(kWriteDirectory)
-          .Append(report->uuid.ToString() + "." + kCrashReportFileExtension);
-
-  report->handle = HANDLE_EINTR(
-      open(report->path.value().c_str(),
-           O_WRONLY | O_EXLOCK | O_CREAT | O_EXCL | O_NOCTTY | O_CLOEXEC,
-           0600));
-  if (report->handle < 0) {
-    PLOG(ERROR) << "open " << report->path.value();
+  if (!report->Initialize(base_dir_.Append(kWriteDirectory),
+                          std::string(".") + kCrashReportFileExtension)) {
     return kFileSystemError;
   }
 
   // TODO(rsesek): Potentially use an fsetxattr() here instead.
-  if (!WriteXattr(
-          report->path, XattrName(kXattrUUID), report->uuid.ToString())) {
-    PLOG_IF(ERROR, IGNORE_EINTR(close(report->handle)) != 0) << "close";
+  if (!WriteXattr(report->file_remover_.get(),
+                  XattrName(kXattrUUID),
+                  report->ReportID().ToString())) {
     return kDatabaseError;
   }
 
-  *out_report = report.release();
-
+  out_report->reset(report.release());
   return kNoError;
 }
 
 CrashReportDatabase::OperationStatus
-CrashReportDatabaseMac::FinishedWritingCrashReport(NewReport* report,
-                                                   UUID* uuid) {
+CrashReportDatabaseMac::FinishedWritingCrashReport(
+    std::unique_ptr<NewReport> report,
+    UUID* uuid) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
-  // Takes ownership of the |handle| and the O_EXLOCK.
-  base::ScopedFD lock(report->handle);
-
-  // Take ownership of the report.
-  std::unique_ptr<NewReport> scoped_report(report);
+  const base::FilePath& path = report->file_remover_.get();
 
   // Get the report's UUID to return.
   std::string uuid_string;
-  if (ReadXattr(report->path, XattrName(kXattrUUID),
-                &uuid_string) != XattrStatus::kOK ||
+  if (ReadXattr(path, XattrName(kXattrUUID), &uuid_string) !=
+          XattrStatus::kOK ||
       !uuid->InitializeFromString(uuid_string)) {
-    LOG(ERROR) << "Failed to read UUID for crash report "
-               << report->path.value();
+    LOG(ERROR) << "Failed to read UUID for crash report " << path.value();
     return kDatabaseError;
   }
 
-  if (*uuid != report->uuid) {
-    LOG(ERROR) << "UUID mismatch for crash report " << report->path.value();
+  if (*uuid != report->ReportID()) {
+    LOG(ERROR) << "UUID mismatch for crash report " << path.value();
     return kDatabaseError;
   }
 
   // Record the creation time of this report.
-  if (!WriteXattrTimeT(report->path, XattrName(kXattrCreationTime),
-                       time(nullptr))) {
+  if (!WriteXattrTimeT(path, XattrName(kXattrCreationTime), time(nullptr))) {
     return kDatabaseError;
   }
 
+  FileOffset size = report->Writer()->Seek(0, SEEK_END);
+
   // Move the report to its new location for uploading.
   base::FilePath new_path =
-      base_dir_.Append(kUploadPendingDirectory).Append(report->path.BaseName());
-  if (rename(report->path.value().c_str(), new_path.value().c_str()) != 0) {
-    PLOG(ERROR) << "rename " << report->path.value() << " to "
-                << new_path.value();
+      base_dir_.Append(kUploadPendingDirectory).Append(path.BaseName());
+  if (rename(path.value().c_str(), new_path.value().c_str()) != 0) {
+    PLOG(ERROR) << "rename " << path.value() << " to " << new_path.value();
     return kFileSystemError;
   }
+  ignore_result(report->file_remover_.release());
 
   Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated);
-  Metrics::CrashReportSize(report->handle);
-
-  return kNoError;
-}
-
-CrashReportDatabase::OperationStatus
-CrashReportDatabaseMac::ErrorWritingCrashReport(NewReport* report) {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-
-  // Takes ownership of the |handle| and the O_EXLOCK.
-  base::ScopedFD lock(report->handle);
-
-  // Take ownership of the report.
-  std::unique_ptr<NewReport> scoped_report(report);
-
-  // Remove the file that the report would have been written to had no error
-  // occurred.
-  if (unlink(report->path.value().c_str()) != 0) {
-    PLOG(ERROR) << "unlink " << report->path.value();
-    return kFileSystemError;
-  }
+  Metrics::CrashReportSize(size);
 
   return kNoError;
 }
@@ -440,31 +409,36 @@
 }
 
 CrashReportDatabase::OperationStatus
-CrashReportDatabaseMac::GetReportForUploading(const UUID& uuid,
-                                              const Report** report) {
+CrashReportDatabaseMac::GetReportForUploading(
+    const UUID& uuid,
+    std::unique_ptr<const UploadReport>* report) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
-  base::FilePath report_path = LocateCrashReport(uuid, kReportStatePending);
-  if (report_path.empty())
+  auto upload_report = std::make_unique<UploadReportMac>();
+
+  upload_report->file_path = LocateCrashReport(uuid, kReportStatePending);
+  if (upload_report->file_path.empty())
     return kReportNotFound;
 
-  std::unique_ptr<UploadReport> upload_report(new UploadReport());
-  upload_report->file_path = report_path;
-
-  base::ScopedFD lock(ObtainReportLock(report_path));
+  base::ScopedFD lock(ObtainReportLock(upload_report->file_path));
   if (!lock.is_valid())
     return kBusyError;
 
-  if (!ReadReportMetadataLocked(report_path, upload_report.get()))
+  if (!ReadReportMetadataLocked(upload_report->file_path, upload_report.get()))
     return kDatabaseError;
 
-  upload_report->lock_fd = lock.release();
-  *report = upload_report.release();
+  if (!upload_report->reader_->Open(upload_report->file_path)) {
+    return kFileSystemError;
+  }
+
+  upload_report->database_ = this;
+  upload_report->lock_fd.reset(lock.release());
+  report->reset(upload_report.release());
   return kNoError;
 }
 
 CrashReportDatabase::OperationStatus
-CrashReportDatabaseMac::RecordUploadAttempt(const Report* report,
+CrashReportDatabaseMac::RecordUploadAttempt(UploadReport* report,
                                             bool successful,
                                             const std::string& id) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
@@ -479,13 +453,6 @@
   if (report_path.empty())
     return kReportNotFound;
 
-  std::unique_ptr<const UploadReport> upload_report(
-      static_cast<const UploadReport*>(report));
-
-  base::ScopedFD lock(upload_report->lock_fd);
-  if (!lock.is_valid())
-    return kBusyError;
-
   if (successful) {
     CrashReportDatabase::OperationStatus os =
         MarkReportCompletedLocked(report_path, &report_path);
@@ -774,8 +741,6 @@
   return std::unique_ptr<CrashReportDatabase>(database_mac.release());
 }
 
-}  // namespace
-
 // static
 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
     const base::FilePath& path) {
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_test.cc b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
index c426696..55bcf3c 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database_test.cc
+++ b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
@@ -19,8 +19,10 @@
 #include "gtest/gtest.h"
 #include "test/errors.h"
 #include "test/file.h"
+#include "test/filesystem.h"
 #include "test/scoped_temp_dir.h"
 #include "util/file/file_io.h"
+#include "util/file/filesystem.h"
 
 namespace crashpad {
 namespace test {
@@ -48,20 +50,19 @@
   }
 
   void CreateCrashReport(CrashReportDatabase::Report* report) {
-    CrashReportDatabase::NewReport* new_report = nullptr;
+    std::unique_ptr<CrashReportDatabase::NewReport> new_report;
     ASSERT_EQ(db_->PrepareNewCrashReport(&new_report),
               CrashReportDatabase::kNoError);
     static constexpr char kTest[] = "test";
-    ASSERT_TRUE(LoggingWriteFile(new_report->handle, kTest, sizeof(kTest)));
+    ASSERT_TRUE(new_report->Writer()->Write(kTest, sizeof(kTest)));
 
     UUID uuid;
-    EXPECT_EQ(db_->FinishedWritingCrashReport(new_report, &uuid),
+    EXPECT_EQ(db_->FinishedWritingCrashReport(std::move(new_report), &uuid),
               CrashReportDatabase::kNoError);
 
     EXPECT_EQ(db_->LookUpCrashReport(uuid, report),
               CrashReportDatabase::kNoError);
     ExpectPreparedCrashReport(*report);
-    ASSERT_TRUE(FileExists(report->file_path));
   }
 
   void UploadReport(const UUID& uuid, bool successful, const std::string& id) {
@@ -70,15 +71,19 @@
     time_t times[2];
     ASSERT_TRUE(settings->GetLastUploadAttemptTime(&times[0]));
 
-    const CrashReportDatabase::Report* report = nullptr;
+    std::unique_ptr<const CrashReportDatabase::UploadReport> report;
     ASSERT_EQ(db_->GetReportForUploading(uuid, &report),
               CrashReportDatabase::kNoError);
     EXPECT_NE(report->uuid, UUID());
     EXPECT_FALSE(report->file_path.empty());
     EXPECT_TRUE(FileExists(report->file_path)) << report->file_path.value();
     EXPECT_GT(report->creation_time, 0);
-    EXPECT_EQ(db_->RecordUploadAttempt(report, successful, id),
-              CrashReportDatabase::kNoError);
+    if (successful) {
+      EXPECT_EQ(db_->RecordUploadComplete(std::move(report), id),
+                CrashReportDatabase::kNoError);
+    } else {
+      report.reset();
+    }
 
     ASSERT_TRUE(settings->GetLastUploadAttemptTime(&times[1]));
     EXPECT_NE(times[1], 0);
@@ -176,13 +181,12 @@
 }
 
 TEST_F(CrashReportDatabaseTest, NewCrashReport) {
-  CrashReportDatabase::NewReport* new_report;
+  std::unique_ptr<CrashReportDatabase::NewReport> new_report;
   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
             CrashReportDatabase::kNoError);
-  UUID expect_uuid = new_report->uuid;
-  EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
+  UUID expect_uuid = new_report->ReportID();
   UUID uuid;
-  EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
+  EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
             CrashReportDatabase::kNoError);
   EXPECT_EQ(uuid, expect_uuid);
 
@@ -201,17 +205,6 @@
   EXPECT_TRUE(reports.empty());
 }
 
-TEST_F(CrashReportDatabaseTest, ErrorWritingCrashReport) {
-  CrashReportDatabase::NewReport* new_report = nullptr;
-  ASSERT_EQ(db()->PrepareNewCrashReport(&new_report),
-            CrashReportDatabase::kNoError);
-  base::FilePath new_report_path = new_report->path;
-  EXPECT_TRUE(FileExists(new_report_path)) << new_report_path.value();
-  EXPECT_EQ(db()->ErrorWritingCrashReport(new_report),
-            CrashReportDatabase::kNoError);
-  EXPECT_FALSE(FileExists(new_report_path)) << new_report_path.value();
-}
-
 TEST_F(CrashReportDatabaseTest, LookUpCrashReport) {
   UUID uuid;
 
@@ -465,16 +458,16 @@
   CrashReportDatabase::Report report;
   CreateCrashReport(&report);
 
-  const CrashReportDatabase::Report* upload_report;
+  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
             CrashReportDatabase::kNoError);
 
-  const CrashReportDatabase::Report* upload_report_2 = nullptr;
+  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2;
   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
             CrashReportDatabase::kBusyError);
   EXPECT_FALSE(upload_report_2);
 
-  EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()),
+  EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()),
             CrashReportDatabase::kNoError);
 }
 
@@ -482,25 +475,24 @@
   CrashReportDatabase::Report report;
   CreateCrashReport(&report);
 
-  const CrashReportDatabase::Report* upload_report;
+  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report),
             CrashReportDatabase::kNoError);
-  EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()),
+  EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()),
             CrashReportDatabase::kNoError);
 
-  const CrashReportDatabase::Report* upload_report_2 = nullptr;
+  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2;
   EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2),
             CrashReportDatabase::kReportNotFound);
-  EXPECT_FALSE(upload_report_2);
+  EXPECT_FALSE(upload_report_2.get());
 }
 
 TEST_F(CrashReportDatabaseTest, MoveDatabase) {
-  CrashReportDatabase::NewReport* new_report;
+  std::unique_ptr<CrashReportDatabase::NewReport> new_report;
   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
             CrashReportDatabase::kNoError);
-  EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
   UUID uuid;
-  EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
+  EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
             CrashReportDatabase::kNoError);
 
   RelocateDatabase();
@@ -509,28 +501,22 @@
   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
             CrashReportDatabase::kNoError);
   ExpectPreparedCrashReport(report);
-  EXPECT_TRUE(FileExists(report.file_path)) << report.file_path.value();
 }
 
 TEST_F(CrashReportDatabaseTest, ReportRemoved) {
-  CrashReportDatabase::NewReport* new_report;
+  std::unique_ptr<CrashReportDatabase::NewReport> new_report;
   EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
             CrashReportDatabase::kNoError);
-  EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value();
+
   UUID uuid;
-  EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid),
+  EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid),
             CrashReportDatabase::kNoError);
 
   CrashReportDatabase::Report report;
   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
             CrashReportDatabase::kNoError);
 
-#if defined(OS_WIN)
-  EXPECT_EQ(_wunlink(report.file_path.value().c_str()), 0);
-#else
-  EXPECT_EQ(unlink(report.file_path.value().c_str()), 0)
-      << ErrnoMessage("unlink");
-#endif
+  EXPECT_TRUE(LoggingRemoveFile(report.file_path));
 
   EXPECT_EQ(db()->LookUpCrashReport(uuid, &report),
             CrashReportDatabase::kReportNotFound);
@@ -642,21 +628,21 @@
   ASSERT_EQ(pending_reports.size(), 2u);
 
   // Check individual reports.
-  const CrashReportDatabase::Report* expicitly_requested_report;
+  const CrashReportDatabase::Report* explicitly_requested_report;
   const CrashReportDatabase::Report* pending_report;
   if (pending_reports[0].uuid == report_0_uuid) {
     pending_report = &pending_reports[0];
-    expicitly_requested_report = &pending_reports[1];
+    explicitly_requested_report = &pending_reports[1];
   } else {
     pending_report = &pending_reports[1];
-    expicitly_requested_report = &pending_reports[0];
+    explicitly_requested_report = &pending_reports[0];
   }
 
   EXPECT_EQ(pending_report->uuid, report_0_uuid);
   EXPECT_FALSE(pending_report->upload_explicitly_requested);
 
-  EXPECT_EQ(expicitly_requested_report->uuid, report_1_uuid);
-  EXPECT_TRUE(expicitly_requested_report->upload_explicitly_requested);
+  EXPECT_EQ(explicitly_requested_report->uuid, report_1_uuid);
+  EXPECT_TRUE(explicitly_requested_report->upload_explicitly_requested);
 
   // Explicitly requested reports will not have upload_explicitly_requested bit
   // after getting skipped.
@@ -683,6 +669,76 @@
             CrashReportDatabase::kCannotRequestUpload);
 }
 
+// This test uses knowledge of the database format to break it, so it only
+// applies to the unfified database implementation.
+#if !defined(OS_MACOSX) && !defined(OS_WIN)
+TEST_F(CrashReportDatabaseTest, CleanBrokenDatabase) {
+  // Remove report files if metadata goes missing.
+  CrashReportDatabase::Report report;
+  ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
+
+  const base::FilePath metadata(
+      report.file_path.RemoveFinalExtension().value() +
+      FILE_PATH_LITERAL(".meta"));
+  ASSERT_TRUE(PathExists(report.file_path));
+  ASSERT_TRUE(PathExists(metadata));
+
+  ASSERT_TRUE(LoggingRemoveFile(metadata));
+  EXPECT_EQ(db()->CleanDatabase(0), 1);
+
+  EXPECT_FALSE(PathExists(report.file_path));
+  EXPECT_FALSE(PathExists(metadata));
+
+  // Remove metadata files if reports go missing.
+  ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
+  const base::FilePath metadata2(
+      report.file_path.RemoveFinalExtension().value() +
+      FILE_PATH_LITERAL(".meta"));
+  ASSERT_TRUE(PathExists(report.file_path));
+  ASSERT_TRUE(PathExists(metadata2));
+
+  ASSERT_TRUE(LoggingRemoveFile(report.file_path));
+  EXPECT_EQ(db()->CleanDatabase(0), 1);
+
+  EXPECT_FALSE(PathExists(report.file_path));
+  EXPECT_FALSE(PathExists(metadata2));
+
+  // Remove stale new files.
+  std::unique_ptr<CrashReportDatabase::NewReport> new_report;
+  EXPECT_EQ(db()->PrepareNewCrashReport(&new_report),
+            CrashReportDatabase::kNoError);
+  new_report->Writer()->Close();
+  EXPECT_EQ(db()->CleanDatabase(0), 1);
+
+  // Remove stale lock files and their associated reports.
+  ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report));
+  const base::FilePath metadata3(
+      report.file_path.RemoveFinalExtension().value() +
+      FILE_PATH_LITERAL(".meta"));
+  ASSERT_TRUE(PathExists(report.file_path));
+  ASSERT_TRUE(PathExists(metadata3));
+
+  const base::FilePath lockpath(
+      report.file_path.RemoveFinalExtension().value() +
+      FILE_PATH_LITERAL(".lock"));
+  ScopedFileHandle handle(LoggingOpenFileForWrite(
+      lockpath, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly));
+  ASSERT_TRUE(handle.is_valid());
+
+  time_t expired_timestamp = time(nullptr) - 60 * 60 * 24 * 3;
+
+  ASSERT_TRUE(LoggingWriteFile(
+      handle.get(), &expired_timestamp, sizeof(expired_timestamp)));
+  ASSERT_TRUE(LoggingCloseFile(handle.get()));
+  ignore_result(handle.release());
+
+  EXPECT_EQ(db()->CleanDatabase(0), 1);
+
+  EXPECT_FALSE(PathExists(report.file_path));
+  EXPECT_FALSE(PathExists(metadata3));
+}
+#endif  // !OS_MACOSX && !OS_WIN
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_win.cc b/third_party/crashpad/crashpad/client/crash_report_database_win.cc
index 538eff5f..fb3cd8f 100644
--- a/third_party/crashpad/crashpad/client/crash_report_database_win.cc
+++ b/third_party/crashpad/crashpad/client/crash_report_database_win.cc
@@ -29,6 +29,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "client/settings.h"
+#include "util/misc/implicit_cast.h"
 #include "util/misc/initialization_state_dcheck.h"
 #include "util/misc/metrics.h"
 
@@ -571,6 +572,8 @@
   return EnsureDirectory(path);
 }
 
+}  // namespace
+
 // CrashReportDatabaseWin ------------------------------------------------------
 
 class CrashReportDatabaseWin : public CrashReportDatabase {
@@ -582,24 +585,27 @@
 
   // CrashReportDatabase:
   Settings* GetSettings() override;
-  OperationStatus PrepareNewCrashReport(NewReport** report) override;
-  OperationStatus FinishedWritingCrashReport(NewReport* report,
+  OperationStatus PrepareNewCrashReport(
+      std::unique_ptr<NewReport>* report) override;
+  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
                                              UUID* uuid) override;
-  OperationStatus ErrorWritingCrashReport(NewReport* report) override;
   OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override;
   OperationStatus GetPendingReports(std::vector<Report>* reports) override;
   OperationStatus GetCompletedReports(std::vector<Report>* reports) override;
-  OperationStatus GetReportForUploading(const UUID& uuid,
-                                        const Report** report) override;
-  OperationStatus RecordUploadAttempt(const Report* report,
-                                      bool successful,
-                                      const std::string& id) override;
+  OperationStatus GetReportForUploading(
+      const UUID& uuid,
+      std::unique_ptr<const UploadReport>* report) override;
   OperationStatus SkipReportUpload(const UUID& uuid,
                                    Metrics::CrashSkippedReason reason) override;
   OperationStatus DeleteReport(const UUID& uuid) override;
   OperationStatus RequestUpload(const UUID& uuid) override;
 
  private:
+  // CrashReportDatabase:
+  OperationStatus RecordUploadAttempt(UploadReport* report,
+                                      bool successful,
+                                      const std::string& id) override;
+
   std::unique_ptr<Metadata> AcquireMetadata();
 
   base::FilePath base_dir_;
@@ -610,11 +616,7 @@
 };
 
 CrashReportDatabaseWin::CrashReportDatabaseWin(const base::FilePath& path)
-    : CrashReportDatabase(),
-      base_dir_(path),
-      settings_(base_dir_.Append(kSettings)),
-      initialized_() {
-}
+    : CrashReportDatabase(), base_dir_(path), settings_(), initialized_() {}
 
 CrashReportDatabaseWin::~CrashReportDatabaseWin() {
 }
@@ -634,7 +636,7 @@
   if (!CreateDirectoryIfNecessary(base_dir_.Append(kReportsDirectory)))
     return false;
 
-  if (!settings_.Initialize())
+  if (!settings_.Initialize(base_dir_.Append(kSettings)))
     return false;
 
   INITIALIZATION_STATE_SET_VALID(initialized_);
@@ -647,67 +649,38 @@
 }
 
 OperationStatus CrashReportDatabaseWin::PrepareNewCrashReport(
-    NewReport** report) {
+    std::unique_ptr<NewReport>* report) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   std::unique_ptr<NewReport> new_report(new NewReport());
-  if (!new_report->uuid.InitializeWithNew())
+  if (!new_report->Initialize(base_dir_.Append(kReportsDirectory),
+                              std::wstring(L".") + kCrashReportFileExtension)) {
     return kFileSystemError;
-  new_report->path = base_dir_.Append(kReportsDirectory)
-                         .Append(new_report->uuid.ToString16() + L"." +
-                                 kCrashReportFileExtension);
-  new_report->handle = LoggingOpenFileForWrite(new_report->path,
-                                               FileWriteMode::kCreateOrFail,
-                                               FilePermissions::kOwnerOnly);
-  if (new_report->handle == INVALID_HANDLE_VALUE)
-    return kFileSystemError;
+  }
 
-  *report = new_report.release();
+  report->reset(new_report.release());
   return kNoError;
 }
 
 OperationStatus CrashReportDatabaseWin::FinishedWritingCrashReport(
-    NewReport* report,
+    std::unique_ptr<NewReport> report,
     UUID* uuid) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
-  // Take ownership of the report.
-  std::unique_ptr<NewReport> scoped_report(report);
-  // Take ownership of the file handle.
-  ScopedFileHandle handle(report->handle);
-
   std::unique_ptr<Metadata> metadata(AcquireMetadata());
   if (!metadata)
     return kDatabaseError;
-  metadata->AddNewRecord(ReportDisk(scoped_report->uuid,
-                                    scoped_report->path,
+  metadata->AddNewRecord(ReportDisk(report->ReportID(),
+                                    report->file_remover_.get(),
                                     time(nullptr),
                                     ReportState::kPending));
-  *uuid = scoped_report->uuid;
+
+  ignore_result(report->file_remover_.release());
+
+  *uuid = report->ReportID();
 
   Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated);
-  Metrics::CrashReportSize(handle.get());
-
-  return kNoError;
-}
-
-OperationStatus CrashReportDatabaseWin::ErrorWritingCrashReport(
-    NewReport* report) {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-
-  // Take ownership of the report.
-  std::unique_ptr<NewReport> scoped_report(report);
-
-  // Close the outstanding handle.
-  LoggingCloseFile(report->handle);
-
-  // We failed to write, so remove the dump file. There's no entry in the
-  // metadata table yet.
-  if (!DeleteFile(scoped_report->path.value().c_str())) {
-    PLOG(ERROR) << "DeleteFile "
-                << base::UTF16ToUTF8(scoped_report->path.value());
-    return kFileSystemError;
-  }
+  Metrics::CrashReportSize(report->Writer()->Seek(0, SEEK_END));
 
   return kNoError;
 }
@@ -747,44 +720,38 @@
 
 OperationStatus CrashReportDatabaseWin::GetReportForUploading(
     const UUID& uuid,
-    const Report** report) {
+    std::unique_ptr<const UploadReport>* report) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   std::unique_ptr<Metadata> metadata(AcquireMetadata());
   if (!metadata)
     return kDatabaseError;
-  // TODO(scottmg): After returning this report to the client, there is no way
-  // to reap this report if the uploader fails to call RecordUploadAttempt() or
-  // SkipReportUpload() (if it crashed or was otherwise buggy). To resolve this,
-  // one possibility would be to change the interface to be FileHandle based, so
-  // that instead of giving the file_path back to the client and changing state
-  // to kUploading, we return an exclusive access handle, and use that as the
-  // signal that the upload is pending, rather than an update to state in the
-  // metadata. Alternatively, there could be a "garbage collection" at startup
-  // where any reports that are orphaned in the kUploading state are either
-  // reset to kPending to retry, or discarded.
+
   ReportDisk* report_disk;
   OperationStatus os = metadata->FindSingleReportAndMarkDirty(
       uuid, ReportState::kPending, &report_disk);
   if (os == kNoError) {
     report_disk->state = ReportState::kUploading;
-    // Create a copy for passing back to client. This will be freed in
-    // RecordUploadAttempt.
-    *report = new Report(*report_disk);
+    auto upload_report = std::make_unique<UploadReport>();
+    *implicit_cast<Report*>(upload_report.get()) = *report_disk;
+
+    if (!upload_report->Initialize(upload_report->file_path, this)) {
+      return kFileSystemError;
+    }
+
+    report->reset(upload_report.release());
   }
   return os;
 }
 
 OperationStatus CrashReportDatabaseWin::RecordUploadAttempt(
-    const Report* report,
+    UploadReport* report,
     bool successful,
     const std::string& id) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   Metrics::CrashUploadAttempted(successful);
 
-  // Take ownership, allocated in GetReportForUploading.
-  std::unique_ptr<const Report> upload_report(report);
   std::unique_ptr<Metadata> metadata(AcquireMetadata());
   if (!metadata)
     return kDatabaseError;
@@ -903,8 +870,6 @@
   return kNoError;
 }
 
-}  // namespace
-
 // static
 std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
     const base::FilePath& path) {
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h
index 7cf2eb8..3cd806a1 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client.h
+++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -24,12 +24,16 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "util/misc/capture_context.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_mach_port.h"
 #elif defined(OS_WIN)
 #include <windows.h>
 #include "util/win/scoped_handle.h"
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+#include <signal.h>
+#include <ucontext.h>
 #endif
 
 namespace crashpad {
@@ -168,6 +172,40 @@
       const std::map<std::string, std::string>& annotations,
       const std::vector<std::string>& arguments,
       int socket);
+
+  //! \brief Requests that the handler capture a dump even though there hasn't
+  //!     been a crash.
+  //!
+  //! A handler must have already been installed before calling this method.
+  //!
+  //! TODO(jperaza): Floating point information in the context is zeroed out
+  //! until CaptureContext() supports collecting that information.
+  //!
+  //! \param[in] context A NativeCPUContext, generally captured by
+  //!     CaptureContext() or similar.
+  static void DumpWithoutCrash(NativeCPUContext* context);
+
+  //! \brief The type for custom handlers installed by clients.
+  using FirstChanceHandler = bool (*)(int, siginfo_t*, ucontext_t*);
+
+  //! \brief Installs a custom crash signal handler which runs before the
+  //!     currently installed Crashpad handler.
+  //!
+  //! Handling signals appropriately can be tricky and use of this method
+  //! should be avoided, if possible.
+  //!
+  //! A handler must have already been installed before calling this method.
+  //!
+  //! The custom handler runs in a signal handler context and must be safe for
+  //! that purpose.
+  //!
+  //! If the custom handler returns `true`, the signal is considered handled and
+  //! the signal handler returns. Otherwise, the currently installed Crashpad
+  //! signal handler is run.
+  //!
+  //! \param[in] handler The custom crash signal handler to install.
+  static void SetFirstChanceExceptionHandler(FirstChanceHandler handler);
+
 #endif  // OS_LINUX || OS_ANDROID || DOXYGEN
 
 #if defined(OS_MACOSX) || DOXYGEN
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
index a36d922..ca13c29 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -27,6 +27,7 @@
 #include "util/file/file_io.h"
 #include "util/linux/exception_handler_client.h"
 #include "util/linux/exception_information.h"
+#include "util/linux/scoped_pr_set_ptracer.h"
 #include "util/misc/from_pointer_cast.h"
 #include "util/posix/double_fork_and_exec.h"
 #include "util/posix/signals.h"
@@ -82,7 +83,7 @@
   }
 }
 
-void ConvertArgvStrings(const std::vector<std::string> argv_strings,
+void ConvertArgvStrings(const std::vector<std::string>& argv_strings,
                         std::vector<const char*>* argv) {
   argv->clear();
   argv->reserve(argv_strings.size() + 1);
@@ -92,8 +93,28 @@
   argv->push_back(nullptr);
 }
 
+class SignalHandler {
+ public:
+  virtual void HandleCrashFatal(int signo,
+                                siginfo_t* siginfo,
+                                void* context) = 0;
+  virtual bool HandleCrashNonFatal(int signo,
+                                   siginfo_t* siginfo,
+                                   void* context) = 0;
+
+  void SetFirstChanceHandler(CrashpadClient::FirstChanceHandler handler) {
+    first_chance_handler_ = handler;
+  }
+
+ protected:
+  SignalHandler() = default;
+  ~SignalHandler() = default;
+
+  CrashpadClient::FirstChanceHandler first_chance_handler_ = nullptr;
+};
+
 // Launches a single use handler to snapshot this process.
-class LaunchAtCrashHandler {
+class LaunchAtCrashHandler : public SignalHandler {
  public:
   static LaunchAtCrashHandler* Get() {
     static LaunchAtCrashHandler* instance = new LaunchAtCrashHandler();
@@ -110,6 +131,46 @@
     return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr);
   }
 
+  bool HandleCrashNonFatal(int signo,
+                           siginfo_t* siginfo,
+                           void* context) override {
+    if (first_chance_handler_ &&
+        first_chance_handler_(
+            signo, siginfo, static_cast<ucontext_t*>(context))) {
+      return true;
+    }
+
+    exception_information_.siginfo_address =
+        FromPointerCast<decltype(exception_information_.siginfo_address)>(
+            siginfo);
+    exception_information_.context_address =
+        FromPointerCast<decltype(exception_information_.context_address)>(
+            context);
+    exception_information_.thread_id = syscall(SYS_gettid);
+
+    ScopedPrSetPtracer set_ptracer(getpid(), /* may_log= */ false);
+
+    pid_t pid = fork();
+    if (pid < 0) {
+      return false;
+    }
+    if (pid == 0) {
+      execv(argv_[0], const_cast<char* const*>(argv_.data()));
+      _exit(EXIT_FAILURE);
+    }
+
+    int status;
+    waitpid(pid, &status, 0);
+    return false;
+  }
+
+  void HandleCrashFatal(int signo, siginfo_t* siginfo, void* context) override {
+    if (HandleCrashNonFatal(signo, siginfo, context)) {
+      return;
+    }
+    Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
+  }
+
  private:
   LaunchAtCrashHandler() = default;
 
@@ -117,27 +178,7 @@
 
   static void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
     auto state = Get();
-    auto exception_information = &state->exception_information_;
-
-    exception_information->siginfo_address =
-        FromPointerCast<decltype(exception_information->siginfo_address)>(
-            siginfo);
-    exception_information->context_address =
-        FromPointerCast<decltype(exception_information->context_address)>(
-            context);
-    exception_information->thread_id = syscall(SYS_gettid);
-
-    pid_t pid = fork();
-    if (pid < 0) {
-      return;
-    }
-    if (pid == 0) {
-      execv(state->argv_[0], const_cast<char* const*>(state->argv_.data()));
-      return;
-    }
-
-    int status;
-    waitpid(pid, &status, 0);
+    state->HandleCrashFatal(signo, siginfo, context);
   }
 
   std::vector<std::string> argv_strings_;
@@ -147,6 +188,11 @@
   DISALLOW_COPY_AND_ASSIGN(LaunchAtCrashHandler);
 };
 
+// A pointer to the currently installed crash signal handler. This allows
+// the static method CrashpadClient::DumpWithoutCrashing to simulate a crash
+// using the currently configured crash handling strategy.
+static SignalHandler* g_crash_handler;
+
 }  // namespace
 
 CrashpadClient::CrashpadClient() {}
@@ -181,7 +227,12 @@
       handler, database, metrics_dir, url, annotations, arguments, &argv);
 
   auto signal_handler = LaunchAtCrashHandler::Get();
-  return signal_handler->Initialize(&argv);
+  if (signal_handler->Initialize(&argv)) {
+    DCHECK(!g_crash_handler);
+    g_crash_handler = signal_handler;
+    return true;
+  }
+  return false;
 }
 
 bool CrashpadClient::StartHandlerForClient(
@@ -201,4 +252,38 @@
   return DoubleForkAndExec(argv, socket, true, nullptr);
 }
 
+// static
+void CrashpadClient::DumpWithoutCrash(NativeCPUContext* context) {
+  DCHECK(g_crash_handler);
+
+#if defined(ARCH_CPU_X86)
+  memset(&context->__fpregs_mem, 0, sizeof(context->__fpregs_mem));
+  context->__fpregs_mem.status = 0xffff0000;
+#elif defined(ARCH_CPU_X86_64)
+  memset(&context->__fpregs_mem, 0, sizeof(context->__fpregs_mem));
+#elif defined(ARCH_CPU_ARMEL)
+  memset(context->uc_regspace, 0, sizeof(context->uc_regspace));
+#elif defined(ARCH_CPU_ARM64)
+  memset(context->uc_mcontext.__reserved,
+         0,
+         sizeof(context->uc_mcontext.__reserved));
+#else
+#error Port.
+#endif
+
+  siginfo_t siginfo;
+  siginfo.si_signo = Signals::kSimulatedSigno;
+  siginfo.si_errno = 0;
+  siginfo.si_code = 0;
+  g_crash_handler->HandleCrashNonFatal(
+      siginfo.si_signo, &siginfo, reinterpret_cast<void*>(context));
+}
+
+// static
+void CrashpadClient::SetFirstChanceExceptionHandler(
+    FirstChanceHandler handler) {
+  DCHECK(g_crash_handler);
+  g_crash_handler->SetFirstChanceHandler(handler);
+}
+
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc
new file mode 100644
index 0000000..9610cdd
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc
@@ -0,0 +1,327 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "client/crashpad_client.h"
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "client/crash_report_database.h"
+#include "client/simulate_crash.h"
+#include "gtest/gtest.h"
+#include "test/multiprocess_exec.h"
+#include "test/multiprocess.h"
+#include "test/scoped_temp_dir.h"
+#include "test/test_paths.h"
+#include "util/file/file_io.h"
+#include "util/linux/exception_handler_client.h"
+#include "util/linux/exception_information.h"
+#include "util/misc/address_types.h"
+#include "util/misc/from_pointer_cast.h"
+#include "util/posix/signals.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+bool HandleCrashSuccessfully(int, siginfo_t*, ucontext_t*) {
+  return true;
+}
+
+TEST(CrashpadClient, SimulateCrash) {
+  ScopedTempDir temp_dir;
+
+  base::FilePath handler_path = TestPaths::Executable().DirName().Append(
+      FILE_PATH_LITERAL("crashpad_handler"));
+
+  crashpad::CrashpadClient client;
+  ASSERT_TRUE(client.StartHandlerAtCrash(handler_path,
+                                         base::FilePath(temp_dir.path()),
+                                         base::FilePath(),
+                                         "",
+                                         std::map<std::string, std::string>(),
+                                         std::vector<std::string>()));
+
+  auto database =
+      CrashReportDatabase::InitializeWithoutCreating(temp_dir.path());
+  ASSERT_TRUE(database);
+
+  {
+    CrashpadClient::SetFirstChanceExceptionHandler(HandleCrashSuccessfully);
+
+    CRASHPAD_SIMULATE_CRASH();
+
+    std::vector<CrashReportDatabase::Report> reports;
+    ASSERT_EQ(database->GetPendingReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 0u);
+
+    reports.clear();
+    ASSERT_EQ(database->GetCompletedReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 0u);
+  }
+
+  {
+    CrashpadClient::SetFirstChanceExceptionHandler(nullptr);
+
+    CRASHPAD_SIMULATE_CRASH();
+
+    std::vector<CrashReportDatabase::Report> reports;
+    ASSERT_EQ(database->GetPendingReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 0u);
+
+    reports.clear();
+    ASSERT_EQ(database->GetCompletedReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 1u);
+  }
+}
+
+CRASHPAD_CHILD_TEST_MAIN(StartHandlerAtCrashChild) {
+  FileHandle in = StdioFileHandle(StdioStream::kStandardInput);
+
+  VMSize temp_dir_length;
+  CheckedReadFileExactly(in, &temp_dir_length, sizeof(temp_dir_length));
+
+  std::string temp_dir(temp_dir_length, '\0');
+  CheckedReadFileExactly(in, &temp_dir[0], temp_dir_length);
+
+  base::FilePath handler_path = TestPaths::Executable().DirName().Append(
+      FILE_PATH_LITERAL("crashpad_handler"));
+
+  crashpad::CrashpadClient client;
+  if (!client.StartHandlerAtCrash(handler_path,
+                                  base::FilePath(temp_dir),
+                                  base::FilePath(),
+                                  "",
+                                  std::map<std::string, std::string>(),
+                                  std::vector<std::string>())) {
+    return EXIT_FAILURE;
+  }
+
+  __builtin_trap();
+
+  NOTREACHED();
+  return EXIT_SUCCESS;
+}
+
+class StartHandlerAtCrashTest : public MultiprocessExec {
+ public:
+  StartHandlerAtCrashTest() : MultiprocessExec() {
+    SetChildTestMainFunction("StartHandlerAtCrashChild");
+    SetExpectedChildTerminationBuiltinTrap();
+  }
+
+ private:
+  void MultiprocessParent() override {
+    ScopedTempDir temp_dir;
+    VMSize temp_dir_length = temp_dir.path().value().size();
+    ASSERT_TRUE(LoggingWriteFile(
+        WritePipeHandle(), &temp_dir_length, sizeof(temp_dir_length)));
+    ASSERT_TRUE(LoggingWriteFile(
+        WritePipeHandle(), temp_dir.path().value().data(), temp_dir_length));
+
+    // Wait for child to finish.
+    CheckedReadFileAtEOF(ReadPipeHandle());
+
+    auto database = CrashReportDatabase::Initialize(temp_dir.path());
+    ASSERT_TRUE(database);
+
+    std::vector<CrashReportDatabase::Report> reports;
+    ASSERT_EQ(database->GetPendingReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 0u);
+
+    ASSERT_EQ(database->GetCompletedReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 1u);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(StartHandlerAtCrashTest);
+};
+
+TEST(CrashpadClient, StartHandlerAtCrash) {
+  StartHandlerAtCrashTest test;
+  test.Run();
+}
+
+// Test state for starting the handler for another process.
+class StartHandlerForClientTest {
+ public:
+  StartHandlerForClientTest() = default;
+  ~StartHandlerForClientTest() = default;
+
+  bool Initialize() {
+    int socks[2];
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) != 0) {
+      PLOG(ERROR) << "socketpair";
+      return false;
+    }
+    client_sock_.reset(socks[0]);
+    server_sock_.reset(socks[1]);
+
+    return true;
+  }
+
+  bool StartHandlerOnDemand() {
+    char c;
+    if (!LoggingReadFileExactly(server_sock_.get(), &c, sizeof(c))) {
+      ADD_FAILURE();
+      return false;
+    }
+
+    base::FilePath handler_path = TestPaths::Executable().DirName().Append(
+        FILE_PATH_LITERAL("crashpad_handler"));
+
+    CrashpadClient client;
+    if (!client.StartHandlerForClient(handler_path,
+                                        temp_dir_.path(),
+                                        base::FilePath(),
+                                        "",
+                                        std::map<std::string, std::string>(),
+                                        std::vector<std::string>(),
+                                        server_sock_.get())) {
+      ADD_FAILURE();
+      return false;
+    }
+
+    return true;
+  }
+
+  void ExpectReport() {
+    auto database =
+        CrashReportDatabase::InitializeWithoutCreating(temp_dir_.path());
+    ASSERT_TRUE(database);
+
+    std::vector<CrashReportDatabase::Report> reports;
+    ASSERT_EQ(database->GetPendingReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 0u);
+
+    ASSERT_EQ(database->GetCompletedReports(&reports),
+              CrashReportDatabase::kNoError);
+    EXPECT_EQ(reports.size(), 1u);
+  }
+
+  bool InstallHandler() {
+    auto signal_handler = SandboxedHandler::Get();
+    return signal_handler->Initialize(client_sock_.get());
+  }
+
+ private:
+  // A signal handler that defers handler process startup to another, presumably
+  // more privileged, process.
+  class SandboxedHandler {
+   public:
+    static SandboxedHandler* Get() {
+      static SandboxedHandler* instance = new SandboxedHandler();
+      return instance;
+    }
+
+    bool Initialize(FileHandle client_sock) {
+      client_sock_ = client_sock;
+      return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr);
+    }
+
+   private:
+    SandboxedHandler() = default;
+    ~SandboxedHandler() = delete;
+
+    static void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
+      auto state = Get();
+
+      char c;
+      CHECK(LoggingWriteFile(state->client_sock_, &c, sizeof(c)));
+
+      ExceptionInformation exception_information;
+      exception_information.siginfo_address =
+          FromPointerCast<decltype(exception_information.siginfo_address)>(
+              siginfo);
+      exception_information.context_address =
+          FromPointerCast<decltype(exception_information.context_address)>(
+              context);
+      exception_information.thread_id = syscall(SYS_gettid);
+
+      ClientInformation info = {};
+      info.exception_information_address =
+          FromPointerCast<decltype(info.exception_information_address)>(
+              &exception_information);
+
+      ExceptionHandlerClient handler_client(state->client_sock_);
+      CHECK_EQ(handler_client.RequestCrashDump(info), 0);
+
+      Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
+    }
+
+    FileHandle client_sock_;
+
+    DISALLOW_COPY_AND_ASSIGN(SandboxedHandler);
+  };
+
+  ScopedTempDir temp_dir_;
+  ScopedFileHandle client_sock_;
+  ScopedFileHandle server_sock_;
+
+  DISALLOW_COPY_AND_ASSIGN(StartHandlerForClientTest);
+};
+
+// Tests starting the handler for a child process.
+class StartHandlerForChildTest : public Multiprocess {
+ public:
+  StartHandlerForChildTest() = default;
+  ~StartHandlerForChildTest() = default;
+
+  bool Initialize() {
+    SetExpectedChildTerminationBuiltinTrap();
+    return test_state_.Initialize();
+  }
+
+ private:
+  void MultiprocessParent() {
+    ASSERT_TRUE(test_state_.StartHandlerOnDemand());
+
+    // Wait for chlid to finish.
+    CheckedReadFileAtEOF(ReadPipeHandle());
+
+    test_state_.ExpectReport();
+  }
+
+  void MultiprocessChild() {
+    CHECK(test_state_.InstallHandler());
+
+    __builtin_trap();
+
+    NOTREACHED();
+  }
+
+  StartHandlerForClientTest test_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(StartHandlerForChildTest);
+};
+
+TEST(CrashpadClient, StartHandlerForChild) {
+  StartHandlerForChildTest test;
+  ASSERT_TRUE(test.Initialize());
+  test.Run();
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_win.cc b/third_party/crashpad/crashpad/client/crashpad_client_win.cc
index dd25c9e..8ceded3 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client_win.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_client_win.cc
@@ -30,10 +30,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "util/file/file_io.h"
+#include "util/misc/capture_context.h"
 #include "util/misc/from_pointer_cast.h"
 #include "util/misc/random_string.h"
 #include "util/win/address_types.h"
-#include "util/win/capture_context.h"
 #include "util/win/command_line.h"
 #include "util/win/critical_section_with_debug_info.h"
 #include "util/win/get_function.h"
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.cc b/third_party/crashpad/crashpad/client/crashpad_info.cc
index b545a3c..7c1316e 100644
--- a/third_party/crashpad/crashpad/client/crashpad_info.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_info.cc
@@ -52,12 +52,6 @@
 // because it’s POD, no code should need to run to initialize this under
 // release-mode optimization.
 
-// Platforms that use ELF objects need to locate this structure via the dynamic
-// symbol table, so avoid name mangling.
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
-extern "C" {
-#endif
-
 #if defined(OS_POSIX)
 __attribute__((
 
@@ -65,10 +59,6 @@
     // Put the structure in a well-known section name where it can be easily
     // found without having to consult the symbol table.
     section(SEG_DATA ",crashpad_info"),
-
-    // There's no need to expose this as a public symbol from the symbol table.
-    // All accesses from the outside can locate the well-known section name.
-    visibility("hidden"),
 #endif
 
 #if defined(ADDRESS_SANITIZER)
@@ -80,6 +70,10 @@
     aligned(64),
 #endif  // defined(ADDRESS_SANITIZER)
 
+    // There's no need to expose this as a public symbol from the symbol table.
+    // All accesses from the outside can locate the well-known section name.
+    visibility("hidden"),
+
     // The “used” attribute prevents the structure from being dead-stripped.
     used))
 
@@ -96,12 +90,19 @@
 
 CrashpadInfo g_crashpad_info;
 
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
-}  // extern "C"
-#endif
+extern "C" int* CRASHPAD_NOTE_REFERENCE;
 
 // static
 CrashpadInfo* CrashpadInfo::GetCrashpadInfo() {
+#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
+  // This otherwise-unused reference is used so that any module that
+  // references GetCrashpadInfo() will also include the note in the
+  // .note.crashpad.info section. That note in turn contains the address of
+  // g_crashpad_info. This allows the module reader to find the CrashpadInfo
+  // structure without requiring the use of the dynamic symbol table.
+  static volatile int* pointer_to_note_section = CRASHPAD_NOTE_REFERENCE;
+  (void)pointer_to_note_section;
+#endif
   return &g_crashpad_info;
 }
 
diff --git a/third_party/crashpad/crashpad/client/crashpad_info_note.S b/third_party/crashpad/crashpad/client/crashpad_info_note.S
new file mode 100644
index 0000000..8084db9
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/crashpad_info_note.S
@@ -0,0 +1,60 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This note section is used on ELF platforms to give ElfImageReader a method
+// of finding the instance of CrashpadInfo g_crashpad_info without requiring
+// that symbol to be in the dynamic symbol table.
+
+#include "build/build_config.h"
+#include "util/misc/elf_note_types.h"
+
+// namespace crashpad {
+// CrashpadInfo g_crashpad_info;
+// }  // namespace crashpad
+#define CRASHPAD_INFO_SYMBOL _ZN8crashpad15g_crashpad_infoE
+
+#define NOTE_ALIGN 4
+
+  // This section must be "a"llocated so that it appears in the final binary at
+  // runtime, and "w"ritable so that the relocation to CRASHPAD_INFO_SYMBOL can
+  // be performed.
+  .section .note.crashpad.info,"aw",%note
+  .balign NOTE_ALIGN
+  # .globl indicates that it's available to link against other .o files. .hidden
+  # indicates that it will not appear in the executable's symbol table.
+  .globl CRASHPAD_NOTE_REFERENCE
+  .hidden CRASHPAD_NOTE_REFERENCE
+  .type CRASHPAD_NOTE_REFERENCE, %object
+CRASHPAD_NOTE_REFERENCE:
+  .long name_end - name  // namesz
+  .long desc_end - desc  // descsz
+  .long CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO  // type
+name:
+  .asciz CRASHPAD_ELF_NOTE_NAME
+name_end:
+  .balign NOTE_ALIGN
+desc:
+#if defined(ARCH_CPU_64_BITS)
+  .quad CRASHPAD_INFO_SYMBOL
+#else
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+  .long CRASHPAD_INFO_SYMBOL
+  .long 0
+#else
+  .long 0
+  .long CRASHPAD_INFO_SYMBOL
+#endif  // ARCH_CPU_LITTLE_ENDIAN
+#endif  // ARCH_CPU_64_BITS
+desc_end:
+  .size CRASHPAD_NOTE_REFERENCE, .-CRASHPAD_NOTE_REFERENCE
diff --git a/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc b/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc
index 54d6941e..2648dee 100644
--- a/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc
+++ b/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc
@@ -36,20 +36,27 @@
  public:
   // CrashReportDatabase:
   MOCK_METHOD0(GetSettings, Settings*());
-  MOCK_METHOD1(PrepareNewCrashReport, OperationStatus(NewReport**));
-  MOCK_METHOD2(FinishedWritingCrashReport, OperationStatus(NewReport*, UUID*));
-  MOCK_METHOD1(ErrorWritingCrashReport, OperationStatus(NewReport*));
+  MOCK_METHOD1(PrepareNewCrashReport,
+               OperationStatus(std::unique_ptr<NewReport>*));
   MOCK_METHOD2(LookUpCrashReport, OperationStatus(const UUID&, Report*));
   MOCK_METHOD1(GetPendingReports, OperationStatus(std::vector<Report>*));
   MOCK_METHOD1(GetCompletedReports, OperationStatus(std::vector<Report>*));
   MOCK_METHOD2(GetReportForUploading,
-               OperationStatus(const UUID&, const Report**));
+               OperationStatus(const UUID&,
+                               std::unique_ptr<const UploadReport>*));
   MOCK_METHOD3(RecordUploadAttempt,
-               OperationStatus(const Report*, bool, const std::string&));
+               OperationStatus(UploadReport*, bool, const std::string&));
   MOCK_METHOD2(SkipReportUpload,
                OperationStatus(const UUID&, Metrics::CrashSkippedReason));
   MOCK_METHOD1(DeleteReport, OperationStatus(const UUID&));
   MOCK_METHOD1(RequestUpload, OperationStatus(const UUID&));
+
+  // gmock doesn't support mocking methods with non-copyable types such as
+  // unique_ptr.
+  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
+                                             UUID* uuid) override {
+    return kNoError;
+  }
 };
 
 time_t NDaysAgo(int num_days) {
diff --git a/third_party/crashpad/crashpad/client/settings.cc b/third_party/crashpad/crashpad/client/settings.cc
index 15d16f2..20bd258 100644
--- a/third_party/crashpad/crashpad/client/settings.cc
+++ b/third_party/crashpad/crashpad/client/settings.cc
@@ -20,10 +20,55 @@
 
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
+#include "util/file/filesystem.h"
 #include "util/numeric/in_range_cast.h"
 
 namespace crashpad {
 
+#if defined(OS_FUCHSIA)
+
+Settings::ScopedLockedFileHandle::ScopedLockedFileHandle()
+    : handle_(kInvalidFileHandle), lockfile_path_() {
+    }
+
+Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
+    FileHandle handle,
+    const base::FilePath& lockfile_path)
+    : handle_(handle), lockfile_path_(lockfile_path) {
+}
+
+Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
+    ScopedLockedFileHandle&& other)
+    : handle_(other.handle_), lockfile_path_(other.lockfile_path_) {
+  other.handle_ = kInvalidFileHandle;
+  other.lockfile_path_ = base::FilePath();
+}
+
+Settings::ScopedLockedFileHandle& Settings::ScopedLockedFileHandle::operator=(
+    ScopedLockedFileHandle&& other) {
+  handle_ = other.handle_;
+  lockfile_path_ = other.lockfile_path_;
+
+  other.handle_ = kInvalidFileHandle;
+  other.lockfile_path_ = base::FilePath();
+  return *this;
+}
+
+Settings::ScopedLockedFileHandle::~ScopedLockedFileHandle() {
+  Destroy();
+}
+
+void Settings::ScopedLockedFileHandle::Destroy() {
+  if (handle_ != kInvalidFileHandle) {
+    CheckedCloseFile(handle_);
+  }
+  if (!lockfile_path_.empty()) {
+    DCHECK(LoggingRemoveFile(lockfile_path_));
+  }
+}
+
+#else // OS_FUCHSIA
+
 namespace internal {
 
 // static
@@ -36,6 +81,8 @@
 
 }  // namespace internal
 
+#endif  // OS_FUCHSIA
+
 struct Settings::Data {
   static const uint32_t kSettingsMagic = 'CPds';
   static const uint32_t kSettingsVersion = 1;
@@ -59,16 +106,14 @@
   UUID client_id;
 };
 
-Settings::Settings(const base::FilePath& file_path)
-    : file_path_(file_path),
-      initialized_() {
-}
+Settings::Settings() = default;
 
-Settings::~Settings() {
-}
+Settings::~Settings() = default;
 
-bool Settings::Initialize() {
+bool Settings::Initialize(const base::FilePath& file_path) {
+  DCHECK(initialized_.is_uninitialized());
   initialized_.set_invalid();
+  file_path_ = file_path;
 
   Data settings;
   if (!OpenForWritingAndReadSettings(&settings).is_valid())
@@ -144,18 +189,33 @@
 // static
 Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
     FileHandle file,
-    FileLocking locking) {
+    FileLocking locking,
+    const base::FilePath& file_path) {
   ScopedFileHandle scoped(file);
+#if defined(OS_FUCHSIA)
+  base::FilePath lockfile_path(file_path.value() + ".__lock__");
+  if (scoped.is_valid()) {
+    ScopedFileHandle lockfile_scoped(
+        LoggingOpenFileForWrite(lockfile_path,
+                                FileWriteMode::kCreateOrFail,
+                                FilePermissions::kWorldReadable));
+    // This is a lightweight attempt to try to catch racy behavior.
+    DCHECK(lockfile_scoped.is_valid());
+    return ScopedLockedFileHandle(scoped.release(), lockfile_path);
+  }
+  return ScopedLockedFileHandle(scoped.release(), base::FilePath());
+#else
   if (scoped.is_valid()) {
     if (!LoggingLockFile(scoped.get(), locking))
       scoped.reset();
   }
   return ScopedLockedFileHandle(scoped.release());
+#endif
 }
 
 Settings::ScopedLockedFileHandle Settings::OpenForReading() {
-  return MakeScopedLockedFileHandle(LoggingOpenFileForRead(file_path()),
-                                    FileLocking::kShared);
+  return MakeScopedLockedFileHandle(
+      LoggingOpenFileForRead(file_path()), FileLocking::kShared, file_path());
 }
 
 Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
@@ -171,7 +231,8 @@
         file_path(), mode, FilePermissions::kWorldReadable);
   }
 
-  return MakeScopedLockedFileHandle(handle, FileLocking::kExclusive);
+  return MakeScopedLockedFileHandle(
+      handle, FileLocking::kExclusive, file_path());
 }
 
 bool Settings::OpenAndReadSettings(Data* out_data) {
diff --git a/third_party/crashpad/crashpad/client/settings.h b/third_party/crashpad/crashpad/client/settings.h
index b64f74fb..a2b0c74 100644
--- a/third_party/crashpad/crashpad/client/settings.h
+++ b/third_party/crashpad/crashpad/client/settings.h
@@ -22,6 +22,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/scoped_generic.h"
+#include "build/build_config.h"
 #include "util/file/file_io.h"
 #include "util/misc/initialization_state.h"
 #include "util/misc/uuid.h"
@@ -44,10 +45,18 @@
 //! should be retrieved via CrashReportDatabase::GetSettings().
 class Settings {
  public:
-  explicit Settings(const base::FilePath& file_path);
+  Settings();
   ~Settings();
 
-  bool Initialize();
+  //! \brief Initializes the settings data store.
+  //!
+  //! This method must be called only once, and must be successfully called
+  //! before any other method in this class may be called.
+  //!
+  //! \param[in] path The location to store the settings data.
+  //! \return `true` if the data store was initialized successfully, otherwise
+  //!     `false` with an error logged.
+  bool Initialize(const base::FilePath& path);
 
   //! \brief Retrieves the immutable identifier for this client, which is used
   //!     on a server to locate all crash reports from a specific Crashpad
@@ -106,11 +115,45 @@
   struct Data;
 
   // This must be constructed with MakeScopedLockedFileHandle(). It both unlocks
-  // and closes the file on destruction.
+  // and closes the file on destruction. Note that on Fuchsia, this handle DOES
+  // NOT offer correct operation, only an attempt to DCHECK if racy behavior is
+  // detected.
+#if defined(OS_FUCHSIA)
+  struct ScopedLockedFileHandle {
+   public:
+    ScopedLockedFileHandle();
+    ScopedLockedFileHandle(FileHandle handle,
+                           const base::FilePath& lockfile_path);
+    ScopedLockedFileHandle(ScopedLockedFileHandle&& other);
+    ScopedLockedFileHandle& operator=(ScopedLockedFileHandle&& other);
+    ~ScopedLockedFileHandle();
+
+    // These mirror the non-Fuchsia ScopedLockedFileHandle via ScopedGeneric so
+    // that calling code can pretend this implementation is the same.
+    bool is_valid() const { return handle_ != kInvalidFileHandle; }
+    FileHandle get() { return handle_; }
+    void reset() {
+      Destroy();
+      handle_ = kInvalidFileHandle;
+      lockfile_path_ = base::FilePath();
+    }
+
+   private:
+    void Destroy();
+
+    FileHandle handle_;
+    base::FilePath lockfile_path_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedLockedFileHandle);
+  };
+#else  // OS_FUCHSIA
   using ScopedLockedFileHandle =
       base::ScopedGeneric<FileHandle, internal::ScopedLockedFileHandleTraits>;
-  static ScopedLockedFileHandle MakeScopedLockedFileHandle(FileHandle file,
-                                                           FileLocking locking);
+#endif  // OS_FUCHSIA
+  static ScopedLockedFileHandle MakeScopedLockedFileHandle(
+      FileHandle file,
+      FileLocking locking,
+      const base::FilePath& file_path);
 
   // Opens the settings file for reading. On error, logs a message and returns
   // the invalid handle.
diff --git a/third_party/crashpad/crashpad/client/settings_test.cc b/third_party/crashpad/crashpad/client/settings_test.cc
index ca961a23..3a5730b 100644
--- a/third_party/crashpad/crashpad/client/settings_test.cc
+++ b/third_party/crashpad/crashpad/client/settings_test.cc
@@ -26,7 +26,7 @@
 
 class SettingsTest : public testing::Test {
  public:
-  SettingsTest() : settings_(settings_path()) {}
+  SettingsTest() = default;
 
   base::FilePath settings_path() {
     return temp_dir_.path().Append(FILE_PATH_LITERAL("settings"));
@@ -49,7 +49,7 @@
  protected:
   // testing::Test:
   void SetUp() override {
-    ASSERT_TRUE(settings()->Initialize());
+    ASSERT_TRUE(settings()->Initialize(settings_path()));
   }
 
  private:
@@ -64,8 +64,8 @@
   EXPECT_TRUE(settings()->GetClientID(&client_id));
   EXPECT_NE(client_id, UUID());
 
-  Settings local_settings(settings_path());
-  EXPECT_TRUE(local_settings.Initialize());
+  Settings local_settings;
+  EXPECT_TRUE(local_settings.Initialize(settings_path()));
   UUID actual;
   EXPECT_TRUE(local_settings.GetClientID(&actual));
   EXPECT_EQ(actual, client_id);
@@ -81,8 +81,8 @@
   EXPECT_TRUE(settings()->GetUploadsEnabled(&enabled));
   EXPECT_TRUE(enabled);
 
-  Settings local_settings(settings_path());
-  EXPECT_TRUE(local_settings.Initialize());
+  Settings local_settings;
+  EXPECT_TRUE(local_settings.Initialize(settings_path()));
   enabled = false;
   EXPECT_TRUE(local_settings.GetUploadsEnabled(&enabled));
   EXPECT_TRUE(enabled);
@@ -107,8 +107,8 @@
   EXPECT_TRUE(settings()->GetLastUploadAttemptTime(&actual));
   EXPECT_EQ(actual, expected);
 
-  Settings local_settings(settings_path());
-  EXPECT_TRUE(local_settings.Initialize());
+  Settings local_settings;
+  EXPECT_TRUE(local_settings.Initialize(settings_path()));
   actual = -1;
   EXPECT_TRUE(local_settings.GetLastUploadAttemptTime(&actual));
   EXPECT_EQ(actual, expected);
@@ -120,8 +120,8 @@
 TEST_F(SettingsTest, BadFileOnInitialize) {
   InitializeBadFile();
 
-  Settings settings(settings_path());
-  EXPECT_TRUE(settings.Initialize());
+  Settings settings;
+  EXPECT_TRUE(settings.Initialize(settings_path()));
 }
 
 TEST_F(SettingsTest, BadFileOnGet) {
@@ -131,8 +131,8 @@
   EXPECT_TRUE(settings()->GetClientID(&client_id));
   EXPECT_NE(client_id, UUID());
 
-  Settings local_settings(settings_path());
-  EXPECT_TRUE(local_settings.Initialize());
+  Settings local_settings;
+  EXPECT_TRUE(local_settings.Initialize(settings_path()));
   UUID actual;
   EXPECT_TRUE(local_settings.GetClientID(&actual));
   EXPECT_EQ(actual, client_id);
@@ -161,8 +161,8 @@
       << ErrnoMessage("unlink");
 #endif
 
-  Settings local_settings(settings_path());
-  EXPECT_TRUE(local_settings.Initialize());
+  Settings local_settings;
+  EXPECT_TRUE(local_settings.Initialize(settings_path()));
   UUID new_client_id;
   EXPECT_TRUE(local_settings.GetClientID(&new_client_id));
   EXPECT_NE(new_client_id, client_id);
diff --git a/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc b/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc
index 6f85e85..5fdeb5b 100644
--- a/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc
+++ b/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc
@@ -253,21 +253,30 @@
 
 #if DCHECK_IS_ON()
 
-TEST(SimpleStringDictionaryDeathTest, NullKey) {
+TEST(SimpleStringDictionaryDeathTest, SetKeyValueWithNullKey) {
   TSimpleStringDictionary<4, 6, 6> map;
   ASSERT_DEATH_CHECK(map.SetKeyValue(nullptr, "hello"), "key");
+}
 
+TEST(SimpleStringDictionaryDeathTest, GetValueForKeyWithNullKey) {
+  TSimpleStringDictionary<4, 6, 6> map;
   map.SetKeyValue("hi", "there");
   ASSERT_DEATH_CHECK(map.GetValueForKey(nullptr), "key");
   EXPECT_STREQ("there", map.GetValueForKey("hi"));
-
-  ASSERT_DEATH_CHECK(map.GetValueForKey(nullptr), "key");
-  map.RemoveKey("hi");
-  EXPECT_EQ(map.GetCount(), 0u);
 }
 
 #endif
 
+// The tests above, without DEATH_CHECK assertions.
+TEST(SimpleStringDictionaryDeathTest, GetValueForKeyWithoutNullKey) {
+  TSimpleStringDictionary<4, 6, 6> map;
+
+  map.SetKeyValue("hi", "there");
+  EXPECT_STREQ("there", map.GetValueForKey("hi"));
+  map.RemoveKey("hi");
+  EXPECT_EQ(map.GetCount(), 0u);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/simulate_crash.h b/third_party/crashpad/crashpad/client/simulate_crash.h
index 299fe97..63e09a1 100644
--- a/third_party/crashpad/crashpad/client/simulate_crash.h
+++ b/third_party/crashpad/crashpad/client/simulate_crash.h
@@ -21,6 +21,8 @@
 #include "client/simulate_crash_mac.h"
 #elif defined(OS_WIN)
 #include "client/simulate_crash_win.h"
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+#include "client/simulate_crash_linux.h"
 #endif
 
 #endif  // CRASHPAD_CLIENT_SIMULATE_CRASH_H_
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_linux.h b/third_party/crashpad/crashpad/client/simulate_crash_linux.h
new file mode 100644
index 0000000..e6c3e487
--- /dev/null
+++ b/third_party/crashpad/crashpad/client/simulate_crash_linux.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_CLIENT_SIMULATE_CRASH_LINUX_H_
+#define CRASHPAD_CLIENT_SIMULATE_CRASH_LINUX_H_
+
+#include "client/crashpad_client.h"
+#include "util/misc/capture_context.h"
+
+//! \file
+
+//! \brief Captures the CPU context and simulates an exception without crashing.
+#define CRASHPAD_SIMULATE_CRASH()                                            \
+  do {                                                                       \
+    crashpad::NativeCPUContext simulate_crash_cpu_context;                   \
+    crashpad::CaptureContext(&simulate_crash_cpu_context);                   \
+    crashpad::CrashpadClient::DumpWithoutCrash(&simulate_crash_cpu_context); \
+  } while (false)
+
+#endif  // CRASHPAD_CLIENT_SIMULATE_CRASH_LINUX_H_
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac.h b/third_party/crashpad/crashpad/client/simulate_crash_mac.h
index e14db3c..dcbcaae 100644
--- a/third_party/crashpad/crashpad/client/simulate_crash_mac.h
+++ b/third_party/crashpad/crashpad/client/simulate_crash_mac.h
@@ -17,7 +17,7 @@
 
 #include <mach/mach.h>
 
-#include "client/capture_context_mac.h"
+#include "util/misc/capture_context.h"
 
 //! \file
 
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_win.h b/third_party/crashpad/crashpad/client/simulate_crash_win.h
index a20f3da..140424f 100644
--- a/third_party/crashpad/crashpad/client/simulate_crash_win.h
+++ b/third_party/crashpad/crashpad/client/simulate_crash_win.h
@@ -18,16 +18,17 @@
 #include <windows.h>
 
 #include "client/crashpad_client.h"
-#include "util/win/capture_context.h"
+#include "util/misc/capture_context.h"
 
 //! \file
 
 //! \brief Captures the CPU context and captures a dump without an exception.
-#define CRASHPAD_SIMULATE_CRASH()                        \
-  do {                                                   \
-    CONTEXT context;                                     \
-    crashpad::CaptureContext(&context);                  \
-    crashpad::CrashpadClient::DumpWithoutCrash(context); \
+#define CRASHPAD_SIMULATE_CRASH()                                           \
+  do {                                                                      \
+    /* Not "context" to avoid variable shadowing warnings. */               \
+    CONTEXT simulate_crash_cpu_context;                                     \
+    crashpad::CaptureContext(&simulate_crash_cpu_context);                  \
+    crashpad::CrashpadClient::DumpWithoutCrash(simulate_crash_cpu_context); \
   } while (false)
 
 #endif  // CRASHPAD_CLIENT_SIMULATE_CRASH_WIN_H_
diff --git a/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn
index 9c337697..b3370fc 100644
--- a/third_party/crashpad/crashpad/handler/BUILD.gn
+++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -18,6 +18,8 @@
   sources = [
     "crash_report_upload_thread.cc",
     "crash_report_upload_thread.h",
+    "handler_main.cc",
+    "handler_main.h",
     "minidump_to_upload_parameters.cc",
     "minidump_to_upload_parameters.h",
     "prune_crash_reports_thread.cc",
@@ -39,14 +41,11 @@
 
   if (crashpad_is_linux || crashpad_is_android) {
     sources += [
+      "linux/crash_report_exception_handler.cc",
+      "linux/crash_report_exception_handler.h",
       "linux/exception_handler_server.cc",
       "linux/exception_handler_server.h",
     ]
-  } else {
-    sources += [
-      "handler_main.cc",
-      "handler_main.h",
-    ]
   }
 
   if (crashpad_is_win) {
@@ -147,8 +146,15 @@
   }
 
   if (crashpad_is_win) {
-    configs -= [ "//build/config/win:console" ]
-    configs += [ "//build/config/win:windowed" ]
+    if (crashpad_is_in_chromium) {
+      configs -= [ "//build/config/win:console" ]
+      configs += [ "//build/config/win:windowed" ]
+    } else {
+      configs -=
+          [ "//third_party/mini_chromium/mini_chromium/build:win_console" ]
+      configs +=
+          [ "//third_party/mini_chromium/mini_chromium/build:win_windowed" ]
+    }
   }
 }
 
@@ -199,4 +205,108 @@
       "$root_out_dir/crashpad_handler.com",
     ]
   }
+
+  executable("crash_other_program") {
+    testonly = true
+
+    sources = [
+      "win/crash_other_program.cc",
+    ]
+
+    deps = [
+      "../client",
+      "../test",
+      "../third_party/gtest:gtest",
+      "../third_party/mini_chromium:base",
+    ]
+  }
+
+  executable("crashy_program") {
+    testonly = true
+
+    sources = [
+      "win/crashy_test_program.cc",
+    ]
+
+    deps = [
+      "../client",
+      "../third_party/mini_chromium:base",
+    ]
+  }
+
+  executable("crashy_signal") {
+    testonly = true
+
+    sources = [
+      "win/crashy_signal.cc",
+    ]
+
+    cflags = [ "/wd4702" ]  # Unreachable code.
+
+    deps = [
+      "../client",
+      "../third_party/mini_chromium:base",
+    ]
+  }
+
+  executable("fake_handler_that_crashes_at_startup") {
+    testonly = true
+
+    sources = [
+      "win/fake_handler_that_crashes_at_startup.cc",
+    ]
+  }
+
+  executable("hanging_program") {
+    testonly = true
+
+    sources = [
+      "win/hanging_program.cc",
+    ]
+
+    deps = [
+      "../client",
+      "../third_party/mini_chromium:base",
+    ]
+  }
+
+  loadable_module("loader_lock_dll") {
+    testonly = true
+
+    sources = [
+      "win/loader_lock_dll.cc",
+    ]
+  }
+
+  executable("self_destroying_program") {
+    testonly = true
+
+    sources = [
+      "win/self_destroying_test_program.cc",
+    ]
+
+    deps = [
+      "../client",
+      "../compat",
+      "../snapshot",
+      "../third_party/mini_chromium:base",
+    ]
+  }
+
+  if (current_cpu == "x86") {
+    # Cannot create an x64 DLL with embedded debug info.
+    executable("crashy_z7_loader") {
+      testonly = true
+
+      sources = [
+        "win/crashy_test_z7_loader.cc",
+      ]
+
+      deps = [
+        "../client",
+        "../test",
+        "../third_party/mini_chromium:base",
+      ]
+    }
+  }
 }
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
index 7505524..715c533 100644
--- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
+++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
@@ -45,44 +45,6 @@
 
 namespace crashpad {
 
-namespace {
-
-// Calls CrashReportDatabase::RecordUploadAttempt() with |successful| set to
-// false upon destruction unless disarmed by calling Fire() or Disarm(). Fire()
-// triggers an immediate call. Armed upon construction.
-class CallRecordUploadAttempt {
- public:
-  CallRecordUploadAttempt(CrashReportDatabase* database,
-                          const CrashReportDatabase::Report* report)
-      : database_(database),
-        report_(report) {
-  }
-
-  ~CallRecordUploadAttempt() {
-    Fire();
-  }
-
-  void Fire() {
-    if (report_) {
-      database_->RecordUploadAttempt(report_, false, std::string());
-    }
-
-    Disarm();
-  }
-
-  void Disarm() {
-    report_ = nullptr;
-  }
-
- private:
-  CrashReportDatabase* database_;  // weak
-  const CrashReportDatabase::Report* report_;  // weak
-
-  DISALLOW_COPY_AND_ASSIGN(CallRecordUploadAttempt);
-};
-
-}  // namespace
-
 CrashReportUploadThread::CrashReportUploadThread(CrashReportDatabase* database,
                                                  const std::string& url,
                                                  const Options& options)
@@ -96,11 +58,18 @@
                                             : WorkerThread::kIndefiniteWait,
               this),
       known_pending_report_uuids_(),
-      database_(database) {}
+      database_(database) {
+  DCHECK(!url_.empty());
+}
 
 CrashReportUploadThread::~CrashReportUploadThread() {
 }
 
+void CrashReportUploadThread::ReportPending(const UUID& report_uuid) {
+  known_pending_report_uuids_.PushBack(report_uuid);
+  thread_.DoWorkNow();
+}
+
 void CrashReportUploadThread::Start() {
   thread_.Start(
       options_.watch_pending_reports ? 0.0 : WorkerThread::kIndefiniteWait);
@@ -110,11 +79,6 @@
   thread_.Stop();
 }
 
-void CrashReportUploadThread::ReportPending(const UUID& report_uuid) {
-  known_pending_report_uuids_.PushBack(report_uuid);
-  thread_.DoWorkNow();
-}
-
 void CrashReportUploadThread::ProcessPendingReports() {
   std::vector<UUID> known_report_uuids = known_pending_report_uuids_.Drain();
   for (const UUID& report_uuid : known_report_uuids) {
@@ -178,9 +142,8 @@
   Settings* const settings = database_->GetSettings();
 
   bool uploads_enabled;
-  if (url_.empty() ||
-      (!report.upload_explicitly_requested &&
-       (!settings->GetUploadsEnabled(&uploads_enabled) || !uploads_enabled))) {
+  if (!report.upload_explicitly_requested &&
+      (!settings->GetUploadsEnabled(&uploads_enabled) || !uploads_enabled)) {
     // Don’t attempt an upload if there’s no URL to upload to. Allow upload if
     // it has been explicitly requested by the user, otherwise, respect the
     // upload-enabled state stored in the database’s settings.
@@ -229,7 +192,7 @@
     }
   }
 
-  const CrashReportDatabase::Report* upload_report;
+  std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report;
   CrashReportDatabase::OperationStatus status =
       database_->GetReportForUploading(report.uuid, &upload_report);
   switch (status) {
@@ -256,18 +219,16 @@
       return;
   }
 
-  CallRecordUploadAttempt call_record_upload_attempt(database_, upload_report);
-
   std::string response_body;
-  UploadResult upload_result = UploadReport(upload_report, &response_body);
+  UploadResult upload_result =
+      UploadReport(upload_report.get(), &response_body);
   switch (upload_result) {
     case UploadResult::kSuccess:
-      call_record_upload_attempt.Disarm();
-      database_->RecordUploadAttempt(upload_report, true, response_body);
+      database_->RecordUploadComplete(std::move(upload_report), response_body);
       break;
     case UploadResult::kPermanentFailure:
     case UploadResult::kRetry:
-      call_record_upload_attempt.Fire();
+      upload_report.reset();
 
       // TODO(mark): Deal with retries properly: don’t call SkipReportUplaod()
       // if the result was kRetry and the report hasn’t already been retried
@@ -279,17 +240,18 @@
 }
 
 CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport(
-    const CrashReportDatabase::Report* report,
+    const CrashReportDatabase::UploadReport* report,
     std::string* response_body) {
+#if defined(OS_ANDROID)
+  // TODO(jperaza): This method can be enabled on Android after HTTPTransport is
+  // implemented and Crashpad takes over upload responsibilty on Android.
+  NOTREACHED();
+  return UploadResult::kPermanentFailure;
+#else
   std::map<std::string, std::string> parameters;
 
-  FileReader minidump_file_reader;
-  if (!minidump_file_reader.Open(report->file_path)) {
-    // If the minidump file can’t be opened, all hope is lost.
-    return UploadResult::kPermanentFailure;
-  }
-
-  FileOffset start_offset = minidump_file_reader.SeekGet();
+  FileReader* reader = report->Reader();
+  FileOffset start_offset = reader->SeekGet();
   if (start_offset < 0) {
     return UploadResult::kPermanentFailure;
   }
@@ -299,12 +261,12 @@
   // parameters, but as long as there’s a dump file, the server can decide what
   // to do with it.
   ProcessSnapshotMinidump minidump_process_snapshot;
-  if (minidump_process_snapshot.Initialize(&minidump_file_reader)) {
+  if (minidump_process_snapshot.Initialize(reader)) {
     parameters =
         BreakpadHTTPFormParametersFromMinidump(&minidump_process_snapshot);
   }
 
-  if (!minidump_file_reader.SeekSet(start_offset)) {
+  if (!reader->SeekSet(start_offset)) {
     return UploadResult::kPermanentFailure;
   }
 
@@ -322,15 +284,10 @@
     }
   }
 
-  http_multipart_builder.SetFileAttachment(
-      kMinidumpKey,
-#if defined(OS_WIN)
-      base::UTF16ToUTF8(report->file_path.BaseName().value()),
-#else
-      report->file_path.BaseName().value(),
-#endif
-      &minidump_file_reader,
-      "application/octet-stream");
+  http_multipart_builder.SetFileAttachment(kMinidumpKey,
+                                           report->uuid.ToString() + ".dmp",
+                                           reader,
+                                           "application/octet-stream");
 
   std::unique_ptr<HTTPTransport> http_transport(HTTPTransport::Create());
   HTTPHeaders content_headers;
@@ -372,6 +329,7 @@
   }
 
   return UploadResult::kSuccess;
+#endif  // OS_ANDROID
 }
 
 void CrashReportUploadThread::DoWork(const WorkerThread* thread) {
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
index cdd1502..2ec1147d 100644
--- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
+++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
@@ -22,6 +22,7 @@
 #include "client/crash_report_database.h"
 #include "util/misc/uuid.h"
 #include "util/stdlib/thread_safe_vector.h"
+#include "util/thread/stoppable.h"
 #include "util/thread/worker_thread.h"
 
 namespace crashpad {
@@ -39,7 +40,8 @@
 //! It also catches reports that are added without a ReportPending() signal
 //! being caught. This may happen if crash reports are added to the database by
 //! other processes.
-class CrashReportUploadThread : public WorkerThread::Delegate {
+class CrashReportUploadThread : public WorkerThread::Delegate,
+                                public Stoppable {
  public:
    //! \brief Options to be passed to the CrashReportUploadThread constructor.
    struct Options {
@@ -70,11 +72,22 @@
                           const Options& options);
   ~CrashReportUploadThread();
 
+  //! \brief Informs the upload thread that a new pending report has been added
+  //!     to the database.
+  //!
+  //! \param[in] report_uuid The unique identifier of the newly added pending
+  //!     report.
+  //!
+  //! This method may be called from any thread.
+  void ReportPending(const UUID& report_uuid);
+
+  // Stoppable:
+
   //! \brief Starts a dedicated upload thread, which executes ThreadMain().
   //!
   //! This method may only be be called on a newly-constructed object or after
   //! a call to Stop().
-  void Start();
+  void Start() override;
 
   //! \brief Stops the upload thread.
   //!
@@ -88,16 +101,7 @@
   //!
   //! This method may be called from any thread other than the upload thread.
   //! It is expected to only be called from the same thread that called Start().
-  void Stop();
-
-  //! \brief Informs the upload thread that a new pending report has been added
-  //!     to the database.
-  //!
-  //! \param[in] report_uuid The unique identifier of the newly added pending
-  //!     report.
-  //!
-  //! This method may be called from any thread.
-  void ReportPending(const UUID& report_uuid);
+  void Stop() override;
 
  private:
   //! \brief The result code from UploadReport().
@@ -148,14 +152,14 @@
   //! \param[in] report The report to upload. The caller is responsible for
   //!     calling CrashReportDatabase::GetReportForUploading() before calling
   //!     this method, and for calling
-  //!     CrashReportDatabase::RecordUploadAttempt() after calling this method.
+  //!     CrashReportDatabase::RecordUploadComplete() after calling this method.
   //! \param[out] response_body If the upload attempt is successful, this will
   //!     be set to the response body sent by the server. Breakpad-type servers
   //!     provide the crash ID assigned by the server in the response body.
   //!
   //! \return A member of UploadResult indicating the result of the upload
   //!    attempt.
-  UploadResult UploadReport(const CrashReportDatabase::Report* report,
+  UploadResult UploadReport(const CrashReportDatabase::UploadReport* report,
                             std::string* response_body);
 
   // WorkerThread::Delegate:
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler.md b/third_party/crashpad/crashpad/handler/crashpad_handler.md
index 5eff39a..003ee2e 100644
--- a/third_party/crashpad/crashpad/handler/crashpad_handler.md
+++ b/third_party/crashpad/crashpad/handler/crashpad_handler.md
@@ -73,6 +73,13 @@
 stdio will be hooked up as expected to the parent console so that logging output
 will be visible.
 
+On Linux/Android, the handler may create a crash dump for its parent process
+using **--trace-parent-with-exception**. In this mode, the handler process
+creates a crash dump for its parent and exits. Alternatively, the handler may
+be launched with **--initial-client-fd** which will start the server connected
+to an initial client. The server will exit when all connected client sockets are
+closed.
+
 It is not normally appropriate to invoke this program directly. Usually, it will
 be invoked by a Crashpad client using the Crashpad client library, or started by
 another system service. On macOS, arbitrary programs may be run with a Crashpad
@@ -238,6 +245,18 @@
    parent process. This option is only valid on macOS. Use of this option is
    discouraged. It should not be used absent extraordinary circumstances.
 
+ * **--trace-parent-with-exception**=_EXCEPTION-INFORMATION-ADDRESS_
+
+   Causes the handler process to trace its parent process and exit. The parent
+   process should have an ExceptionInformation struct at
+   _EXCEPTION-INFORMATION-ADDRESS_.
+
+ * **--initial-client-fd**=_FD_
+
+   Starts the excetion handler server with an initial ExceptionHandlerClient
+   connected on the socket _FD_. The server will exit when all connected client
+   sockets have been closed.
+
  * **--url**=_URL_
 
    If uploads are enabled, sends crash reports to the Breakpad-type crash report
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
index 65fed90f..79076b8 100644
--- a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
+++ b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
@@ -28,7 +28,7 @@
 #include "test/test_paths.h"
 #include "test/win/win_multiprocess_with_temp_dir.h"
 #include "util/file/file_reader.h"
-#include "util/win/capture_context.h"
+#include "util/misc/capture_context.h"
 
 namespace crashpad {
 namespace test {
diff --git a/third_party/crashpad/crashpad/handler/handler.gyp b/third_party/crashpad/crashpad/handler/handler.gyp
index 8263dfd..60a6f251 100644
--- a/third_party/crashpad/crashpad/handler/handler.gyp
+++ b/third_party/crashpad/crashpad/handler/handler.gyp
@@ -39,6 +39,8 @@
         'crash_report_upload_thread.h',
         'handler_main.cc',
         'handler_main.h',
+        'linux/crash_report_exception_handler.cc',
+        'linux/crash_report_exception_handler.h',
         'linux/exception_handler_server.cc',
         'linux/exception_handler_server.h',
         'mac/crash_report_exception_handler.cc',
@@ -56,13 +58,6 @@
         'win/crash_report_exception_handler.cc',
         'win/crash_report_exception_handler.h',
       ],
-      'conditions': [
-        ['OS=="linux" or OS=="android"', {
-          'sources!': [
-            'handler_main.cc',
-          ],
-        }],
-      ],
       'target_conditions': [
         ['OS=="android"', {
           'sources/': [
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index f175fddf..dd7adf6 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -34,6 +34,7 @@
 #include "base/logging.h"
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/scoped_generic.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -46,6 +47,7 @@
 #include "handler/prune_crash_reports_thread.h"
 #include "tools/tool_support.h"
 #include "util/file/file_io.h"
+#include "util/misc/address_types.h"
 #include "util/misc/metrics.h"
 #include "util/misc/paths.h"
 #include "util/numeric/in_range_cast.h"
@@ -54,7 +56,13 @@
 #include "util/string/split_string.h"
 #include "util/synchronization/semaphore.h"
 
-#if defined(OS_MACOSX)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+#include <unistd.h>
+
+#include "handler/linux/crash_report_exception_handler.h"
+#include "handler/linux/exception_handler_server.h"
+#include "util/posix/signals.h"
+#elif defined(OS_MACOSX)
 #include <libgen.h>
 #include <signal.h>
 
@@ -77,6 +85,9 @@
 #elif defined(OS_FUCHSIA)
 #include "handler/fuchsia/crash_report_exception_handler.h"
 #include "handler/fuchsia/exception_handler_server.h"
+#elif defined(OS_LINUX)
+#include "handler/linux/crash_report_exception_handler.h"
+#include "handler/linux/exception_handler_server.h"
 #endif  // OS_MACOSX
 
 namespace crashpad {
@@ -126,6 +137,11 @@
 "      --reset-own-crash-exception-port-to-system-default\n"
 "                              reset the server's exception handler to default\n"
 #endif  // OS_MACOSX
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+"      --trace-parent-with-exception=EXCEPTION_INFORMATION_ADDRESS\n"
+"                              request a dump for the handler's parent process\n"
+"      --initial-client-fd=FD  a socket connected to a client.\n"
+#endif  // OS_LINUX || OS_ANDROID
 "      --url=URL               send crash reports to this Breakpad server URL,\n"
 "                              only if uploads are enabled for the database\n"
 "      --help                  display this help and exit\n"
@@ -145,6 +161,9 @@
   std::string mach_service;
   int handshake_fd;
   bool reset_own_crash_exception_port_to_system_default;
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+  VMAddress exception_information_address;
+  int initial_client_fd;
 #elif defined(OS_WIN)
   std::string pipe_name;
   InitialClientData initial_client_data;
@@ -211,7 +230,9 @@
   DISALLOW_COPY_AND_ASSIGN(CallMetricsRecordNormalExit);
 };
 
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
+
+Signals::OldActions g_old_crash_signal_handlers;
 
 void HandleCrashSignal(int sig, siginfo_t* siginfo, void* context) {
   MetricsRecordExit(Metrics::LifetimeMilestone::kCrashed);
@@ -247,7 +268,9 @@
   }
   Metrics::HandlerCrashed(metrics_code);
 
-  Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
+  struct sigaction* old_action =
+      g_old_crash_signal_handlers.ActionForSignal(sig);
+  Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, old_action);
 }
 
 void HandleTerminateSignal(int sig, siginfo_t* siginfo, void* context) {
@@ -255,6 +278,8 @@
   Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr);
 }
 
+#if defined(OS_MACOSX)
+
 void ReinstallCrashHandler() {
   // This is used to re-enable the metrics-recording crash handler after
   // MonitorSelf() sets up a Crashpad exception handler. On macOS, the
@@ -293,6 +318,23 @@
   g_exception_handler_server->Stop();
 }
 
+#else
+
+void ReinstallCrashHandler() {
+  // This is used to re-enable the metrics-recording crash handler after
+  // MonitorSelf() sets up a Crashpad signal handler.
+  Signals::InstallCrashHandlers(
+      HandleCrashSignal, 0, &g_old_crash_signal_handlers);
+}
+
+void InstallCrashHandler() {
+  ReinstallCrashHandler();
+
+  Signals::InstallTerminateHandlers(HandleTerminateSignal, 0, nullptr);
+}
+
+#endif  // OS_MACOSX
+
 #elif defined(OS_WIN)
 
 LONG(WINAPI* g_original_exception_filter)(EXCEPTION_POINTERS*) = nullptr;
@@ -348,14 +390,18 @@
   ALLOW_UNUSED_LOCAL(terminate_handler);
 }
 
-#elif defined(OS_FUCHSIA)
+#elif defined(OS_FUCHSIA) || defined(OS_LINUX)
 
 void InstallCrashHandler() {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
+  // TODO(scottmg): Fuchsia: https://crashpad.chromium.org/bug/196
+  // TODO(jperaza): Linux: https://crashpad.chromium.org/bug/30
+  NOTREACHED();
 }
 
 void ReinstallCrashHandler() {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
+  // TODO(scottmg): Fuchsia: https://crashpad.chromium.org/bug/196
+  // TODO(jperaza): Linux: https://crashpad.chromium.org/bug/30
+  NOTREACHED();
 }
 
 #endif  // OS_MACOSX
@@ -394,6 +440,16 @@
   // instance of crashpad_handler to be writing metrics at a time, and it should
   // be the primary instance.
   CrashpadClient crashpad_client;
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  if (!crashpad_client.StartHandlerAtCrash(executable_path,
+                                           options.database,
+                                           base::FilePath(),
+                                           options.url,
+                                           options.annotations,
+                                           extra_arguments)) {
+    return;
+  }
+#else
   if (!crashpad_client.StartHandler(executable_path,
                                     options.database,
                                     base::FilePath(),
@@ -404,12 +460,33 @@
                                     false)) {
     return;
   }
+#endif
 
   // Make sure that appropriate metrics will be recorded on crash before this
   // process is terminated.
   ReinstallCrashHandler();
 }
 
+class ScopedStoppable {
+ public:
+  ScopedStoppable() = default;
+
+  ~ScopedStoppable() {
+    if (stoppable_) {
+      stoppable_->Stop();
+    }
+  }
+
+  void Reset(Stoppable* stoppable) { stoppable_.reset(stoppable); }
+
+  Stoppable* Get() { return stoppable_.get(); }
+
+ private:
+  std::unique_ptr<Stoppable> stoppable_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedStoppable);
+};
+
 }  // namespace
 
 int HandlerMain(int argc,
@@ -450,6 +527,10 @@
 #if defined(OS_MACOSX)
     kOptionResetOwnCrashExceptionPortToSystemDefault,
 #endif  // OS_MACOSX
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+    kOptionTraceParentWithException,
+    kOptionInitialClientFD,
+#endif
     kOptionURL,
 
     // Standard options.
@@ -498,6 +579,13 @@
      nullptr,
      kOptionResetOwnCrashExceptionPortToSystemDefault},
 #endif  // OS_MACOSX
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+    {"trace-parent-with-exception",
+     required_argument,
+     nullptr,
+     kOptionTraceParentWithException},
+    {"initial-client-fd", required_argument, nullptr, kOptionInitialClientFD},
+#endif  // OS_LINUX || OS_ANDROID
     {"url", required_argument, nullptr, kOptionURL},
     {"help", no_argument, nullptr, kOptionHelp},
     {"version", no_argument, nullptr, kOptionVersion},
@@ -512,6 +600,10 @@
   options.periodic_tasks = true;
   options.rate_limit = true;
   options.upload_gzip = true;
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  options.exception_information_address = 0;
+  options.initial_client_fd = kInvalidFileHandle;
+#endif
 
   int opt;
   while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
@@ -601,6 +693,23 @@
         break;
       }
 #endif  // OS_MACOSX
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+      case kOptionTraceParentWithException: {
+        if (!StringToNumber(optarg, &options.exception_information_address)) {
+          ToolSupport::UsageHint(
+              me, "failed to parse --trace-parent-with-exception");
+          return ExitFailure();
+        }
+        break;
+      }
+      case kOptionInitialClientFD: {
+        if (!base::StringToInt(optarg, &options.initial_client_fd)) {
+          ToolSupport::UsageHint(me, "failed to parse --initial-client-fd");
+          return ExitFailure();
+        }
+        break;
+      }
+#endif  // OS_LINUX || OS_ANDROID
       case kOptionURL: {
         options.url = optarg;
         break;
@@ -645,6 +754,14 @@
         me, "--initial-client-data and --pipe-name are incompatible");
     return ExitFailure();
   }
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+  if (!options.exception_information_address &&
+      options.initial_client_fd == kInvalidFileHandle) {
+    ToolSupport::UsageHint(
+        me,
+        "--exception_information_address or --initial_client_fd is required");
+    return ExitFailure();
+  }
 #endif  // OS_MACOSX
 
   if (options.database.empty()) {
@@ -687,6 +804,50 @@
     }
   }
 
+  std::unique_ptr<CrashReportDatabase> database(
+      CrashReportDatabase::Initialize(options.database));
+  if (!database) {
+    return ExitFailure();
+  }
+
+  ScopedStoppable upload_thread;
+  if (!options.url.empty()) {
+    // TODO(scottmg): options.rate_limit should be removed when we have a
+    // configurable database setting to control upload limiting.
+    // See https://crashpad.chromium.org/bug/23.
+    CrashReportUploadThread::Options upload_thread_options;
+    upload_thread_options.identify_client_via_url =
+        options.identify_client_via_url;
+    upload_thread_options.rate_limit = options.rate_limit;
+    upload_thread_options.upload_gzip = options.upload_gzip;
+    upload_thread_options.watch_pending_reports = options.periodic_tasks;
+
+    upload_thread.Reset(new CrashReportUploadThread(
+        database.get(), options.url, upload_thread_options));
+    upload_thread.Get()->Start();
+  }
+
+  CrashReportExceptionHandler exception_handler(
+      database.get(),
+      static_cast<CrashReportUploadThread*>(upload_thread.Get()),
+      &options.annotations,
+      user_stream_sources);
+
+ #if defined(OS_LINUX) || defined(OS_ANDROID)
+  if (options.exception_information_address) {
+    return exception_handler.HandleException(getppid(),
+                                      options.exception_information_address) ?
+    EXIT_SUCCESS : ExitFailure();
+  }
+#endif  // OS_LINUX || OS_ANDROID
+
+  ScopedStoppable prune_thread;
+  if (options.periodic_tasks) {
+    prune_thread.Reset(new PruneCrashReportThread(
+        database.get(), PruneCondition::GetDefault()));
+    prune_thread.Get()->Start();
+  }
+
 #if defined(OS_MACOSX)
   if (options.mach_service.empty()) {
     // Don’t do this when being run by launchd. See launchd.plist(5).
@@ -740,7 +901,7 @@
   if (!options.pipe_name.empty()) {
     exception_handler_server.SetPipeName(base::UTF8ToUTF16(options.pipe_name));
   }
-#elif defined(OS_FUCHSIA)
+#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
   ExceptionHandlerServer exception_handler_server;
 #endif  // OS_MACOSX
 
@@ -757,52 +918,21 @@
 
   Metrics::HandlerLifetimeMilestone(Metrics::LifetimeMilestone::kStarted);
 
-  std::unique_ptr<CrashReportDatabase> database(
-      CrashReportDatabase::Initialize(options.database));
-  if (!database) {
-    return ExitFailure();
-  }
-
-  // TODO(scottmg): options.rate_limit should be removed when we have a
-  // configurable database setting to control upload limiting.
-  // See https://crashpad.chromium.org/bug/23.
-  CrashReportUploadThread::Options upload_thread_options;
-  upload_thread_options.identify_client_via_url =
-      options.identify_client_via_url;
-  upload_thread_options.rate_limit = options.rate_limit;
-  upload_thread_options.upload_gzip = options.upload_gzip;
-  upload_thread_options.watch_pending_reports = options.periodic_tasks;
-  CrashReportUploadThread upload_thread(database.get(),
-                                        options.url,
-                                        upload_thread_options);
-  upload_thread.Start();
-
-  std::unique_ptr<PruneCrashReportThread> prune_thread;
-  if (options.periodic_tasks) {
-    prune_thread.reset(new PruneCrashReportThread(
-        database.get(), PruneCondition::GetDefault()));
-    prune_thread->Start();
-  }
-
-  CrashReportExceptionHandler exception_handler(database.get(),
-                                                &upload_thread,
-                                                &options.annotations,
-                                                user_stream_sources);
-
 #if defined(OS_WIN)
   if (options.initial_client_data.IsValid()) {
     exception_handler_server.InitializeWithInheritedDataForInitialClient(
         options.initial_client_data, &exception_handler);
   }
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+  if (options.initial_client_fd == kInvalidFileHandle ||
+             !exception_handler_server.InitializeWithClient(
+                 ScopedFileHandle(options.initial_client_fd))) {
+    return ExitFailure();
+  }
 #endif  // OS_WIN
 
   exception_handler_server.Run(&exception_handler);
 
-  upload_thread.Stop();
-  if (prune_thread) {
-    prune_thread->Stop();
-  }
-
   return EXIT_SUCCESS;
 }
 
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc
new file mode 100644
index 0000000..3aa46981
--- /dev/null
+++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc
@@ -0,0 +1,153 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "handler/linux/crash_report_exception_handler.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "client/settings.h"
+#include "minidump/minidump_file_writer.h"
+#include "snapshot/crashpad_info_client_options.h"
+#include "snapshot/linux/process_snapshot_linux.h"
+#include "util/linux/direct_ptrace_connection.h"
+#include "util/linux/ptrace_client.h"
+#include "util/misc/metrics.h"
+#include "util/misc/tri_state.h"
+#include "util/misc/uuid.h"
+
+namespace crashpad {
+
+CrashReportExceptionHandler::CrashReportExceptionHandler(
+    CrashReportDatabase* database,
+    CrashReportUploadThread* upload_thread,
+    const std::map<std::string, std::string>* process_annotations,
+    const UserStreamDataSources* user_stream_data_sources)
+    : database_(database),
+      upload_thread_(upload_thread),
+      process_annotations_(process_annotations),
+      user_stream_data_sources_(user_stream_data_sources) {}
+
+CrashReportExceptionHandler::~CrashReportExceptionHandler() = default;
+
+bool CrashReportExceptionHandler::HandleException(
+    pid_t client_process_id,
+    VMAddress exception_info_address) {
+  Metrics::ExceptionEncountered();
+
+  DirectPtraceConnection connection;
+  if (!connection.Initialize(client_process_id)) {
+    Metrics::ExceptionCaptureResult(
+        Metrics::CaptureResult::kDirectPtraceFailed);
+    return false;
+  }
+
+  return HandleExceptionWithConnection(&connection, exception_info_address);
+}
+
+bool CrashReportExceptionHandler::HandleExceptionWithBroker(
+    pid_t client_process_id,
+    VMAddress exception_info_address,
+    int broker_sock) {
+  Metrics::ExceptionEncountered();
+
+  PtraceClient client;
+  if (client.Initialize(broker_sock, client_process_id)) {
+    Metrics::ExceptionCaptureResult(
+        Metrics::CaptureResult::kBrokeredPtraceFailed);
+    return false;
+  }
+
+  return HandleExceptionWithConnection(&client, exception_info_address);
+}
+
+bool CrashReportExceptionHandler::HandleExceptionWithConnection(
+    PtraceConnection* connection,
+    VMAddress exception_info_address) {
+  ProcessSnapshotLinux process_snapshot;
+  if (!process_snapshot.Initialize(connection)) {
+    Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed);
+    return false;
+  }
+
+  if (!process_snapshot.InitializeException(exception_info_address)) {
+    Metrics::ExceptionCaptureResult(
+        Metrics::CaptureResult::kExceptionInitializationFailed);
+    return false;
+  }
+
+  Metrics::ExceptionCode(process_snapshot.Exception()->Exception());
+
+  CrashpadInfoClientOptions client_options;
+  process_snapshot.GetCrashpadOptions(&client_options);
+  if (client_options.crashpad_handler_behavior != TriState::kDisabled) {
+    UUID client_id;
+    Settings* const settings = database_->GetSettings();
+    if (settings) {
+      // If GetSettings() or GetClientID() fails, something else will log a
+      // message and client_id will be left at its default value, all zeroes,
+      // which is appropriate.
+      settings->GetClientID(&client_id);
+    }
+
+    process_snapshot.SetClientID(client_id);
+    process_snapshot.SetAnnotationsSimpleMap(*process_annotations_);
+
+    std::unique_ptr<CrashReportDatabase::NewReport> new_report;
+    CrashReportDatabase::OperationStatus database_status =
+        database_->PrepareNewCrashReport(&new_report);
+    if (database_status != CrashReportDatabase::kNoError) {
+      LOG(ERROR) << "PrepareNewCrashReport failed";
+      Metrics::ExceptionCaptureResult(
+          Metrics::CaptureResult::kPrepareNewCrashReportFailed);
+      return false;
+    }
+
+    process_snapshot.SetReportID(new_report->ReportID());
+
+    MinidumpFileWriter minidump;
+    minidump.InitializeFromSnapshot(&process_snapshot);
+    AddUserExtensionStreams(
+        user_stream_data_sources_, &process_snapshot, &minidump);
+
+    if (!minidump.WriteEverything(new_report->Writer())) {
+      LOG(ERROR) << "WriteEverything failed";
+      Metrics::ExceptionCaptureResult(
+          Metrics::CaptureResult::kMinidumpWriteFailed);
+      return false;
+    }
+
+    UUID uuid;
+    database_status =
+        database_->FinishedWritingCrashReport(std::move(new_report), &uuid);
+    if (database_status != CrashReportDatabase::kNoError) {
+      LOG(ERROR) << "FinishedWritingCrashReport failed";
+      Metrics::ExceptionCaptureResult(
+          Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
+      return false;
+    }
+
+    if (upload_thread_) {
+      upload_thread_->ReportPending(uuid);
+    } else {
+      database_->SkipReportUpload(
+          uuid, Metrics::CrashSkippedReason::kUploadsDisabled);
+    }
+  }
+
+  Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
+  return true;
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h
new file mode 100644
index 0000000..ca14f81
--- /dev/null
+++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h
@@ -0,0 +1,86 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_
+#define CRASHPAD_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "client/crash_report_database.h"
+#include "handler/crash_report_upload_thread.h"
+#include "handler/linux/exception_handler_server.h"
+#include "handler/user_stream_data_source.h"
+#include "util/linux/ptrace_connection.h"
+#include "util/misc/address_types.h"
+
+namespace crashpad {
+
+//! \brief An exception handler that writes crash reports for exceptions
+//!     to a CrashReportDatabase.
+class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate {
+ public:
+  //! \brief Creates a new object that will store crash reports in \a database.
+  //!
+  //! \param[in] database The database to store crash reports in. Weak.
+  //! \param[in] upload_thread The upload thread to notify when a new crash
+  //!     report is written into \a database. Report upload is skipped if this
+  //!     value is `nullptr`.
+  //! \param[in] process_annotations A map of annotations to insert as
+  //!     process-level annotations into each crash report that is written. Do
+  //!     not confuse this with module-level annotations, which are under the
+  //!     control of the crashing process, and are used to implement Chrome’s
+  //!     “crash keys.” Process-level annotations are those that are beyond the
+  //!     control of the crashing process, which must reliably be set even if
+  //!     the process crashes before it’s able to establish its own annotations.
+  //!     To interoperate with Breakpad servers, the recommended practice is to
+  //!     specify values for the `"prod"` and `"ver"` keys as process
+  //!     annotations.
+  //! \param[in] user_stream_data_sources Data sources to be used to extend
+  //!     crash reports. For each crash report that is written, the data sources
+  //!     are called in turn. These data sources may contribute additional
+  //!     minidump streams. `nullptr` if not required.
+  CrashReportExceptionHandler(
+      CrashReportDatabase* database,
+      CrashReportUploadThread* upload_thread,
+      const std::map<std::string, std::string>* process_annotations,
+      const UserStreamDataSources* user_stream_data_sources);
+
+  ~CrashReportExceptionHandler();
+
+  // ExceptionHandlerServer::Delegate:
+
+  bool HandleException(pid_t client_process_id,
+                       VMAddress exception_info_address) override;
+
+  bool HandleExceptionWithBroker(pid_t client_process_id,
+                                 VMAddress exception_info_address,
+                                 int broker_sock) override;
+
+ private:
+  bool HandleExceptionWithConnection(PtraceConnection* connection,
+                                     VMAddress exception_info_address);
+
+  CrashReportDatabase* database_;  // weak
+  CrashReportUploadThread* upload_thread_;  // weak
+  const std::map<std::string, std::string>* process_annotations_;  // weak
+  const UserStreamDataSources* user_stream_data_sources_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_
diff --git a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc
index fb6c21a9..5b0c8ce 100644
--- a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc
+++ b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc
@@ -20,11 +20,11 @@
 #include "base/logging.h"
 #include "gtest/gtest.h"
 #include "test/errors.h"
-#include "test/linux/scoped_pr_set_ptracer.h"
 #include "test/multiprocess.h"
 #include "util/linux/direct_ptrace_connection.h"
 #include "util/linux/exception_handler_client.h"
 #include "util/linux/ptrace_client.h"
+#include "util/linux/scoped_pr_set_ptracer.h"
 #include "util/synchronization/semaphore.h"
 #include "util/thread/thread.h"
 
@@ -205,7 +205,7 @@
       // If the current ptrace_scope is restricted, the broker needs to be set
       // as the ptracer for this process. Setting this process as its own
       // ptracer allows the broker to inherit this condition.
-      ScopedPrSetPtracer set_ptracer(getpid());
+      ScopedPrSetPtracer set_ptracer(getpid(), /* may_log= */ true);
 
       ExceptionHandlerClient client(server_test_->SockToHandler());
       ASSERT_EQ(client.RequestCrashDump(info), 0);
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc
index 6f9cdbe..edebf87 100644
--- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc
+++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc
@@ -14,6 +14,7 @@
 
 #include "handler/mac/crash_report_exception_handler.h"
 
+#include <utility>
 #include <vector>
 
 #include "base/logging.h"
@@ -155,7 +156,7 @@
     process_snapshot.SetClientID(client_id);
     process_snapshot.SetAnnotationsSimpleMap(*process_annotations_);
 
-    CrashReportDatabase::NewReport* new_report;
+    std::unique_ptr<CrashReportDatabase::NewReport> new_report;
     CrashReportDatabase::OperationStatus database_status =
         database_->PrepareNewCrashReport(&new_report);
     if (database_status != CrashReportDatabase::kNoError) {
@@ -164,35 +165,34 @@
       return KERN_FAILURE;
     }
 
-    process_snapshot.SetReportID(new_report->uuid);
-
-    CrashReportDatabase::CallErrorWritingCrashReport
-        call_error_writing_crash_report(database_, new_report);
-
-    WeakFileHandleFileWriter file_writer(new_report->handle);
+    process_snapshot.SetReportID(new_report->ReportID());
 
     MinidumpFileWriter minidump;
     minidump.InitializeFromSnapshot(&process_snapshot);
     AddUserExtensionStreams(
         user_stream_data_sources_, &process_snapshot, &minidump);
 
-    if (!minidump.WriteEverything(&file_writer)) {
+    if (!minidump.WriteEverything(new_report->Writer())) {
       Metrics::ExceptionCaptureResult(
           Metrics::CaptureResult::kMinidumpWriteFailed);
       return KERN_FAILURE;
     }
 
-    call_error_writing_crash_report.Disarm();
-
     UUID uuid;
-    database_status = database_->FinishedWritingCrashReport(new_report, &uuid);
+    database_status =
+        database_->FinishedWritingCrashReport(std::move(new_report), &uuid);
     if (database_status != CrashReportDatabase::kNoError) {
       Metrics::ExceptionCaptureResult(
           Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
       return KERN_FAILURE;
     }
 
-    upload_thread_->ReportPending(uuid);
+    if (upload_thread_) {
+      upload_thread_->ReportPending(uuid);
+    } else {
+      database_->SkipReportUpload(
+          uuid, Metrics::CrashSkippedReason::kUploadsDisabled);
+    }
   }
 
   if (client_options.system_crash_reporter_forwarding != TriState::kDisabled &&
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h
index cc314f1..0b44de6 100644
--- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h
+++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h
@@ -36,7 +36,8 @@
   //!
   //! \param[in] database The database to store crash reports in. Weak.
   //! \param[in] upload_thread The upload thread to notify when a new crash
-  //!     report is written into \a database.
+  //!     report is written into \a database. Report upload is skipped if this
+  //!     value is `nullptr`.
   //! \param[in] process_annotations A map of annotations to insert as
   //!     process-level annotations into each crash report that is written. Do
   //!     not confuse this with module-level annotations, which are under the
diff --git a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc
index 722275f5..7876c2fe 100644
--- a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc
+++ b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc
@@ -38,6 +38,7 @@
 }
 
 void PruneCrashReportThread::DoWork(const WorkerThread* thread) {
+  database_->CleanDatabase(60 * 60 * 24 * 3);
   PruneCrashReportDatabase(database_, condition_.get());
 }
 
diff --git a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h
index 72b69fc..0fd365b0 100644
--- a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h
+++ b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h
@@ -18,6 +18,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "util/thread/stoppable.h"
 #include "util/thread/worker_thread.h"
 
 namespace crashpad {
@@ -31,7 +32,7 @@
 //! After the thread is started, the database is pruned using the condition
 //! every 24 hours. Upon calling Start(), the thread waits 10 minutes before
 //! performing the initial prune operation.
-class PruneCrashReportThread : public WorkerThread::Delegate {
+class PruneCrashReportThread : public WorkerThread::Delegate, public Stoppable {
  public:
   //! \brief Constructs a new object.
   //!
@@ -42,6 +43,8 @@
                          std::unique_ptr<PruneCondition> condition);
   ~PruneCrashReportThread();
 
+  // Stoppable:
+
   //! \brief Starts a dedicated pruning thread.
   //!
   //! The thread waits before running the initial prune, so as to not interfere
@@ -49,7 +52,7 @@
   //!
   //! This method may only be be called on a newly-constructed object or after
   //! a call to Stop().
-  void Start();
+  void Start() override;
 
   //! \brief Stops the pruning thread.
   //!
@@ -58,7 +61,7 @@
   //!
   //! This method may be called from any thread other than the pruning thread.
   //! It is expected to only be called from the same thread that called Start().
-  void Stop();
+  void Stop() override;
 
  private:
   // WorkerThread::Delegate:
diff --git a/third_party/crashpad/crashpad/handler/win/crash_other_program.cc b/third_party/crashpad/crashpad/handler/win/crash_other_program.cc
index 55c0699..bbd25af 100644
--- a/third_party/crashpad/crashpad/handler/win/crash_other_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/crash_other_program.cc
@@ -122,7 +122,7 @@
   DWORD exit_code = child.WaitForExit();
   if (exit_code != expect_exit_code) {
     LOG(ERROR) << base::StringPrintf(
-        "incorrect exit code, expected 0x%x, observed 0x%x",
+        "incorrect exit code, expected 0x%lx, observed 0x%lx",
         expect_exit_code,
         exit_code);
     return EXIT_FAILURE;
diff --git a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc
index 0ab206c1..6d53d81 100644
--- a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc
+++ b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc
@@ -15,6 +15,7 @@
 #include "handler/win/crash_report_exception_handler.h"
 
 #include <type_traits>
+#include <utility>
 
 #include "client/crash_report_database.h"
 #include "client/settings.h"
@@ -59,7 +60,6 @@
                                    ProcessSuspensionState::kSuspended,
                                    exception_information_address,
                                    debug_critical_section_address)) {
-    LOG(WARNING) << "ProcessSnapshotWin::Initialize failed";
     Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed);
     return kTerminationCodeSnapshotFailed;
   }
@@ -90,7 +90,7 @@
     process_snapshot.SetClientID(client_id);
     process_snapshot.SetAnnotationsSimpleMap(*process_annotations_);
 
-    CrashReportDatabase::NewReport* new_report;
+    std::unique_ptr<CrashReportDatabase::NewReport> new_report;
     CrashReportDatabase::OperationStatus database_status =
         database_->PrepareNewCrashReport(&new_report);
     if (database_status != CrashReportDatabase::kNoError) {
@@ -100,29 +100,23 @@
       return termination_code;
     }
 
-    process_snapshot.SetReportID(new_report->uuid);
-
-    CrashReportDatabase::CallErrorWritingCrashReport
-        call_error_writing_crash_report(database_, new_report);
-
-    WeakFileHandleFileWriter file_writer(new_report->handle);
+    process_snapshot.SetReportID(new_report->ReportID());
 
     MinidumpFileWriter minidump;
     minidump.InitializeFromSnapshot(&process_snapshot);
     AddUserExtensionStreams(
         user_stream_data_sources_, &process_snapshot, &minidump);
 
-    if (!minidump.WriteEverything(&file_writer)) {
+    if (!minidump.WriteEverything(new_report->Writer())) {
       LOG(ERROR) << "WriteEverything failed";
       Metrics::ExceptionCaptureResult(
           Metrics::CaptureResult::kMinidumpWriteFailed);
       return termination_code;
     }
 
-    call_error_writing_crash_report.Disarm();
-
     UUID uuid;
-    database_status = database_->FinishedWritingCrashReport(new_report, &uuid);
+    database_status =
+        database_->FinishedWritingCrashReport(std::move(new_report), &uuid);
     if (database_status != CrashReportDatabase::kNoError) {
       LOG(ERROR) << "FinishedWritingCrashReport failed";
       Metrics::ExceptionCaptureResult(
@@ -130,7 +124,12 @@
       return termination_code;
     }
 
-    upload_thread_->ReportPending(uuid);
+    if (upload_thread_) {
+      upload_thread_->ReportPending(uuid);
+    } else {
+      database_->SkipReportUpload(
+          uuid, Metrics::CrashSkippedReason::kUploadsDisabled);
+    }
   }
 
   Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
diff --git a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h
index e1fb725d..c2781de3 100644
--- a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h
+++ b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h
@@ -37,7 +37,8 @@
   //!
   //! \param[in] database The database to store crash reports in. Weak.
   //! \param[in] upload_thread The upload thread to notify when a new crash
-  //!     report is written into \a database.
+  //!     report is written into \a database. Report upload is skipped if this
+  //!     value is `nullptr`.
   //! \param[in] process_annotations A map of annotations to insert as
   //!     process-level annotations into each crash report that is written. Do
   //!     not confuse this with module-level annotations, which are under the
diff --git a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
index a5532da8..a4f4797 100644
--- a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
+++ b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
@@ -21,6 +21,7 @@
 
 #include <map>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "base/files/file_path.h"
@@ -39,8 +40,8 @@
 
 namespace crashpad {
 
-int* g_extra_memory_pointer;
-int* g_extra_memory_not_saved;
+uint32_t* g_extra_memory_pointer;
+uint32_t* g_extra_memory_not_saved;
 
 namespace {
 
@@ -142,29 +143,33 @@
 
 void AllocateExtraMemoryToBeSaved(
     crashpad::SimpleAddressRangeBag* extra_ranges) {
-  constexpr size_t kNumInts = 2000;
-  int* extra_memory = new int[kNumInts];
+  constexpr size_t kNumVals = 2000;
+  auto extra_memory = new uint32_t[kNumVals];
   g_extra_memory_pointer = extra_memory;
-  for (int i = 0; i < kNumInts; ++i)
-    extra_memory[i] = i * 13 + 2;
-  extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumInts);
+  for (size_t i = 0; i < kNumVals; ++i)
+    extra_memory[i] =
+        static_cast<std::remove_reference<decltype(extra_memory[0])>::type>(
+            i * 13 + 2);
+  extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumVals);
   extra_ranges->Insert(&g_extra_memory_pointer, sizeof(g_extra_memory_pointer));
 }
 
 void AllocateExtraUnsavedMemory(crashpad::SimpleAddressRangeBag* extra_ranges) {
   // Allocate some extra memory, and then Insert() but also Remove() it so we
   // can confirm it doesn't get saved.
-  constexpr size_t kNumInts = 2000;
-  int* extra_memory = new int[kNumInts];
+  constexpr size_t kNumVals = 2000;
+  auto extra_memory = new uint32_t[kNumVals];
   g_extra_memory_not_saved = extra_memory;
-  for (int i = 0; i < kNumInts; ++i)
-    extra_memory[i] = i * 17 + 7;
-  extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumInts);
+  for (size_t i = 0; i < kNumVals; ++i)
+    extra_memory[i] =
+        static_cast<std::remove_reference<decltype(extra_memory[0])>::type>(
+            i * 17 + 7);
+  extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumVals);
   extra_ranges->Insert(&g_extra_memory_not_saved,
                        sizeof(g_extra_memory_not_saved));
 
   // We keep the pointer's memory, but remove the pointed-to memory.
-  extra_ranges->Remove(extra_memory, sizeof(extra_memory[0]) * kNumInts);
+  extra_ranges->Remove(extra_memory, sizeof(extra_memory[0]) * kNumVals);
 }
 
 int CrashyMain(int argc, wchar_t* argv[]) {
diff --git a/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc b/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc
index cfa098b2..63c145cf 100644
--- a/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc
+++ b/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc
@@ -55,7 +55,7 @@
   va_end(va);
 
   if (get_last_error) {
-    fprintf(stderr, ": error %u", last_error);
+    fprintf(stderr, ": error %lu", last_error);
   }
 
   fputs("\n", stderr);
diff --git a/third_party/crashpad/crashpad/infra/config/cq.cfg b/third_party/crashpad/crashpad/infra/config/cq.cfg
index d00ef14..64213fc3 100644
--- a/third_party/crashpad/crashpad/infra/config/cq.cfg
+++ b/third_party/crashpad/crashpad/infra/config/cq.cfg
@@ -35,14 +35,18 @@
       name: "master.client.crashpad"
       builders { name: "crashpad_try_mac_dbg" }
       builders { name: "crashpad_try_mac_rel" }
-      builders { name: "crashpad_try_win_x64_dbg" }
-      builders { name: "crashpad_try_win_x64_rel" }
+      builders { name: "crashpad_try_win_dbg" }
+      builders { name: "crashpad_try_win_rel" }
+      builders { name: "crashpad_try_linux_dbg" }
+      builders { name: "crashpad_try_linux_rel" }
+      # https://bugs.chromium.org/p/crashpad/issues/detail?id=219 QEMU runs are
+      # flaking; remove from CQ while being investigated.
+      #builders { name: "crashpad_try_fuchsia_x64_dbg" }
+      #builders { name: "crashpad_try_fuchsia_x64_rel" }
       # https://crbug.com/743139 - disabled until we can move these to swarming,
       # at which point we can just remove them.
       #builders { name: "crashpad_try_win_x86_dbg" }
       #builders { name: "crashpad_try_win_x86_rel" }
-      builders { name: "crashpad_try_win_x86_wow64_dbg" }
-      builders { name: "crashpad_try_win_x86_wow64_rel" }
     }
   }
 }
diff --git a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc
index 9c665f4f..4a22b43 100644
--- a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc
+++ b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc
@@ -123,6 +123,12 @@
     case kCPUArchitectureX86_64:
       cpu_architecture = kMinidumpCPUArchitectureAMD64;
       break;
+    case kCPUArchitectureARM:
+      cpu_architecture = kMinidumpCPUArchitectureARM;
+      break;
+    case kCPUArchitectureARM64:
+      cpu_architecture = kMinidumpCPUArchitectureARM64;
+      break;
     default:
       NOTREACHED();
       cpu_architecture = kMinidumpCPUArchitectureUnknown;
@@ -160,6 +166,12 @@
     case SystemSnapshot::kOperatingSystemWindows:
       operating_system = kMinidumpOSWin32NT;
       break;
+    case SystemSnapshot::kOperatingSystemLinux:
+      operating_system = kMinidumpOSLinux;
+      break;
+    case SystemSnapshot::kOperatingSystemAndroid:
+      operating_system = kMinidumpOSAndroid;
+      break;
     default:
       NOTREACHED();
       operating_system = kMinidumpOSUnknown;
diff --git a/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn
index e1d24002..5ccc735e 100644
--- a/third_party/crashpad/crashpad/snapshot/BUILD.gn
+++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -34,6 +34,7 @@
     "handle_snapshot.h",
     "memory_snapshot.cc",
     "memory_snapshot.h",
+    "memory_snapshot_generic.h",
     "minidump/minidump_annotation_reader.cc",
     "minidump/minidump_annotation_reader.h",
     "minidump/minidump_simple_string_dictionary_reader.cc",
@@ -47,8 +48,6 @@
     "minidump/process_snapshot_minidump.cc",
     "minidump/process_snapshot_minidump.h",
     "module_snapshot.h",
-    "posix/timezone.cc",
-    "posix/timezone.h",
     "process_snapshot.h",
     "snapshot_constants.h",
     "system_snapshot.h",
@@ -57,6 +56,13 @@
     "unloaded_module_snapshot.h",
   ]
 
+  if (crashpad_is_posix) {
+    sources += [
+      "posix/timezone.cc",
+      "posix/timezone.h",
+    ]
+  }
+
   if (crashpad_is_mac) {
     sources += [
       "mac/cpu_context_mac.cc",
@@ -71,12 +77,10 @@
       "mac/mach_o_image_segment_reader.h",
       "mac/mach_o_image_symbol_table_reader.cc",
       "mac/mach_o_image_symbol_table_reader.h",
-      "mac/memory_snapshot_mac.cc",
-      "mac/memory_snapshot_mac.h",
       "mac/module_snapshot_mac.cc",
       "mac/module_snapshot_mac.h",
-      "mac/process_reader.cc",
-      "mac/process_reader.h",
+      "mac/process_reader_mac.cc",
+      "mac/process_reader_mac.h",
       "mac/process_snapshot_mac.cc",
       "mac/process_snapshot_mac.h",
       "mac/process_types.cc",
@@ -101,20 +105,14 @@
 
   if (crashpad_is_linux || crashpad_is_android) {
     sources += [
-      "crashpad_types/image_annotation_reader.cc",
-      "crashpad_types/image_annotation_reader.h",
       "linux/cpu_context_linux.cc",
       "linux/cpu_context_linux.h",
       "linux/debug_rendezvous.cc",
       "linux/debug_rendezvous.h",
       "linux/exception_snapshot_linux.cc",
       "linux/exception_snapshot_linux.h",
-      "linux/memory_snapshot_linux.cc",
-      "linux/memory_snapshot_linux.h",
-      "linux/module_snapshot_linux.cc",
-      "linux/module_snapshot_linux.h",
-      "linux/process_reader.cc",
-      "linux/process_reader.h",
+      "linux/process_reader_linux.cc",
+      "linux/process_reader_linux.h",
       "linux/process_snapshot_linux.cc",
       "linux/process_snapshot_linux.h",
       "linux/signal_context.h",
@@ -129,12 +127,16 @@
     sources += [
       "crashpad_types/crashpad_info_reader.cc",
       "crashpad_types/crashpad_info_reader.h",
+      "crashpad_types/image_annotation_reader.cc",
+      "crashpad_types/image_annotation_reader.h",
       "elf/elf_dynamic_array_reader.cc",
       "elf/elf_dynamic_array_reader.h",
       "elf/elf_image_reader.cc",
       "elf/elf_image_reader.h",
       "elf/elf_symbol_table_reader.cc",
       "elf/elf_symbol_table_reader.h",
+      "elf/module_snapshot_elf.cc",
+      "elf/module_snapshot_elf.h",
     ]
   }
 
@@ -173,8 +175,12 @@
 
   if (crashpad_is_fuchsia) {
     sources += [
+      "fuchsia/process_reader_fuchsia.cc",
+      "fuchsia/process_reader_fuchsia.h",
       "fuchsia/process_snapshot_fuchsia.cc",
       "fuchsia/process_snapshot_fuchsia.h",
+      "fuchsia/thread_snapshot_fuchsia.cc",
+      "fuchsia/thread_snapshot_fuchsia.h",
     ]
   }
 
@@ -290,7 +296,7 @@
       "mac/mach_o_image_annotations_reader_test.cc",
       "mac/mach_o_image_reader_test.cc",
       "mac/mach_o_image_segment_reader_test.cc",
-      "mac/process_reader_test.cc",
+      "mac/process_reader_mac_test.cc",
       "mac/process_types_test.cc",
       "mac/system_snapshot_mac_test.cc",
     ]
@@ -298,10 +304,9 @@
 
   if (crashpad_is_linux || crashpad_is_android) {
     sources += [
-      "crashpad_types/image_annotation_reader_test.cc",
       "linux/debug_rendezvous_test.cc",
       "linux/exception_snapshot_linux_test.cc",
-      "linux/process_reader_test.cc",
+      "linux/process_reader_linux_test.cc",
       "linux/system_snapshot_linux_test.cc",
     ]
   } else {
@@ -311,6 +316,7 @@
   if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
     sources += [
       "crashpad_types/crashpad_info_reader_test.cc",
+      "crashpad_types/image_annotation_reader_test.cc",
       "elf/elf_image_reader_test.cc",
       "elf/elf_image_reader_test_note.S",
       "elf/test_exported_symbols.sym",
@@ -329,10 +335,18 @@
       "win/process_snapshot_win_test.cc",
       "win/system_snapshot_win_test.cc",
     ]
-  } else {
+  } else if (!crashpad_is_fuchsia) {
+    # Timezones are currently non-functional on Fuchsia:
+    # https://fuchsia.googlesource.com/zircon/+/master/third_party/ulib/musl/src/time/__tz.c#9
+    # https://crashpad.chromium.org/bug/196. Relevant upstream bugs are ZX-337
+    # and ZX-1731.
     sources += [ "posix/timezone_test.cc" ]
   }
 
+  if (crashpad_is_fuchsia) {
+    sources += [ "fuchsia/process_reader_fuchsia_test.cc" ]
+  }
+
   # public_configs isn’t quite right. snapshot_test_link sets ldflags, and
   # what’s really needed is a way to push ldflags to dependent targets that
   # produce linker output. Luckily in this case, all dependents do produce
@@ -403,10 +417,15 @@
   sources = [
     "crashpad_info_size_test_module.cc",
   ]
+
+  deps = []
+  if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
+    sources += [ "crashpad_info_size_test_note.S" ]
+    deps += [ "../util" ]
+  }
+
   defines = [ "CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE" ]
-  deps = [
-    "../third_party/mini_chromium:base",
-  ]
+  deps += [ "../third_party/mini_chromium:base" ]
 }
 
 loadable_module("crashpad_snapshot_test_module_small") {
@@ -414,10 +433,15 @@
   sources = [
     "crashpad_info_size_test_module.cc",
   ]
+
+  deps = []
+  if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
+    sources += [ "crashpad_info_size_test_note.S" ]
+    deps += [ "../util" ]
+  }
+
   defines = [ "CRASHPAD_INFO_SIZE_TEST_MODULE_SMALL" ]
-  deps = [
-    "../third_party/mini_chromium:base",
-  ]
+  deps += [ "../third_party/mini_chromium:base" ]
 }
 
 if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
diff --git a/third_party/crashpad/crashpad/snapshot/capture_memory.cc b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
index c860285..4327fbda9 100644
--- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc
+++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
@@ -94,8 +94,20 @@
     MaybeCaptureMemoryAround(delegate, context.x86->ebp);
     MaybeCaptureMemoryAround(delegate, context.x86->eip);
   }
+#elif defined(ARCH_CPU_ARM_FAMILY)
+  if (context.architecture == kCPUArchitectureARM64) {
+    MaybeCaptureMemoryAround(delegate, context.arm64->pc);
+    for (size_t i = 0; i < arraysize(context.arm64->regs); ++i) {
+      MaybeCaptureMemoryAround(delegate, context.arm64->regs[i]);
+    }
+  } else {
+    MaybeCaptureMemoryAround(delegate, context.arm->pc);
+    for (size_t i = 0; i < arraysize(context.arm->regs); ++i) {
+      MaybeCaptureMemoryAround(delegate, context.arm->regs[i]);
+    }
+  }
 #else
-#error non-x86
+#error Port.
 #endif
 }
 
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc
index d39fada..53f4a3f 100644
--- a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc
+++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc
@@ -23,7 +23,6 @@
 #endif  // OS_MACOSX
 
 namespace crashpad {
-namespace {
 
 #if defined(CRASHPAD_INFO_SIZE_TEST_MODULE_SMALL) == \
     defined(CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE)
@@ -70,16 +69,12 @@
 __attribute__((
 #if defined(OS_MACOSX)
     section(SEG_DATA ",crashpad_info"),
-#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
-    section("crashpad_info"),
-#else
-#error Port
 #endif
 #if defined(ADDRESS_SANITIZER)
     aligned(64),
 #endif  // defined(ADDRESS_SANITIZER)
-    used,
-    visibility("hidden")))
+    visibility("hidden"),
+    used))
 #elif defined(OS_WIN)
 #pragma section("CPADinfo", read, write)
 __declspec(allocate("CPADinfo"))
@@ -106,7 +101,6 @@
 #endif  // CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE
 };
 
-}  // namespace
 }  // namespace crashpad
 
 extern "C" {
@@ -119,6 +113,9 @@
 #error Port
 #endif  // OS_POSIX
 crashpad::TestCrashpadInfo* TestModule_GetCrashpadInfo() {
+  // Note that there's no need to do the back-reference here to the note on
+  // POSIX like CrashpadInfo::GetCrashpadInfo() because the note .S file is
+  // directly included into this test binary.
   return &crashpad::g_test_crashpad_info;
 }
 
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S
new file mode 100644
index 0000000..a355a83
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S
@@ -0,0 +1,56 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This note section is used on ELF platforms to give ElfImageReader a method
+// of finding the instance of CrashpadInfo g_crashpad_info without requiring
+// that symbol to be in the dynamic symbol table.
+
+#include "build/build_config.h"
+#include "util/misc/elf_note_types.h"
+
+// namespace crashpad {
+// CrashpadInfo g_test_crashpad_info;
+// }  // namespace crashpad
+#define TEST_CRASHPAD_INFO_SYMBOL _ZN8crashpad20g_test_crashpad_infoE
+
+#define NOTE_ALIGN 4
+
+  // This section must be "a"llocated so that it appears in the final binary at
+  // runtime, and "w"ritable so that the relocation to TEST_CRASHPAD_INFO_SYMBOL
+  // can be performed.
+  .section .note.crashpad.info,"aw",%note
+  .balign NOTE_ALIGN
+  .type info_size_test_note, %object
+info_size_test_note:
+  .long name_end - name  // namesz
+  .long desc_end - desc  // descsz
+  .long CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO  // type
+name:
+  .asciz CRASHPAD_ELF_NOTE_NAME
+name_end:
+  .balign NOTE_ALIGN
+desc:
+#if defined(ARCH_CPU_64_BITS)
+  .quad TEST_CRASHPAD_INFO_SYMBOL
+#else
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+  .long TEST_CRASHPAD_INFO_SYMBOL
+  .long 0
+#else
+  .long 0
+  .long TEST_CRASHPAD_INFO_SYMBOL
+#endif  // ARCH_CPU_LITTLE_ENDIAN
+#endif  // ARCH_CPU_64_BITS
+desc_end:
+  .size info_size_test_note, .-info_size_test_note
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc
index ade9931..dfc438f 100644
--- a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc
@@ -81,7 +81,11 @@
       return false;
     }
 
-    memset(reinterpret_cast<char*>(&info), 0, sizeof(info) - info.size);
+    if (sizeof(info) > info.size) {
+      memset(reinterpret_cast<char*>(&info) + info.size,
+             0,
+             sizeof(info) - info.size);
+    }
 
     UnsetIfNotValidTriState(&info.crashpad_handler_behavior);
     UnsetIfNotValidTriState(&info.system_crash_reporter_forwarding);
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc
index 73564177..87bafc6 100644
--- a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc
@@ -17,6 +17,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <memory>
+
 #include "build/build_config.h"
 #include "client/annotation_list.h"
 #include "client/crashpad_info.h"
@@ -43,10 +45,32 @@
 
 constexpr uint32_t kIndirectlyReferencedMemoryCap = 42;
 
+class ScopedUnsetCrashpadInfo {
+ public:
+  explicit ScopedUnsetCrashpadInfo(CrashpadInfo* crashpad_info)
+      : crashpad_info_(crashpad_info) {}
+
+  ~ScopedUnsetCrashpadInfo() {
+    crashpad_info_->set_crashpad_handler_behavior(TriState::kUnset);
+    crashpad_info_->set_system_crash_reporter_forwarding(TriState::kUnset);
+    crashpad_info_->set_gather_indirectly_referenced_memory(TriState::kUnset,
+                                                            0);
+    crashpad_info_->set_extra_memory_ranges(nullptr);
+    crashpad_info_->set_simple_annotations(nullptr);
+    crashpad_info_->set_annotations_list(nullptr);
+  }
+
+ private:
+  CrashpadInfo* crashpad_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedUnsetCrashpadInfo);
+};
+
 class CrashpadInfoTestDataSetup {
  public:
   CrashpadInfoTestDataSetup() {
     CrashpadInfo* info = CrashpadInfo::GetCrashpadInfo();
+    unset_.reset(new ScopedUnsetCrashpadInfo(info));
 
     info->set_extra_memory_ranges(&extra_memory_);
     info->set_simple_annotations(&simple_annotations_);
@@ -69,6 +93,7 @@
   }
 
  private:
+  std::unique_ptr<ScopedUnsetCrashpadInfo> unset_;
   SimpleAddressRangeBag extra_memory_;
   SimpleStringDictionary simple_annotations_;
   AnnotationList annotation_list_;
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc
index b0e635ff..63cfcfcc 100644
--- a/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc
@@ -26,11 +26,12 @@
 #include "client/annotation_list.h"
 #include "client/simple_string_dictionary.h"
 #include "gtest/gtest.h"
-#include "test/multiprocess.h"
+#include "test/multiprocess_exec.h"
+#include "test/process_type.h"
 #include "util/file/file_io.h"
 #include "util/misc/as_underlying_type.h"
 #include "util/misc/from_pointer_cast.h"
-#include "util/process/process_memory_linux.h"
+#include "util/process/process_memory_native.h"
 
 namespace crashpad {
 namespace test {
@@ -60,67 +61,64 @@
   }
 }
 
-class AnnotationTest {
- public:
-  AnnotationTest()
-      : expected_simple_map_(),
-        test_annotations_(),
-        expected_annotation_list_() {
-    expected_simple_map_.SetKeyValue("key", "value");
-    expected_simple_map_.SetKeyValue("key2", "value2");
+void BuildTestStructures(
+    std::vector<std::unique_ptr<Annotation>>* annotations_storage,
+    SimpleStringDictionary* into_map,
+    AnnotationList* into_annotation_list) {
+  into_map->SetKeyValue("key", "value");
+  into_map->SetKeyValue("key2", "value2");
 
-    static constexpr char kAnnotationName[] = "test annotation";
-    static constexpr char kAnnotationValue[] = "test annotation value";
-    test_annotations_.push_back(std::make_unique<Annotation>(
-        Annotation::Type::kString,
-        kAnnotationName,
-        reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue))));
-    test_annotations_.back()->SetSize(sizeof(kAnnotationValue));
-    expected_annotation_list_.Add(test_annotations_.back().get());
+  static constexpr char kAnnotationName[] = "test annotation";
+  static constexpr char kAnnotationValue[] = "test annotation value";
+  annotations_storage->push_back(std::make_unique<Annotation>(
+      Annotation::Type::kString,
+      kAnnotationName,
+      reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue))));
+  annotations_storage->back()->SetSize(sizeof(kAnnotationValue));
+  into_annotation_list->Add(annotations_storage->back().get());
 
-    static constexpr char kAnnotationName2[] = "test annotation2";
-    static constexpr char kAnnotationValue2[] = "test annotation value2";
-    test_annotations_.push_back(std::make_unique<Annotation>(
-        Annotation::Type::kString,
-        kAnnotationName2,
-        reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2))));
-    test_annotations_.back()->SetSize(sizeof(kAnnotationValue2));
-    expected_annotation_list_.Add(test_annotations_.back().get());
-  }
+  static constexpr char kAnnotationName2[] = "test annotation2";
+  static constexpr char kAnnotationValue2[] = "test annotation value2";
+  annotations_storage->push_back(std::make_unique<Annotation>(
+      Annotation::Type::kString,
+      kAnnotationName2,
+      reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2))));
+  annotations_storage->back()->SetSize(sizeof(kAnnotationValue2));
+  into_annotation_list->Add(annotations_storage->back().get());
+}
 
-  ~AnnotationTest() = default;
+void ExpectAnnotations(ProcessType process,
+                       bool is_64_bit,
+                       VMAddress simple_map_address,
+                       VMAddress annotation_list_address) {
+  ProcessMemoryNative memory;
+  ASSERT_TRUE(memory.Initialize(process));
 
-  void ExpectAnnotations(pid_t pid, bool is_64_bit) {
-    ProcessMemoryLinux memory;
-    ASSERT_TRUE(memory.Initialize(pid));
+  ProcessMemoryRange range;
+  ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
 
-    ProcessMemoryRange range;
-    ASSERT_TRUE(range.Initialize(&memory, is_64_bit));
+  SimpleStringDictionary expected_simple_map;
+  std::vector<std::unique_ptr<Annotation>> storage;
+  AnnotationList expected_annotations;
+  BuildTestStructures(&storage, &expected_simple_map, &expected_annotations);
 
-    ImageAnnotationReader reader(&range);
+  ImageAnnotationReader reader(&range);
 
-    std::map<std::string, std::string> simple_map;
-    ASSERT_TRUE(reader.SimpleMap(
-        FromPointerCast<VMAddress>(&expected_simple_map_), &simple_map));
-    ExpectSimpleMap(simple_map, expected_simple_map_);
+  std::map<std::string, std::string> simple_map;
+  ASSERT_TRUE(reader.SimpleMap(simple_map_address, &simple_map));
+  ExpectSimpleMap(simple_map, expected_simple_map);
 
-    std::vector<AnnotationSnapshot> annotation_list;
-    ASSERT_TRUE(reader.AnnotationsList(
-        FromPointerCast<VMAddress>(&expected_annotation_list_),
-        &annotation_list));
-    ExpectAnnotationList(annotation_list, expected_annotation_list_);
-  }
-
- private:
-  SimpleStringDictionary expected_simple_map_;
-  std::vector<std::unique_ptr<Annotation>> test_annotations_;
-  AnnotationList expected_annotation_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(AnnotationTest);
-};
+  std::vector<AnnotationSnapshot> annotation_list;
+  ASSERT_TRUE(
+      reader.AnnotationsList(annotation_list_address, &annotation_list));
+  ExpectAnnotationList(annotation_list, expected_annotations);
+}
 
 TEST(ImageAnnotationReader, ReadFromSelf) {
-  AnnotationTest test;
+  SimpleStringDictionary map;
+  std::vector<std::unique_ptr<Annotation>> storage;
+  AnnotationList annotations;
+  BuildTestStructures(&storage, &map, &annotations);
 
 #if defined(ARCH_CPU_64_BITS)
   constexpr bool am_64_bit = true;
@@ -128,14 +126,35 @@
   constexpr bool am_64_bit = false;
 #endif
 
-  test.ExpectAnnotations(getpid(), am_64_bit);
+  ExpectAnnotations(GetSelfProcess(),
+                    am_64_bit,
+                    FromPointerCast<VMAddress>(&map),
+                    FromPointerCast<VMAddress>(&annotations));
 }
 
-class ReadFromChildTest : public Multiprocess {
- public:
-  ReadFromChildTest() : Multiprocess(), annotation_test_() {}
+CRASHPAD_CHILD_TEST_MAIN(ReadAnnotationsFromChildTestMain) {
+  SimpleStringDictionary map;
+  std::vector<std::unique_ptr<Annotation>> storage;
+  AnnotationList annotations;
+  BuildTestStructures(&storage, &map, &annotations);
 
-  ~ReadFromChildTest() {}
+  VMAddress simple_map_address = FromPointerCast<VMAddress>(&map);
+  VMAddress annotations_address = FromPointerCast<VMAddress>(&annotations);
+  FileHandle out = StdioFileHandle(StdioStream::kStandardOutput);
+  CheckedWriteFile(out, &simple_map_address, sizeof(simple_map_address));
+  CheckedWriteFile(out, &annotations_address, sizeof(annotations_address));
+
+  CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
+  return 0;
+}
+
+class ReadFromChildTest : public MultiprocessExec {
+ public:
+  ReadFromChildTest() : MultiprocessExec() {
+    SetChildTestMainFunction("ReadAnnotationsFromChildTestMain");
+  }
+
+  ~ReadFromChildTest() = default;
 
  private:
   void MultiprocessParent() {
@@ -144,13 +163,17 @@
 #else
     constexpr bool am_64_bit = false;
 #endif
-    annotation_test_.ExpectAnnotations(ChildPID(), am_64_bit);
+
+    VMAddress simple_map_address;
+    VMAddress annotations_address;
+    ASSERT_TRUE(ReadFileExactly(
+        ReadPipeHandle(), &simple_map_address, sizeof(simple_map_address)));
+    ASSERT_TRUE(ReadFileExactly(
+        ReadPipeHandle(), &annotations_address, sizeof(annotations_address)));
+    ExpectAnnotations(
+        ChildProcess(), am_64_bit, simple_map_address, annotations_address);
   }
 
-  void MultiprocessChild() { CheckedReadFileAtEOF(ReadPipeHandle()); }
-
-  AnnotationTest annotation_test_;
-
   DISALLOW_COPY_AND_ASSIGN(ReadFromChildTest);
 };
 
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc
index 2fc9608..c681660 100644
--- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc
@@ -164,7 +164,7 @@
                       VMSize* size) const override {
     INITIALIZATION_STATE_DCHECK_VALID(initialized_);
     for (size_t index = *start_index; index < table_.size(); ++index) {
-      if (table_[index].p_type == PT_NOTE) {
+      if (table_[index].p_type == PT_NOTE && table_[index].p_vaddr != 0) {
         *start_index = index + 1;
         *address = table_[index].p_vaddr;
         *size = table_[index].p_memsz;
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc
index dc13ad6f..91cce068 100644
--- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc
@@ -27,6 +27,7 @@
 #include "test/test_paths.h"
 #include "util/file/file_io.h"
 #include "util/misc/address_types.h"
+#include "util/misc/elf_note_types.h"
 #include "util/misc/from_pointer_cast.h"
 #include "util/process/process_memory_native.h"
 
@@ -163,14 +164,14 @@
             ElfImageReader::NoteReader::Result::kNoMoreNotes);
 
   // Find the note defined in elf_image_reader_test_note.S.
-  constexpr char kCrashpadNoteName[] = "Crashpad";
-  constexpr ElfImageReader::NoteReader::NoteType kCrashpadNoteType = 1;
   constexpr uint32_t kCrashpadNoteDesc = 42;
-  notes = reader.NotesWithNameAndType(kCrashpadNoteName, kCrashpadNoteType, -1);
+  notes = reader.NotesWithNameAndType(
+      CRASHPAD_ELF_NOTE_NAME, CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST, -1);
   ASSERT_EQ(notes->NextNote(&note_name, &note_type, &note_desc),
             ElfImageReader::NoteReader::Result::kSuccess);
-  EXPECT_EQ(note_name, kCrashpadNoteName);
-  EXPECT_EQ(note_type, kCrashpadNoteType);
+  EXPECT_EQ(note_name, CRASHPAD_ELF_NOTE_NAME);
+  EXPECT_EQ(note_type,
+            implicit_cast<unsigned int>(CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST));
   EXPECT_EQ(note_desc.size(), sizeof(kCrashpadNoteDesc));
   EXPECT_EQ(*reinterpret_cast<decltype(kCrashpadNoteDesc)*>(&note_desc[0]),
             kCrashpadNoteDesc);
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S
index e41a520..9ab0338 100644
--- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S
+++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "util/misc/elf_note_types.h"
+
 #define NOTE_ALIGN 4
   .section .note.crashpad.test,"a",%note
   .balign NOTE_ALIGN
@@ -19,9 +21,9 @@
 testnote:
   .long name_end - name  // namesz
   .long desc_end - desc  // descsz
-  .long 1  // type
+  .long CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST  // type
 name:
-  .ascii "Crashpad\0"
+  .asciz CRASHPAD_ELF_NOTE_NAME
 name_end:
   .balign NOTE_ALIGN
 desc:
diff --git a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc
similarity index 64%
rename from third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc
rename to third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc
index 0ddbebf..5c5039ee1 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc
@@ -12,46 +12,52 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot/linux/module_snapshot_linux.h"
+#include "snapshot/elf/module_snapshot_elf.h"
 
 #include <algorithm>
 
 #include "base/files/file_path.h"
 #include "snapshot/crashpad_types/image_annotation_reader.h"
+#include "util/misc/elf_note_types.h"
 
 namespace crashpad {
 namespace internal {
 
-ModuleSnapshotLinux::ModuleSnapshotLinux()
+ModuleSnapshotElf::ModuleSnapshotElf(const std::string& name,
+                                     ElfImageReader* elf_reader,
+                                     ModuleSnapshot::ModuleType type)
     : ModuleSnapshot(),
-      name_(),
-      elf_reader_(nullptr),
+      name_(name),
+      elf_reader_(elf_reader),
       crashpad_info_(),
-      type_(kModuleTypeUnknown),
+      type_(type),
       initialized_() {}
 
-ModuleSnapshotLinux::~ModuleSnapshotLinux() = default;
+ModuleSnapshotElf::~ModuleSnapshotElf() = default;
 
-bool ModuleSnapshotLinux::Initialize(
-    const ProcessReader::Module& process_reader_module) {
+bool ModuleSnapshotElf::Initialize() {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
-  if (!process_reader_module.elf_reader) {
+  if (!elf_reader_) {
     LOG(ERROR) << "no elf reader";
     return false;
   }
 
-  name_ = process_reader_module.name;
-  elf_reader_ = process_reader_module.elf_reader;
-  type_ = process_reader_module.type;
-
+  // The data payload is only sizeof(VMAddress) in the note, but add a bit to
+  // account for the name, header, and padding.
+  constexpr ssize_t kMaxNoteSize = 256;
+  std::unique_ptr<ElfImageReader::NoteReader> notes =
+      elf_reader_->NotesWithNameAndType(CRASHPAD_ELF_NOTE_NAME,
+                                        CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO,
+                                        kMaxNoteSize);
+  std::string desc;
   VMAddress info_address;
-  VMSize info_size;
-  if (elf_reader_->GetDynamicSymbol(
-          "g_crashpad_info", &info_address, &info_size)) {
+  if (notes->NextNote(nullptr, nullptr, &desc) ==
+      ElfImageReader::NoteReader::Result::kSuccess) {
+    info_address = *reinterpret_cast<VMAddress*>(&desc[0]);
+
     ProcessMemoryRange range;
-    if (range.Initialize(*elf_reader_->Memory()) &&
-        range.RestrictRange(info_address, info_size)) {
+    if (range.Initialize(*elf_reader_->Memory())) {
       auto info = std::make_unique<CrashpadInfoReader>();
       if (info->Initialize(&range, info_address)) {
         crashpad_info_ = std::move(info);
@@ -63,8 +69,7 @@
   return true;
 }
 
-bool ModuleSnapshotLinux::GetCrashpadOptions(
-    CrashpadInfoClientOptions* options) {
+bool ModuleSnapshotElf::GetCrashpadOptions(CrashpadInfoClientOptions* options) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   if (!crashpad_info_) {
@@ -82,27 +87,38 @@
   return true;
 }
 
-std::string ModuleSnapshotLinux::Name() const {
+std::string ModuleSnapshotElf::Name() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return name_;
 }
 
-uint64_t ModuleSnapshotLinux::Address() const {
+uint64_t ModuleSnapshotElf::Address() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return elf_reader_->Address();
 }
 
-uint64_t ModuleSnapshotLinux::Size() const {
+uint64_t ModuleSnapshotElf::Size() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return elf_reader_->Size();
 }
 
-time_t ModuleSnapshotLinux::Timestamp() const {
+time_t ModuleSnapshotElf::Timestamp() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return 0;
 }
 
-void ModuleSnapshotLinux::FileVersion(uint16_t* version_0,
+void ModuleSnapshotElf::FileVersion(uint16_t* version_0,
+                                    uint16_t* version_1,
+                                    uint16_t* version_2,
+                                    uint16_t* version_3) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  *version_0 = 0;
+  *version_1 = 0;
+  *version_2 = 0;
+  *version_3 = 0;
+}
+
+void ModuleSnapshotElf::SourceVersion(uint16_t* version_0,
                                       uint16_t* version_1,
                                       uint16_t* version_2,
                                       uint16_t* version_3) const {
@@ -113,24 +129,12 @@
   *version_3 = 0;
 }
 
-void ModuleSnapshotLinux::SourceVersion(uint16_t* version_0,
-                                        uint16_t* version_1,
-                                        uint16_t* version_2,
-                                        uint16_t* version_3) const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-  *version_0 = 0;
-  *version_1 = 0;
-  *version_2 = 0;
-  *version_3 = 0;
-}
-
-ModuleSnapshot::ModuleType ModuleSnapshotLinux::GetModuleType() const {
+ModuleSnapshot::ModuleType ModuleSnapshotElf::GetModuleType() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return type_;
 }
 
-void ModuleSnapshotLinux::UUIDAndAge(crashpad::UUID* uuid,
-                                     uint32_t* age) const {
+void ModuleSnapshotElf::UUIDAndAge(crashpad::UUID* uuid, uint32_t* age) const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   *age = 0;
 
@@ -142,17 +146,17 @@
   uuid->InitializeFromBytes(reinterpret_cast<const uint8_t*>(&desc[0]));
 }
 
-std::string ModuleSnapshotLinux::DebugFileName() const {
+std::string ModuleSnapshotElf::DebugFileName() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return base::FilePath(Name()).BaseName().value();
 }
 
-std::vector<std::string> ModuleSnapshotLinux::AnnotationsVector() const {
+std::vector<std::string> ModuleSnapshotElf::AnnotationsVector() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return std::vector<std::string>();
 }
 
-std::map<std::string, std::string> ModuleSnapshotLinux::AnnotationsSimpleMap()
+std::map<std::string, std::string> ModuleSnapshotElf::AnnotationsSimpleMap()
     const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   std::map<std::string, std::string> annotations;
@@ -163,7 +167,7 @@
   return annotations;
 }
 
-std::vector<AnnotationSnapshot> ModuleSnapshotLinux::AnnotationObjects() const {
+std::vector<AnnotationSnapshot> ModuleSnapshotElf::AnnotationObjects() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   std::vector<AnnotationSnapshot> annotations;
   if (crashpad_info_ && crashpad_info_->AnnotationsList()) {
@@ -173,14 +177,13 @@
   return annotations;
 }
 
-std::set<CheckedRange<uint64_t>> ModuleSnapshotLinux::ExtraMemoryRanges()
-    const {
+std::set<CheckedRange<uint64_t>> ModuleSnapshotElf::ExtraMemoryRanges() const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return std::set<CheckedRange<uint64_t>>();
 }
 
 std::vector<const UserMinidumpStream*>
-ModuleSnapshotLinux::CustomMinidumpStreams() const {
+ModuleSnapshotElf::CustomMinidumpStreams() const {
   return std::vector<const UserMinidumpStream*>();
 }
 
diff --git a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h
similarity index 79%
rename from third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h
rename to third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h
index b277ff7..1f7cf65 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_
-#define CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_
+#ifndef CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_
+#define CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -27,7 +27,6 @@
 #include "snapshot/crashpad_info_client_options.h"
 #include "snapshot/crashpad_types/crashpad_info_reader.h"
 #include "snapshot/elf/elf_image_reader.h"
-#include "snapshot/linux/process_reader.h"
 #include "snapshot/module_snapshot.h"
 #include "util/misc/initialization_state_dcheck.h"
 
@@ -36,20 +35,22 @@
 namespace internal {
 
 //! \brief A ModuleSnapshot of a code module (binary image) loaded into a
-//!     running (or crashed) process on a Linux system.
-class ModuleSnapshotLinux final : public ModuleSnapshot {
+//!     running (or crashed) process on a system that uses ELF modules.
+class ModuleSnapshotElf final : public ModuleSnapshot {
  public:
-  ModuleSnapshotLinux();
-  ~ModuleSnapshotLinux() override;
+  //! \param[in] name The pathname used to load the module from disk.
+  //! \param[in] elf_reader An image reader for the module.
+  //! \param[in] type The module's type.
+  ModuleSnapshotElf(const std::string& name,
+                    ElfImageReader* elf_reader,
+                    ModuleSnapshot::ModuleType type);
+  ~ModuleSnapshotElf() override;
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader_module The module within the ProcessReader for
-  //!     which the snapshot should be created.
-  //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
-  bool Initialize(const ProcessReader::Module& process_reader_module);
+  bool Initialize();
 
   //! \brief Returns options from the module’s CrashpadInfo structure.
   //!
@@ -87,10 +88,10 @@
   ModuleType type_;
   InitializationStateDcheck initialized_;
 
-  DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotLinux);
+  DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotElf);
 };
 
 }  // namespace internal
 }  // namespace crashpad
 
-#endif  // CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_
+#endif  // CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc
new file mode 100644
index 0000000..1ace0d13
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc
@@ -0,0 +1,266 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/fuchsia/process_reader_fuchsia.h"
+
+#include <link.h>
+#include <zircon/syscalls.h>
+
+#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/scoped_zx_handle.h"
+#include "base/logging.h"
+
+namespace crashpad {
+
+ProcessReaderFuchsia::Module::Module() = default;
+
+ProcessReaderFuchsia::Module::~Module() = default;
+
+ProcessReaderFuchsia::Thread::Thread() = default;
+
+ProcessReaderFuchsia::Thread::~Thread() = default;
+
+ProcessReaderFuchsia::ProcessReaderFuchsia() = default;
+
+ProcessReaderFuchsia::~ProcessReaderFuchsia() = default;
+
+bool ProcessReaderFuchsia::Initialize(zx_handle_t process) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+  process_ = process;
+
+  process_memory_.reset(new ProcessMemoryFuchsia());
+  process_memory_->Initialize(process_);
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+const std::vector<ProcessReaderFuchsia::Module>&
+ProcessReaderFuchsia::Modules() {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  if (!initialized_modules_) {
+    InitializeModules();
+  }
+
+  return modules_;
+}
+
+const std::vector<ProcessReaderFuchsia::Thread>&
+ProcessReaderFuchsia::Threads() {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  if (!initialized_threads_) {
+    InitializeThreads();
+  }
+
+  return threads_;
+}
+
+void ProcessReaderFuchsia::InitializeModules() {
+  DCHECK(!initialized_modules_);
+  DCHECK(modules_.empty());
+
+  initialized_modules_ = true;
+
+  // TODO(scottmg): <inspector/inspector.h> does some of this, but doesn't
+  // expose any of the data that's necessary to fill out a Module after it
+  // retrieves (some of) the data into internal structures. It may be worth
+  // trying to refactor/upstream some of this into Fuchsia.
+
+  std::string app_name("app:");
+  {
+    char name[ZX_MAX_NAME_LEN];
+    zx_status_t status =
+        zx_object_get_property(process_, ZX_PROP_NAME, name, sizeof(name));
+    if (status != ZX_OK) {
+      LOG(ERROR) << "zx_object_get_property ZX_PROP_NAME";
+      return;
+    }
+
+    app_name += name;
+  }
+
+  // Starting from the ld.so's _dl_debug_addr, read the link_map structure and
+  // walk the list to fill out modules_.
+
+  uintptr_t debug_address;
+  zx_status_t status = zx_object_get_property(process_,
+                                              ZX_PROP_PROCESS_DEBUG_ADDR,
+                                              &debug_address,
+                                              sizeof(debug_address));
+  if (status != ZX_OK || debug_address == 0) {
+    LOG(ERROR) << "zx_object_get_property ZX_PROP_PROCESS_DEBUG_ADDR";
+    return;
+  }
+
+  constexpr auto k_r_debug_map_offset = offsetof(r_debug, r_map);
+  uintptr_t map;
+  if (!process_memory_->Read(
+          debug_address + k_r_debug_map_offset, sizeof(map), &map)) {
+    LOG(ERROR) << "read link_map";
+    return;
+  }
+
+  int i = 0;
+  constexpr int kMaxDso = 1000;  // Stop after an unreasonably large number.
+  while (map != 0) {
+    if (++i >= kMaxDso) {
+      LOG(ERROR) << "possibly circular dso list, terminating";
+      return;
+    }
+
+    constexpr auto k_link_map_addr_offset = offsetof(link_map, l_addr);
+    zx_vaddr_t base;
+    if (!process_memory_->Read(
+            map + k_link_map_addr_offset, sizeof(base), &base)) {
+      LOG(ERROR) << "Read base";
+      // Could theoretically continue here, but realistically if any part of
+      // link_map fails to read, things are looking bad, so just abort.
+      break;
+    }
+
+    constexpr auto k_link_map_next_offset = offsetof(link_map, l_next);
+    zx_vaddr_t next;
+    if (!process_memory_->Read(
+            map + k_link_map_next_offset, sizeof(next), &next)) {
+      LOG(ERROR) << "Read next";
+      break;
+    }
+
+    constexpr auto k_link_map_name_offset = offsetof(link_map, l_name);
+    zx_vaddr_t name_address;
+    if (!process_memory_->Read(map + k_link_map_name_offset,
+                               sizeof(name_address),
+                               &name_address)) {
+      LOG(ERROR) << "Read name address";
+      break;
+    }
+
+    std::string dsoname;
+    if (!process_memory_->ReadCString(name_address, &dsoname)) {
+      // In this case, it could be reasonable to continue on to the next module
+      // as this data isn't strictly in the link_map.
+      LOG(ERROR) << "ReadCString name";
+    }
+
+    Module module;
+    if (dsoname.empty()) {
+      module.name = app_name;
+      module.type = ModuleSnapshot::kModuleTypeExecutable;
+    } else {
+      module.name = dsoname;
+      // TODO(scottmg): Handle kModuleTypeDynamicLoader.
+      module.type = ModuleSnapshot::kModuleTypeSharedLibrary;
+    }
+
+    std::unique_ptr<ElfImageReader> reader(new ElfImageReader());
+
+    std::unique_ptr<ProcessMemoryRange> process_memory_range(
+        new ProcessMemoryRange());
+    // TODO(scottmg): Could this be limited range?
+    process_memory_range->Initialize(process_memory_.get(), true);
+    process_memory_ranges_.push_back(std::move(process_memory_range));
+
+    reader->Initialize(*process_memory_ranges_.back(), base);
+    module.reader = reader.get();
+    module_readers_.push_back(std::move(reader));
+    modules_.push_back(module);
+
+    map = next;
+  }
+}
+
+void ProcessReaderFuchsia::InitializeThreads() {
+  DCHECK(!initialized_threads_);
+  DCHECK(threads_.empty());
+
+  initialized_threads_ = true;
+
+  // Retrieve the thread koids. This is racy; better if the process is suspended
+  // itself, but threads could still be externally created. As there's no
+  // maximum, this needs to be retried in a loop until the actual threads
+  // retrieved is equal to the available threads.
+
+  std::vector<zx_koid_t> threads(100);
+  size_t actual_num_threads, available_num_threads;
+  for (;;) {
+    zx_status_t status = zx_object_get_info(process_,
+                                            ZX_INFO_PROCESS_THREADS,
+                                            &threads[0],
+                                            sizeof(threads[0]) * threads.size(),
+                                            &actual_num_threads,
+                                            &available_num_threads);
+    // If the buffer is too small (even zero), the result is still ZX_OK, not
+    // ZX_ERR_BUFFER_TOO_SMALL.
+    if (status != ZX_OK) {
+      ZX_LOG(ERROR, status) << "zx_object_get_info ZX_INFO_PROCESS_THREADS";
+      break;
+    }
+    if (actual_num_threads == available_num_threads) {
+      threads.resize(actual_num_threads);
+      break;
+    }
+
+    // Resize to the expected number next time with a bit extra to attempt to
+    // handle the race between here and the next request.
+    threads.resize(available_num_threads + 10);
+  }
+
+  for (const zx_koid_t thread_koid : threads) {
+    zx_handle_t raw_handle;
+    zx_status_t status = zx_object_get_child(
+        process_, thread_koid, ZX_RIGHT_SAME_RIGHTS, &raw_handle);
+    if (status != ZX_OK) {
+      ZX_LOG(ERROR, status) << "zx_object_get_child";
+      // TODO(scottmg): Decide if it's worthwhile adding a mostly-empty Thread
+      // here, consisting only of the koid, but no other information. The only
+      // time this is expected to happen is when there's a race between getting
+      // the koid above, and requesting the handle here.
+      continue;
+    }
+
+    base::ScopedZxHandle thread_handle(raw_handle);
+
+    Thread thread;
+    thread.id = thread_koid;
+
+    char name[ZX_MAX_NAME_LEN] = {0};
+    status = zx_object_get_property(
+        thread_handle.get(), ZX_PROP_NAME, &name, sizeof(name));
+    if (status != ZX_OK) {
+      ZX_LOG(WARNING, status) << "zx_object_get_property ZX_PROP_NAME";
+    } else {
+      thread.name.assign(name);
+    }
+
+    zx_info_thread_t thread_info;
+    status = zx_object_get_info(thread_handle.get(),
+                                ZX_INFO_THREAD,
+                                &thread_info,
+                                sizeof(thread_info),
+                                nullptr,
+                                nullptr);
+    if (status != ZX_OK) {
+      ZX_LOG(WARNING, status) << "zx_object_get_info ZX_INFO_THREAD";
+    } else {
+      thread.state = thread_info.state;
+    }
+
+    threads_.push_back(thread);
+  }
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h
new file mode 100644
index 0000000..d0811cfe
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h
@@ -0,0 +1,121 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
+#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "snapshot/elf/elf_image_reader.h"
+#include "snapshot/module_snapshot.h"
+#include "util/misc/initialization_state_dcheck.h"
+#include "util/process/process_memory_fuchsia.h"
+#include "util/process/process_memory_range.h"
+
+namespace crashpad {
+
+//! \brief Accesses information about another process, identified by a Fuchsia
+//!     process.
+class ProcessReaderFuchsia {
+ public:
+  //! \brief Contains information about a module loaded into a process.
+  struct Module {
+    Module();
+    ~Module();
+
+    //! \brief The `ZX_PROP_NAME` of the module. Will be prepended with "app:"
+    //!     for the main executable.
+    std::string name;
+
+    //! \brief An image reader for the module.
+    //!
+    //! The lifetime of this ElfImageReader is scoped to the lifetime of the
+    //! ProcessReaderFuchsia that created it.
+    //!
+    //! This field may be `nullptr` if a reader could not be created for the
+    //! module.
+    ElfImageReader* reader;
+
+    //! \brief The module's type.
+    ModuleSnapshot::ModuleType type = ModuleSnapshot::kModuleTypeUnknown;
+  };
+
+  //! \brief Contains information about a thread that belongs to a process.
+  struct Thread {
+    Thread();
+    ~Thread();
+
+    //! \brief The kernel identifier for the thread.
+    zx_koid_t id = ZX_KOID_INVALID;
+
+    //! \brief The state of the thread, the `ZX_THREAD_STATE_*` value or `-1` if
+    //!     the value could not be retrieved.
+    uint32_t state = -1;
+
+    //! \brief The `ZX_PROP_NAME` property of the thread. This may be empty.
+    std::string name;
+  };
+
+  ProcessReaderFuchsia();
+  ~ProcessReaderFuchsia();
+
+  //! \brief Initializes this object. This method must be called before any
+  //!     other.
+  //!
+  //! \param[in] process A process handle with permissions to read properties
+  //!     and memory from the target process.
+  //!
+  //! \return `true` on success, indicating that this object will respond
+  //!     validly to further method calls. `false` on failure. On failure, no
+  //!     further method calls should be made.
+  bool Initialize(zx_handle_t process);
+
+  //! \return The modules loaded in the process. The first element (at index
+  //!     `0`) corresponds to the main executable.
+  const std::vector<Module>& Modules();
+
+  //! \return The threads that are in the process.
+  const std::vector<Thread>& Threads();
+
+  //! \brief Return a memory reader for the target process.
+  ProcessMemory* Memory() { return process_memory_.get(); }
+
+ private:
+  //! Performs lazy initialization of the \a modules_ vector on behalf of
+  //! Modules().
+  void InitializeModules();
+
+  //! Performs lazy initialization of the \a threads_ vector on behalf of
+  //! Threads().
+  void InitializeThreads();
+
+  std::vector<Module> modules_;
+  std::vector<Thread> threads_;
+  std::vector<std::unique_ptr<ElfImageReader>> module_readers_;
+  std::vector<std::unique_ptr<ProcessMemoryRange>> process_memory_ranges_;
+  std::unique_ptr<ProcessMemoryFuchsia> process_memory_;
+  zx_handle_t process_;
+  bool initialized_modules_ = false;
+  bool initialized_threads_ = false;
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessReaderFuchsia);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc
new file mode 100644
index 0000000..35af291
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc
@@ -0,0 +1,95 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/fuchsia/process_reader_fuchsia.h"
+
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
+
+#include "gtest/gtest.h"
+#include "test/multiprocess_exec.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+TEST(ProcessReaderFuchsia, SelfBasic) {
+  ProcessReaderFuchsia process_reader;
+  ASSERT_TRUE(process_reader.Initialize(zx_process_self()));
+
+  static constexpr char kTestMemory[] = "Some test memory";
+  char buffer[arraysize(kTestMemory)];
+  ASSERT_TRUE(process_reader.Memory()->Read(
+      reinterpret_cast<zx_vaddr_t>(kTestMemory), sizeof(kTestMemory), &buffer));
+  EXPECT_STREQ(kTestMemory, buffer);
+
+  const auto& modules = process_reader.Modules();
+  EXPECT_GT(modules.size(), 0u);
+  for (const auto& module : modules) {
+    EXPECT_FALSE(module.name.empty());
+    EXPECT_NE(module.type, ModuleSnapshot::kModuleTypeUnknown);
+  }
+
+  const auto& threads = process_reader.Threads();
+  EXPECT_GT(threads.size(), 0u);
+
+  zx_info_handle_basic_t info;
+  ASSERT_EQ(zx_object_get_info(zx_thread_self(),
+                               ZX_INFO_HANDLE_BASIC,
+                               &info,
+                               sizeof(info),
+                               nullptr,
+                               nullptr),
+            ZX_OK);
+  EXPECT_EQ(threads[0].id, info.koid);
+  EXPECT_EQ(threads[0].state, ZX_THREAD_STATE_RUNNING);
+  EXPECT_EQ(threads[0].name, "initial-thread");
+}
+
+constexpr char kTestMemory[] = "Read me from another process";
+
+CRASHPAD_CHILD_TEST_MAIN(ProcessReaderBasicChildTestMain) {
+  CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
+  return 0;
+}
+
+class BasicChildTest : public MultiprocessExec {
+ public:
+  BasicChildTest() : MultiprocessExec() {
+    SetChildTestMainFunction("ProcessReaderBasicChildTestMain");
+  }
+  ~BasicChildTest() {}
+
+ private:
+  void MultiprocessParent() override {
+    ProcessReaderFuchsia process_reader;
+    ASSERT_TRUE(process_reader.Initialize(zx_process_self()));
+
+    std::string read_string;
+    ASSERT_TRUE(process_reader.Memory()->ReadCString(
+        reinterpret_cast<zx_vaddr_t>(kTestMemory), &read_string));
+    EXPECT_EQ(read_string, kTestMemory);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(BasicChildTest);
+};
+
+TEST(ProcessReaderFuchsia, ChildBasic) {
+  BasicChildTest test;
+  test.Run();
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc
index acd5449..9d0897d 100644
--- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc
@@ -23,92 +23,175 @@
 ProcessSnapshotFuchsia::~ProcessSnapshotFuchsia() {}
 
 bool ProcessSnapshotFuchsia::Initialize(zx_handle_t process) {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
-  return false;
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+  if (!process_reader_.Initialize(process)) {
+    return false;
+  }
+
+  InitializeThreads();
+  InitializeModules();
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
 }
 
 void ProcessSnapshotFuchsia::GetCrashpadOptions(
     CrashpadInfoClientOptions* options) {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+  CrashpadInfoClientOptions local_options;
+
+  for (const auto& module : modules_) {
+    CrashpadInfoClientOptions module_options;
+    module->GetCrashpadOptions(&module_options);
+
+    if (local_options.crashpad_handler_behavior == TriState::kUnset) {
+      local_options.crashpad_handler_behavior =
+          module_options.crashpad_handler_behavior;
+    }
+    if (local_options.system_crash_reporter_forwarding == TriState::kUnset) {
+      local_options.system_crash_reporter_forwarding =
+          module_options.system_crash_reporter_forwarding;
+    }
+    if (local_options.gather_indirectly_referenced_memory == TriState::kUnset) {
+      local_options.gather_indirectly_referenced_memory =
+          module_options.gather_indirectly_referenced_memory;
+      local_options.indirectly_referenced_memory_cap =
+          module_options.indirectly_referenced_memory_cap;
+    }
+
+    // If non-default values have been found for all options, the loop can end
+    // early.
+    if (local_options.crashpad_handler_behavior != TriState::kUnset &&
+        local_options.system_crash_reporter_forwarding != TriState::kUnset &&
+        local_options.gather_indirectly_referenced_memory != TriState::kUnset) {
+      break;
+    }
+  }
+
+  *options = local_options;
 }
 
 pid_t ProcessSnapshotFuchsia::ProcessID() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return 0;
 }
 
 pid_t ProcessSnapshotFuchsia::ParentProcessID() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return 0;
 }
 
 void ProcessSnapshotFuchsia::SnapshotTime(timeval* snapshot_time) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
 }
 
 void ProcessSnapshotFuchsia::ProcessStartTime(timeval* start_time) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
 }
 
 void ProcessSnapshotFuchsia::ProcessCPUTimes(timeval* user_time,
                                              timeval* system_time) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
 }
 
 void ProcessSnapshotFuchsia::ReportID(UUID* report_id) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
 }
 
 void ProcessSnapshotFuchsia::ClientID(UUID* client_id) const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
 }
 
 const std::map<std::string, std::string>&
 ProcessSnapshotFuchsia::AnnotationsSimpleMap() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return annotations_simple_map_;
 }
 
 const SystemSnapshot* ProcessSnapshotFuchsia::System() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return nullptr;
 }
 
 std::vector<const ThreadSnapshot*> ProcessSnapshotFuchsia::Threads() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return std::vector<const ThreadSnapshot*>();
 }
 
 std::vector<const ModuleSnapshot*> ProcessSnapshotFuchsia::Modules() const {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
-  return std::vector<const ModuleSnapshot*>();
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  std::vector<const ModuleSnapshot*> modules;
+  for (const auto& module : modules_) {
+    modules.push_back(module.get());
+  }
+  return modules;
 }
 
 std::vector<UnloadedModuleSnapshot> ProcessSnapshotFuchsia::UnloadedModules()
     const {
-  NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  // dlclose() never unloads on Fuchsia. ZX-1728 upstream.
   return std::vector<UnloadedModuleSnapshot>();
 }
 
 const ExceptionSnapshot* ProcessSnapshotFuchsia::Exception() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return nullptr;
 }
 
 std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotFuchsia::MemoryMap()
     const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return std::vector<const MemoryMapRegionSnapshot*>();
 }
 
 std::vector<HandleSnapshot> ProcessSnapshotFuchsia::Handles() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return std::vector<HandleSnapshot>();
 }
 
 std::vector<const MemorySnapshot*> ProcessSnapshotFuchsia::ExtraMemory() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   NOTREACHED();  // TODO(scottmg): https://crashpad.chromium.org/bug/196
   return std::vector<const MemorySnapshot*>();
 }
 
+void ProcessSnapshotFuchsia::InitializeThreads() {
+  const std::vector<ProcessReaderFuchsia::Thread>& process_reader_threads =
+      process_reader_.Threads();
+  for (const ProcessReaderFuchsia::Thread& process_reader_thread :
+       process_reader_threads) {
+    auto thread = std::make_unique<internal::ThreadSnapshotFuchsia>();
+    if (thread->Initialize(&process_reader_, process_reader_thread)) {
+      threads_.push_back(std::move(thread));
+    }
+  }
+}
+
+void ProcessSnapshotFuchsia::InitializeModules() {
+  for (const ProcessReaderFuchsia::Module& reader_module :
+       process_reader_.Modules()) {
+    auto module = std::make_unique<internal::ModuleSnapshotElf>(
+        reader_module.name, reader_module.reader, reader_module.type);
+    if (module->Initialize()) {
+      modules_.push_back(std::move(module));
+    }
+  }
+}
+
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h
index 5ae6fd3..eb07733 100644
--- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h
@@ -17,10 +17,18 @@
 
 #include <zircon/types.h>
 
+#include <memory>
+#include <vector>
+
 #include "base/macros.h"
 #include "snapshot/crashpad_info_client_options.h"
+#include "snapshot/elf/elf_image_reader.h"
+#include "snapshot/elf/module_snapshot_elf.h"
+#include "snapshot/fuchsia/process_reader_fuchsia.h"
+#include "snapshot/fuchsia/thread_snapshot_fuchsia.h"
 #include "snapshot/process_snapshot.h"
 #include "snapshot/unloaded_module_snapshot.h"
+#include "util/misc/initialization_state_dcheck.h"
 
 namespace crashpad {
 
@@ -66,7 +74,17 @@
   std::vector<const MemorySnapshot*> ExtraMemory() const override;
 
  private:
+  // Initializes threads_ on behalf of Initialize().
+  void InitializeThreads();
+
+  // Initializes modules_ on behalf of Initialize().
+  void InitializeModules();
+
+  std::vector<std::unique_ptr<internal::ThreadSnapshotFuchsia>> threads_;
+  std::vector<std::unique_ptr<internal::ModuleSnapshotElf>> modules_;
+  ProcessReaderFuchsia process_reader_;
   std::map<std::string, std::string> annotations_simple_map_;
+  InitializationStateDcheck initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotFuchsia);
 };
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc
new file mode 100644
index 0000000..ce1aeb33
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc
@@ -0,0 +1,96 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "snapshot/fuchsia/thread_snapshot_fuchsia.h"
+
+#include "base/logging.h"
+
+namespace crashpad {
+namespace internal {
+
+ThreadSnapshotFuchsia::ThreadSnapshotFuchsia()
+    : ThreadSnapshot(),
+      context_arch_(),
+      context_(),
+      stack_(),
+      thread_id_(ZX_KOID_INVALID),
+      thread_specific_data_address_(0),
+      initialized_() {}
+
+ThreadSnapshotFuchsia::~ThreadSnapshotFuchsia() {}
+
+bool ThreadSnapshotFuchsia::Initialize(
+    ProcessReaderFuchsia* process_reader,
+    const ProcessReaderFuchsia::Thread& thread) {
+  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+
+#if defined(ARCH_CPU_X86_64)
+  context_.architecture = kCPUArchitectureX86_64;
+  context_.x86_64 = &context_arch_;
+// TODO(scottmg): Implement context capture for x64.
+#elif defined(ARCH_CPU_ARM64)
+  context_.architecture = kCPUArchitectureARM64;
+  context_.arm64 = &context_arch_;
+// TODO(scottmg): Implement context capture for arm64.
+#else
+#error Port.
+#endif
+
+  // TODO(scottmg): https://crashpad.chromium.org/bug/196. Initialize stack_ and
+  // TLS address here. API request for stack range filed upstream at ZX-1748.
+
+  thread_id_ = thread.id;
+
+  INITIALIZATION_STATE_SET_VALID(initialized_);
+  return true;
+}
+
+const CPUContext* ThreadSnapshotFuchsia::Context() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return &context_;
+}
+
+const MemorySnapshot* ThreadSnapshotFuchsia::Stack() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return &stack_;
+}
+
+uint64_t ThreadSnapshotFuchsia::ThreadID() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return thread_id_;
+}
+
+int ThreadSnapshotFuchsia::SuspendCount() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  // There is not (currently) a suspend count for threads on Fuchsia.
+  return 0;
+}
+
+int ThreadSnapshotFuchsia::Priority() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  // There is not (currently) thread priorities on Fuchsia.
+  return 0;
+}
+
+uint64_t ThreadSnapshotFuchsia::ThreadSpecificDataAddress() const {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return thread_specific_data_address_;
+}
+
+std::vector<const MemorySnapshot*> ThreadSnapshotFuchsia::ExtraMemory() const {
+  return std::vector<const MemorySnapshot*>();
+}
+
+}  // namespace internal
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h
new file mode 100644
index 0000000..db975976
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h
@@ -0,0 +1,81 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_
+#define CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_
+
+#include <stdint.h>
+#include <zircon/types.h>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "snapshot/cpu_context.h"
+#include "snapshot/fuchsia/process_reader_fuchsia.h"
+#include "snapshot/memory_snapshot.h"
+#include "snapshot/memory_snapshot_generic.h"
+#include "snapshot/thread_snapshot.h"
+#include "util/misc/initialization_state_dcheck.h"
+
+namespace crashpad {
+namespace internal {
+
+//! \brief A ThreadSnapshot of a thread on a Fuchsia system.
+class ThreadSnapshotFuchsia final : public ThreadSnapshot {
+ public:
+  ThreadSnapshotFuchsia();
+  ~ThreadSnapshotFuchsia() override;
+
+  //! \brief Initializes the object.
+  //!
+  //! \param[in] process_reader A ProcessReaderFuchsia for the process
+  //!     containing the thread.
+  //! \param[in] thread The thread within the ProcessReaderFuchsia for
+  //!     which the snapshot should be created.
+  //!
+  //! \return `true` if the snapshot could be created, `false` otherwise with
+  //!     a message logged.
+  bool Initialize(ProcessReaderFuchsia* process_reader,
+                  const ProcessReaderFuchsia::Thread& thread);
+
+  // ThreadSnapshot:
+
+  const CPUContext* Context() const override;
+  const MemorySnapshot* Stack() const override;
+  uint64_t ThreadID() const override;
+  int SuspendCount() const override;
+  int Priority() const override;
+  uint64_t ThreadSpecificDataAddress() const override;
+  std::vector<const MemorySnapshot*> ExtraMemory() const override;
+
+ private:
+#if defined(ARCH_CPU_X86_64)
+  CPUContextX86_64 context_arch_;
+#elif defined(ARCH_CPU_ARM64)
+  CPUContextARM64 context_arch_;
+#else
+#error Port.
+#endif
+  CPUContext context_;
+  MemorySnapshotGeneric<ProcessReaderFuchsia> stack_;
+  zx_koid_t thread_id_;
+  zx_vaddr_t thread_specific_data_address_;
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadSnapshotFuchsia);
+};
+
+}  // namespace internal
+}  // namespace crashpad
+
+#endif  // CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
index 498b1f79..fa2e8f9 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
@@ -18,7 +18,7 @@
 
 #include "base/logging.h"
 #include "snapshot/linux/cpu_context_linux.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/linux/signal_context.h"
 #include "util/linux/traits.h"
 #include "util/misc/reinterpret_bytes.h"
@@ -43,7 +43,7 @@
 #if defined(ARCH_CPU_X86_FAMILY)
 template <>
 bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
-    ProcessReader* reader,
+    ProcessReaderLinux* reader,
     LinuxVMAddress context_address) {
   UContext<ContextTraits32> ucontext;
   if (!reader->Memory()->Read(context_address, sizeof(ucontext), &ucontext)) {
@@ -79,7 +79,7 @@
 
 template <>
 bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
-    ProcessReader* reader,
+    ProcessReaderLinux* reader,
     LinuxVMAddress context_address) {
   UContext<ContextTraits64> ucontext;
   if (!reader->Memory()->Read(context_address, sizeof(ucontext), &ucontext)) {
@@ -99,7 +99,7 @@
 
 template <>
 bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>(
-    ProcessReader* reader,
+    ProcessReaderLinux* reader,
     LinuxVMAddress context_address) {
   context_.architecture = kCPUArchitectureARM;
   context_.arm = &context_union_.arm;
@@ -179,7 +179,7 @@
 
 template <>
 bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>(
-    ProcessReader* reader,
+    ProcessReaderLinux* reader,
     LinuxVMAddress context_address) {
   context_.architecture = kCPUArchitectureARM64;
   context_.arm64 = &context_union_.arm64;
@@ -253,7 +253,7 @@
 
 #endif  // ARCH_CPU_X86_FAMILY
 
-bool ExceptionSnapshotLinux::Initialize(ProcessReader* process_reader,
+bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
                                         LinuxVMAddress siginfo_address,
                                         LinuxVMAddress context_address,
                                         pid_t thread_id) {
@@ -278,7 +278,7 @@
 }
 
 template <typename Traits>
-bool ExceptionSnapshotLinux::ReadSiginfo(ProcessReader* reader,
+bool ExceptionSnapshotLinux::ReadSiginfo(ProcessReaderLinux* reader,
                                          LinuxVMAddress siginfo_address) {
   Siginfo<Traits> siginfo;
   if (!reader->Memory()->Read(siginfo_address, sizeof(siginfo), &siginfo)) {
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
index 7394966..0dcead7b 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
@@ -24,7 +24,7 @@
 #include "build/build_config.h"
 #include "snapshot/cpu_context.h"
 #include "snapshot/exception_snapshot.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/memory_snapshot.h"
 #include "util/linux/address_types.h"
 #include "util/misc/initialization_state_dcheck.h"
@@ -41,7 +41,8 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the process that received
+  //! \param[in] process_reader A ProcessReaderLinux for the process that
+  //! received
   //!     the signal.
   //! \param[in] siginfo_address The address in the target process' address
   //!     space of the siginfo_t passed to the signal handler.
@@ -51,7 +52,7 @@
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
+  bool Initialize(ProcessReaderLinux* process_reader,
                   LinuxVMAddress siginfo_address,
                   LinuxVMAddress context_address,
                   pid_t thread_id);
@@ -68,10 +69,10 @@
 
  private:
   template <typename Traits>
-  bool ReadSiginfo(ProcessReader* reader, LinuxVMAddress siginfo_address);
+  bool ReadSiginfo(ProcessReaderLinux* reader, LinuxVMAddress siginfo_address);
 
   template <typename Traits>
-  bool ReadContext(ProcessReader* reader, LinuxVMAddress context_address);
+  bool ReadContext(ProcessReaderLinux* reader, LinuxVMAddress context_address);
 
   union {
 #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
index 24f0ef5..4add607d 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
@@ -25,7 +25,7 @@
 #include "base/strings/stringprintf.h"
 #include "gtest/gtest.h"
 #include "snapshot/cpu_architecture.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/linux/signal_context.h"
 #include "sys/syscall.h"
 #include "test/errors.h"
@@ -271,7 +271,7 @@
   FakePtraceConnection connection;
   ASSERT_TRUE(connection.Initialize(getpid()));
 
-  ProcessReader process_reader;
+  ProcessReaderLinux process_reader;
   ASSERT_TRUE(process_reader.Initialize(&connection));
 
   siginfo_t siginfo;
@@ -348,7 +348,7 @@
     FakePtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(getpid()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
 
     internal::ExceptionSnapshotLinux exception;
@@ -411,7 +411,7 @@
     FakePtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(getpid()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
 
     internal::ExceptionSnapshotLinux exception;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc
deleted file mode 100644
index dfe9d33..0000000
--- a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "snapshot/linux/memory_snapshot_linux.h"
-
-#include <memory>
-
-namespace crashpad {
-namespace internal {
-
-MemorySnapshotLinux::MemorySnapshotLinux()
-    : MemorySnapshot(),
-      process_reader_(nullptr),
-      address_(0),
-      size_(0),
-      initialized_() {
-}
-
-MemorySnapshotLinux::~MemorySnapshotLinux() {
-}
-
-void MemorySnapshotLinux::Initialize(ProcessReader* process_reader,
-                                     LinuxVMAddress address,
-                                     size_t size) {
-  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
-  process_reader_ = process_reader;
-  address_ = address;
-  size_ = size;
-  INITIALIZATION_STATE_SET_VALID(initialized_);
-}
-
-uint64_t MemorySnapshotLinux::Address() const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-  return address_;
-}
-
-size_t MemorySnapshotLinux::Size() const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-  return size_;
-}
-
-bool MemorySnapshotLinux::Read(Delegate* delegate) const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-
-  if (size_ == 0) {
-    return delegate->MemorySnapshotDelegateRead(nullptr, size_);
-  }
-
-  std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]);
-  if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) {
-    return false;
-  }
-  return delegate->MemorySnapshotDelegateRead(buffer.get(), size_);
-}
-
-const MemorySnapshot* MemorySnapshotLinux::MergeWithOtherSnapshot(
-    const MemorySnapshot* other) const {
-  return MergeWithOtherSnapshotImpl(this, other);
-}
-
-}  // namespace internal
-}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h
deleted file mode 100644
index 8b4bcf8..0000000
--- a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CRASHPAD_SNAPSHOT_LINUX_MEMORY_SNAPSHOT_LINUX_H_
-#define CRASHPAD_SNAPSHOT_LINUX_MEMORY_SNAPSHOT_LINUX_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "snapshot/linux/process_reader.h"
-#include "snapshot/memory_snapshot.h"
-#include "util/linux/address_types.h"
-#include "util/misc/initialization_state_dcheck.h"
-
-namespace crashpad {
-namespace internal {
-
-//! \brief A MemorySnapshot of a memory region in a process on the running
-//!     system, when the system runs Linux.
-class MemorySnapshotLinux final : public MemorySnapshot {
- public:
-  MemorySnapshotLinux();
-  ~MemorySnapshotLinux() override;
-
-  //! \brief Initializes the object.
-  //!
-  //! Memory is read lazily. No attempt is made to read the memory snapshot data
-  //! until Read() is called, and the memory snapshot data is discared when
-  //! Read() returns.
-  //!
-  //! \param[in] process_reader A reader for the process being snapshotted.
-  //! \param[in] address The base address of the memory region to snapshot, in
-  //!     the snapshot process’ address space.
-  //! \param[in] size The size of the memory region to snapshot.
-  void Initialize(ProcessReader* process_reader,
-                  LinuxVMAddress address,
-                  size_t size);
-
-  // MemorySnapshot:
-
-  uint64_t Address() const override;
-  size_t Size() const override;
-  bool Read(Delegate* delegate) const override;
-  const MemorySnapshot* MergeWithOtherSnapshot(
-      const MemorySnapshot* other) const override;
-
- private:
-  template <class T>
-  friend const MemorySnapshot* MergeWithOtherSnapshotImpl(
-      const T* self,
-      const MemorySnapshot* other);
-
-  ProcessReader* process_reader_;  // weak
-  uint64_t address_;
-  size_t size_;
-  InitializationStateDcheck initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemorySnapshotLinux);
-};
-
-}  // namespace internal
-}  // namespace crashpad
-
-#endif  // CRASHPAD_SNAPSHOT_LINUX_MEMORY_SNAPSHOT_LINUX_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
similarity index 91%
rename from third_party/crashpad/crashpad/snapshot/linux/process_reader.cc
rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
index 0f196c6..40b1406 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 
 #include <elf.h>
 #include <errno.h>
@@ -46,7 +46,7 @@
 
 }  // namespace
 
-ProcessReader::Thread::Thread()
+ProcessReaderLinux::Thread::Thread()
     : thread_info(),
       stack_region_address(0),
       stack_region_size(0),
@@ -54,9 +54,10 @@
       static_priority(-1),
       nice_value(-1) {}
 
-ProcessReader::Thread::~Thread() {}
+ProcessReaderLinux::Thread::~Thread() {}
 
-bool ProcessReader::Thread::InitializePtrace(PtraceConnection* connection) {
+bool ProcessReaderLinux::Thread::InitializePtrace(
+    PtraceConnection* connection) {
   if (!connection->GetThreadInfo(tid, &thread_info)) {
     return false;
   }
@@ -89,7 +90,7 @@
   return true;
 }
 
-void ProcessReader::Thread::InitializeStack(ProcessReader* reader) {
+void ProcessReaderLinux::Thread::InitializeStack(ProcessReaderLinux* reader) {
   LinuxVMAddress stack_pointer;
 #if defined(ARCH_CPU_X86_FAMILY)
   stack_pointer = reader->Is64Bit() ? thread_info.thread_context.t64.rsp
@@ -169,12 +170,12 @@
   }
 }
 
-ProcessReader::Module::Module()
+ProcessReaderLinux::Module::Module()
     : name(), elf_reader(nullptr), type(ModuleSnapshot::kModuleTypeUnknown) {}
 
-ProcessReader::Module::~Module() = default;
+ProcessReaderLinux::Module::~Module() = default;
 
-ProcessReader::ProcessReader()
+ProcessReaderLinux::ProcessReaderLinux()
     : connection_(),
       process_info_(),
       memory_map_(),
@@ -187,9 +188,9 @@
       initialized_modules_(false),
       initialized_() {}
 
-ProcessReader::~ProcessReader() {}
+ProcessReaderLinux::~ProcessReaderLinux() {}
 
-bool ProcessReader::Initialize(PtraceConnection* connection) {
+bool ProcessReaderLinux::Initialize(PtraceConnection* connection) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
   DCHECK(connection);
   connection_ = connection;
@@ -213,12 +214,13 @@
   return true;
 }
 
-bool ProcessReader::StartTime(timeval* start_time) const {
+bool ProcessReaderLinux::StartTime(timeval* start_time) const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   return process_info_.StartTime(start_time);
 }
 
-bool ProcessReader::CPUTimes(timeval* user_time, timeval* system_time) const {
+bool ProcessReaderLinux::CPUTimes(timeval* user_time,
+                                  timeval* system_time) const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   timerclear(user_time);
   timerclear(system_time);
@@ -253,7 +255,7 @@
   return true;
 }
 
-const std::vector<ProcessReader::Thread>& ProcessReader::Threads() {
+const std::vector<ProcessReaderLinux::Thread>& ProcessReaderLinux::Threads() {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   if (!initialized_threads_) {
     InitializeThreads();
@@ -261,7 +263,7 @@
   return threads_;
 }
 
-const std::vector<ProcessReader::Module>& ProcessReader::Modules() {
+const std::vector<ProcessReaderLinux::Module>& ProcessReaderLinux::Modules() {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
   if (!initialized_modules_) {
     InitializeModules();
@@ -269,7 +271,7 @@
   return modules_;
 }
 
-void ProcessReader::InitializeThreads() {
+void ProcessReaderLinux::InitializeThreads() {
   DCHECK(threads_.empty());
 
   pid_t pid = ProcessID();
@@ -326,7 +328,7 @@
   DCHECK(main_thread_found);
 }
 
-void ProcessReader::InitializeModules() {
+void ProcessReaderLinux::InitializeModules() {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   AuxiliaryVector aux;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h
similarity index 91%
rename from third_party/crashpad/crashpad/snapshot/linux/process_reader.h
rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h
index 59a3c7ef..2e89655 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_
-#define CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_
+#ifndef CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_
+#define CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_
 
 #include <sys/time.h>
 #include <sys/types.h>
@@ -38,7 +38,7 @@
 
 //! \brief Accesses information about another process, identified by a process
 //!     ID.
-class ProcessReader {
+class ProcessReaderLinux {
  public:
   //! \brief Contains information about a thread that belongs to a process.
   struct Thread {
@@ -54,10 +54,10 @@
     int nice_value;
 
    private:
-    friend class ProcessReader;
+    friend class ProcessReaderLinux;
 
     bool InitializePtrace(PtraceConnection* connection);
-    void InitializeStack(ProcessReader* reader);
+    void InitializeStack(ProcessReaderLinux* reader);
   };
 
   //! \brief Contains information about a module loaded into a process.
@@ -71,7 +71,7 @@
     //! \brief An image reader for the module.
     //!
     //! The lifetime of this ElfImageReader is scoped to the lifetime of the
-    //! ProcessReader that created it.
+    //! ProcessReaderLinux that created it.
     //!
     //! This field may be `nullptr` if a reader could not be created for the
     //! module.
@@ -81,8 +81,8 @@
     ModuleSnapshot::ModuleType type;
   };
 
-  ProcessReader();
-  ~ProcessReader();
+  ProcessReaderLinux();
+  ~ProcessReaderLinux();
 
   //! \brief Initializes this object.
   //!
@@ -152,9 +152,9 @@
   bool initialized_modules_;
   InitializationStateDcheck initialized_;
 
-  DISALLOW_COPY_AND_ASSIGN(ProcessReader);
+  DISALLOW_COPY_AND_ASSIGN(ProcessReaderLinux);
 };
 
 }  // namespace crashpad
 
-#endif  // CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_
+#endif  // CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
similarity index 92%
rename from third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc
rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
index a8190b3..11a606a9 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 
 #include <errno.h>
 #include <link.h>
@@ -55,11 +55,11 @@
   return syscall(SYS_gettid);
 }
 
-TEST(ProcessReader, SelfBasic) {
+TEST(ProcessReaderLinux, SelfBasic) {
   FakePtraceConnection connection;
   connection.Initialize(getpid());
 
-  ProcessReader process_reader;
+  ProcessReaderLinux process_reader;
   ASSERT_TRUE(process_reader.Initialize(&connection));
 
 #if defined(ARCH_CPU_64_BITS)
@@ -92,7 +92,7 @@
     DirectPtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(ChildPID()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
 
 #if !defined(ARCH_CPU_64_BITS)
@@ -115,7 +115,7 @@
   DISALLOW_COPY_AND_ASSIGN(BasicChildTest);
 };
 
-TEST(ProcessReader, ChildBasic) {
+TEST(ProcessReaderLinux, ChildBasic) {
   BasicChildTest test;
   test.Run();
 }
@@ -241,7 +241,7 @@
 using ThreadMap = std::map<pid_t, TestThreadPool::ThreadExpectation>;
 
 void ExpectThreads(const ThreadMap& thread_map,
-                   const std::vector<ProcessReader::Thread>& threads,
+                   const std::vector<ProcessReaderLinux::Thread>& threads,
                    const pid_t pid) {
   ASSERT_EQ(threads.size(), thread_map.size());
   MemoryMap memory_map;
@@ -302,9 +302,9 @@
     DirectPtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(ChildPID()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
-    const std::vector<ProcessReader::Thread>& threads =
+    const std::vector<ProcessReaderLinux::Thread>& threads =
         process_reader.Threads();
     ExpectThreads(thread_map, threads, ChildPID());
   }
@@ -350,12 +350,12 @@
   DISALLOW_COPY_AND_ASSIGN(ChildThreadTest);
 };
 
-TEST(ProcessReader, ChildWithThreads) {
+TEST(ProcessReaderLinux, ChildWithThreads) {
   ChildThreadTest test;
   test.Run();
 }
 
-TEST(ProcessReader, ChildThreadsWithSmallUserStacks) {
+TEST(ProcessReaderLinux, ChildThreadsWithSmallUserStacks) {
   ChildThreadTest test(PTHREAD_STACK_MIN);
   test.Run();
 }
@@ -379,10 +379,10 @@
     DirectPtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(ChildPID()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
 
-    const std::vector<ProcessReader::Thread>& threads =
+    const std::vector<ProcessReaderLinux::Thread>& threads =
         process_reader.Threads();
     ASSERT_EQ(threads.size(), 1u);
 
@@ -440,7 +440,7 @@
   DISALLOW_COPY_AND_ASSIGN(ChildWithSplitStackTest);
 };
 
-TEST(ProcessReader, ChildWithSplitStack) {
+TEST(ProcessReaderLinux, ChildWithSplitStack) {
   ChildWithSplitStackTest test;
   test.Run();
 }
@@ -454,7 +454,7 @@
                          LinuxVMAddress{info->dlpi_addr},
                          FromPointerCast<LinuxVMAddress>(info->dlpi_phdr)));
   auto modules =
-      reinterpret_cast<const std::vector<ProcessReader::Module>*>(data);
+      reinterpret_cast<const std::vector<ProcessReaderLinux::Module>*>(data);
 
   auto phdr_addr = FromPointerCast<LinuxVMAddress>(info->dlpi_phdr);
 
@@ -482,7 +482,8 @@
 }
 #endif  // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21
 
-void ExpectModulesFromSelf(const std::vector<ProcessReader::Module>& modules) {
+void ExpectModulesFromSelf(
+    const std::vector<ProcessReaderLinux::Module>& modules) {
   for (const auto& module : modules) {
     EXPECT_FALSE(module.name.empty());
     EXPECT_NE(module.type, ModuleSnapshot::kModuleTypeUnknown);
@@ -490,19 +491,20 @@
 
 // Android doesn't provide dl_iterate_phdr on ARM until API 21.
 #if !defined(OS_ANDROID) || !defined(ARCH_CPU_ARMEL) || __ANDROID_API__ >= 21
-  EXPECT_EQ(dl_iterate_phdr(
-                ExpectFindModule,
-                reinterpret_cast<void*>(
-                    const_cast<std::vector<ProcessReader::Module>*>(&modules))),
-            0);
+  EXPECT_EQ(
+      dl_iterate_phdr(
+          ExpectFindModule,
+          reinterpret_cast<void*>(
+              const_cast<std::vector<ProcessReaderLinux::Module>*>(&modules))),
+      0);
 #endif  // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21
 }
 
-TEST(ProcessReader, SelfModules) {
+TEST(ProcessReaderLinux, SelfModules) {
   FakePtraceConnection connection;
   connection.Initialize(getpid());
 
-  ProcessReader process_reader;
+  ProcessReaderLinux process_reader;
   ASSERT_TRUE(process_reader.Initialize(&connection));
 
   ExpectModulesFromSelf(process_reader.Modules());
@@ -518,7 +520,7 @@
     DirectPtraceConnection connection;
     ASSERT_TRUE(connection.Initialize(ChildPID()));
 
-    ProcessReader process_reader;
+    ProcessReaderLinux process_reader;
     ASSERT_TRUE(process_reader.Initialize(&connection));
 
     ExpectModulesFromSelf(process_reader.Modules());
@@ -529,7 +531,7 @@
   DISALLOW_COPY_AND_ASSIGN(ChildModuleTest);
 };
 
-TEST(ProcessReader, ChildModules) {
+TEST(ProcessReaderLinux, ChildModules) {
   ChildModuleTest test;
   test.Run();
 }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc
index 8397ad9..9e21244 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc
@@ -213,9 +213,9 @@
 }
 
 void ProcessSnapshotLinux::InitializeThreads() {
-  const std::vector<ProcessReader::Thread>& process_reader_threads =
+  const std::vector<ProcessReaderLinux::Thread>& process_reader_threads =
       process_reader_.Threads();
-  for (const ProcessReader::Thread& process_reader_thread :
+  for (const ProcessReaderLinux::Thread& process_reader_thread :
        process_reader_threads) {
     auto thread = std::make_unique<internal::ThreadSnapshotLinux>();
     if (thread->Initialize(&process_reader_, process_reader_thread)) {
@@ -225,9 +225,11 @@
 }
 
 void ProcessSnapshotLinux::InitializeModules() {
-  for (const ProcessReader::Module& reader_module : process_reader_.Modules()) {
-    auto module = std::make_unique<internal::ModuleSnapshotLinux>();
-    if (module->Initialize(reader_module)) {
+  for (const ProcessReaderLinux::Module& reader_module :
+       process_reader_.Modules()) {
+    auto module = std::make_unique<internal::ModuleSnapshotElf>(
+        reader_module.name, reader_module.elf_reader, reader_module.type);
+    if (module->Initialize()) {
       modules_.push_back(std::move(module));
     }
   }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h
index aa6964c..25c414d 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h
@@ -25,9 +25,9 @@
 
 #include "base/macros.h"
 #include "snapshot/crashpad_info_client_options.h"
+#include "snapshot/elf/module_snapshot_elf.h"
 #include "snapshot/linux/exception_snapshot_linux.h"
-#include "snapshot/linux/module_snapshot_linux.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/linux/system_snapshot_linux.h"
 #include "snapshot/linux/thread_snapshot_linux.h"
 #include "snapshot/memory_map_region_snapshot.h"
@@ -124,10 +124,10 @@
   UUID report_id_;
   UUID client_id_;
   std::vector<std::unique_ptr<internal::ThreadSnapshotLinux>> threads_;
-  std::vector<std::unique_ptr<internal::ModuleSnapshotLinux>> modules_;
+  std::vector<std::unique_ptr<internal::ModuleSnapshotElf>> modules_;
   std::unique_ptr<internal::ExceptionSnapshotLinux> exception_;
   internal::SystemSnapshotLinux system_;
-  ProcessReader process_reader_;
+  ProcessReaderLinux process_reader_;
   InitializationStateDcheck initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotLinux);
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
index c9c6438..4c39288 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
@@ -151,7 +151,7 @@
 
 SystemSnapshotLinux::~SystemSnapshotLinux() {}
 
-void SystemSnapshotLinux::Initialize(ProcessReader* process_reader,
+void SystemSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
                                      const timeval* snapshot_time) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
   process_reader_ = process_reader;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h
index a991450..d22c49a6 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h
@@ -22,7 +22,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/system_snapshot.h"
 #include "util/misc/initialization_state_dcheck.h"
 
@@ -44,9 +44,9 @@
   //! \param[in] process_reader A reader for the process being snapshotted.
   //!     \n\n
   //!     It seems odd that a system snapshot implementation would need a
-  //!     ProcessReader, but some of the information reported about the system
-  //!     depends on the process it’s being reported for. For example, the
-  //!     architecture returned by GetCPUArchitecture() should be the
+  //!     ProcessReaderLinux, but some of the information reported about the
+  //!     system depends on the process it’s being reported for. For example,
+  //!     the architecture returned by GetCPUArchitecture() should be the
   //!     architecture of the process, which may be different than the native
   //!     architecture of the system: an x86_64 system can run both x86_64 and
   //!     32-bit x86 processes.
@@ -57,7 +57,8 @@
   //!     Otherwise, it would need to base its determination on the current
   //!     time, which may be different than the snapshot time for snapshots
   //!     generated around the daylight saving transition time.
-  void Initialize(ProcessReader* process_reader, const timeval* snapshot_time);
+  void Initialize(ProcessReaderLinux* process_reader,
+                  const timeval* snapshot_time);
 
   // SystemSnapshot:
 
@@ -91,7 +92,7 @@
 
   std::string os_version_full_;
   std::string os_version_build_;
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderLinux* process_reader_;  // weak
   const timeval* snapshot_time_;  // weak
 #if defined(ARCH_CPU_X86_FAMILY)
   CpuidReader cpuid_;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc
index a91dfa41..46d3845f 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc
@@ -21,7 +21,7 @@
 
 #include "build/build_config.h"
 #include "gtest/gtest.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "test/errors.h"
 #include "test/linux/fake_ptrace_connection.h"
 
@@ -33,7 +33,7 @@
   FakePtraceConnection connection;
   ASSERT_TRUE(connection.Initialize(getpid()));
 
-  ProcessReader process_reader;
+  ProcessReaderLinux process_reader;
   ASSERT_TRUE(process_reader.Initialize(&connection));
 
   timeval snapshot_time;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
index f465a59..084ed73 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
+++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
@@ -37,9 +37,8 @@
 ThreadSnapshotLinux::~ThreadSnapshotLinux() {
 }
 
-bool ThreadSnapshotLinux::Initialize(
-    ProcessReader* process_reader,
-    const ProcessReader::Thread& thread) {
+bool ThreadSnapshotLinux::Initialize(ProcessReaderLinux* process_reader,
+                                     const ProcessReaderLinux::Thread& thread) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
 #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
index 1ba291d..8fc7e17 100644
--- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
+++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
@@ -20,9 +20,9 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "snapshot/cpu_context.h"
-#include "snapshot/linux/memory_snapshot_linux.h"
-#include "snapshot/linux/process_reader.h"
+#include "snapshot/linux/process_reader_linux.h"
 #include "snapshot/memory_snapshot.h"
+#include "snapshot/memory_snapshot_generic.h"
 #include "snapshot/thread_snapshot.h"
 #include "util/misc/initialization_state_dcheck.h"
 
@@ -37,15 +37,15 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the process containing the
-  //!     thread.
-  //! \param[in] thread The thread within the ProcessReader for
+  //! \param[in] process_reader A ProcessReaderLinux for the process containing
+  //!     the thread.
+  //! \param[in] thread The thread within the ProcessReaderLinux for
   //!     which the snapshot should be created.
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     a message logged.
-  bool Initialize(ProcessReader* process_reader,
-                  const ProcessReader::Thread& thread);
+  bool Initialize(ProcessReaderLinux* process_reader,
+                  const ProcessReaderLinux::Thread& thread);
 
   // ThreadSnapshot:
 
@@ -70,7 +70,7 @@
 #endif  // ARCH_CPU_X86_FAMILY
   } context_union_;
   CPUContext context_;
-  MemorySnapshotLinux stack_;
+  MemorySnapshotGeneric<ProcessReaderLinux> stack_;
   LinuxVMAddress thread_specific_data_address_;
   pid_t thread_id_;
   int priority_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc
index 92c8450..50d1a12 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc
@@ -17,7 +17,7 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "snapshot/mac/cpu_context_mac.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "util/mach/exception_behaviors.h"
 #include "util/mach/exception_types.h"
 #include "util/mach/symbolic_constants_mach.h"
@@ -41,7 +41,7 @@
 ExceptionSnapshotMac::~ExceptionSnapshotMac() {
 }
 
-bool ExceptionSnapshotMac::Initialize(ProcessReader* process_reader,
+bool ExceptionSnapshotMac::Initialize(ProcessReaderMac* process_reader,
                                       exception_behavior_t behavior,
                                       thread_t exception_thread,
                                       exception_type_t exception,
@@ -126,8 +126,9 @@
     exception_code_0_ = unsigned_exception_code_0;
   }
 
-  const ProcessReader::Thread* thread = nullptr;
-  for (const ProcessReader::Thread& loop_thread : process_reader->Threads()) {
+  const ProcessReaderMac::Thread* thread = nullptr;
+  for (const ProcessReaderMac::Thread& loop_thread :
+       process_reader->Threads()) {
     if (exception_thread == loop_thread.port) {
       thread = &loop_thread;
       break;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h
index 9a6ddcaa..52ef519 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h
@@ -29,7 +29,7 @@
 
 namespace crashpad {
 
-class ProcessReader;
+class ProcessReaderMac;
 
 namespace internal {
 
@@ -45,8 +45,8 @@
   //! Other than \a process_reader, the parameters may be passed directly
   //! through from a Mach exception handler.
   //!
-  //! \param[in] process_reader A ProcessReader for the task that sustained the
-  //!     exception.
+  //! \param[in] process_reader A ProcessReaderMac for the task that sustained
+  //!     the exception.
   //! \param[in] behavior
   //! \param[in] exception_thread
   //! \param[in] exception
@@ -58,7 +58,7 @@
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
+  bool Initialize(ProcessReaderMac* process_reader,
                   exception_behavior_t behavior,
                   thread_t exception_thread,
                   exception_type_t exception,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc
index bb8f7e2..b02acae 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc
@@ -24,7 +24,7 @@
 #include "client/crashpad_info.h"
 #include "client/simple_string_dictionary.h"
 #include "snapshot/mac/mach_o_image_reader.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/snapshot_constants.h"
 #include "util/mach/task_memory.h"
 #include "util/stdlib/strnlen.h"
@@ -32,13 +32,12 @@
 namespace crashpad {
 
 MachOImageAnnotationsReader::MachOImageAnnotationsReader(
-    ProcessReader* process_reader,
+    ProcessReaderMac* process_reader,
     const MachOImageReader* image_reader,
     const std::string& name)
     : name_(name),
       process_reader_(process_reader),
-      image_reader_(image_reader) {
-}
+      image_reader_(image_reader) {}
 
 std::vector<std::string> MachOImageAnnotationsReader::Vector() const {
   std::vector<std::string> vector_annotations;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h
index 06d2bea..a56b073 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h
@@ -26,7 +26,7 @@
 namespace crashpad {
 
 class MachOImageReader;
-class ProcessReader;
+class ProcessReaderMac;
 
 //! \brief A reader for annotations stored in a Mach-O image mapped into another
 //!     process.
@@ -54,7 +54,7 @@
   //!     contained within the remote process.
   //! \param[in] name The module’s name, a string to be used in logged messages.
   //!     This string is for diagnostic purposes only, and may be empty.
-  MachOImageAnnotationsReader(ProcessReader* process_reader,
+  MachOImageAnnotationsReader(ProcessReaderMac* process_reader,
                               const MachOImageReader* image_reader,
                               const std::string& name);
 
@@ -91,7 +91,7 @@
       std::vector<AnnotationSnapshot>* vector_annotations) const;
 
   std::string name_;
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderMac* process_reader_;  // weak
   const MachOImageReader* image_reader_;  // weak
 
   DISALLOW_COPY_AND_ASSIGN(MachOImageAnnotationsReader);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc
index f486c1d..6930250 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc
@@ -33,7 +33,7 @@
 #include "client/crashpad_info.h"
 #include "client/simple_string_dictionary.h"
 #include "gtest/gtest.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "test/errors.h"
 #include "test/mac/mach_errors.h"
 #include "test/mac/mach_multiprocess.h"
@@ -161,15 +161,15 @@
     EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "pid_for_task");
     EXPECT_EQ(task_pid, ChildPID());
 
-    ProcessReader process_reader;
+    ProcessReaderMac process_reader;
     bool rv = process_reader.Initialize(task);
     if (!rv) {
       ADD_FAILURE();
     } else {
-      const std::vector<ProcessReader::Module>& modules =
+      const std::vector<ProcessReaderMac::Module>& modules =
           process_reader.Modules();
       std::vector<std::string> all_annotations_vector;
-      for (const ProcessReader::Module& module : modules) {
+      for (const ProcessReaderMac::Module& module : modules) {
         if (module.reader) {
           MachOImageAnnotationsReader module_annotations_reader(
               &process_reader, module.reader, module.name);
@@ -271,7 +271,7 @@
   // MachMultiprocess:
 
   void MachMultiprocessParent() override {
-    ProcessReader process_reader;
+    ProcessReaderMac process_reader;
     ASSERT_TRUE(process_reader.Initialize(ChildTask()));
 
     // Wait for the child process to indicate that it’s done setting up its
@@ -281,11 +281,11 @@
 
     // Verify the “simple map” and object-based annotations set via the
     // CrashpadInfo interface.
-    const std::vector<ProcessReader::Module>& modules =
+    const std::vector<ProcessReaderMac::Module>& modules =
         process_reader.Modules();
     std::map<std::string, std::string> all_annotations_simple_map;
     std::vector<AnnotationSnapshot> all_annotations;
-    for (const ProcessReader::Module& module : modules) {
+    for (const ProcessReaderMac::Module& module : modules) {
       MachOImageAnnotationsReader module_annotations_reader(
           &process_reader, module.reader, module.name);
       std::map<std::string, std::string> module_annotations_simple_map =
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
index 8a65726..6baee770 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
@@ -26,7 +26,7 @@
 #include "client/crashpad_info.h"
 #include "snapshot/mac/mach_o_image_segment_reader.h"
 #include "snapshot/mac/mach_o_image_symbol_table_reader.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "util/mac/checked_mach_address_range.h"
 #include "util/misc/implicit_cast.h"
 
@@ -62,7 +62,7 @@
 MachOImageReader::~MachOImageReader() {
 }
 
-bool MachOImageReader::Initialize(ProcessReader* process_reader,
+bool MachOImageReader::Initialize(ProcessReaderMac* process_reader,
                                   mach_vm_address_t address,
                                   const std::string& name) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h
index c16cce9..aded956 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h
@@ -33,7 +33,7 @@
 
 class MachOImageSegmentReader;
 class MachOImageSymbolTableReader;
-class ProcessReader;
+class ProcessReaderMac;
 
 //! \brief A reader for Mach-O images mapped into another process.
 //!
@@ -64,7 +64,7 @@
   //!
   //! \return `true` if the image was read successfully, including all load
   //!     commands. `false` otherwise, with an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
+  bool Initialize(ProcessReaderMac* process_reader,
                   mach_vm_address_t address,
                   const std::string& name);
 
@@ -337,7 +337,7 @@
   mutable std::unique_ptr<MachOImageSymbolTableReader> symbol_table_;
 
   std::unique_ptr<process_types::dylib_command> id_dylib_command_;
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderMac* process_reader_;  // weak
   uint32_t file_type_;
   InitializationStateDcheck initialized_;
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
index d6b801f8..625f8a7 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
@@ -29,7 +29,7 @@
 #include "client/crashpad_info.h"
 #include "gtest/gtest.h"
 #include "snapshot/mac/mach_o_image_segment_reader.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/mac/process_types.h"
 #include "test/mac/dyld.h"
 #include "util/misc/from_pointer_cast.h"
@@ -496,7 +496,7 @@
 }
 
 TEST(MachOImageReader, Self_MainExecutable) {
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
   const MachHeader* mh_execute_header =
@@ -531,7 +531,7 @@
 }
 
 TEST(MachOImageReader, Self_DyldImages) {
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
   uint32_t count = _dyld_image_count();
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
index 06e1daf4..1be829d 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
@@ -20,7 +20,7 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "util/mac/checked_mach_address_range.h"
 #include "util/mac/mac_util.h"
 #include "util/stdlib/strnlen.h"
@@ -47,7 +47,7 @@
 MachOImageSegmentReader::~MachOImageSegmentReader() {
 }
 
-bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader,
+bool MachOImageSegmentReader::Initialize(ProcessReaderMac* process_reader,
                                          mach_vm_address_t load_command_address,
                                          const std::string& load_command_info,
                                          const std::string& module_name,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h
index 20f891d..bdd5771 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h
@@ -62,7 +62,7 @@
   //!
   //! \return `true` if the load command was read successfully. `false`
   //!     otherwise, with an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
+  bool Initialize(ProcessReaderMac* process_reader,
                   mach_vm_address_t load_command_address,
                   const std::string& load_command_info,
                   const std::string& module_name,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc
index c5eb196..361253ce 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc
@@ -39,7 +39,7 @@
 class MachOImageSymbolTableReaderInitializer {
  public:
   MachOImageSymbolTableReaderInitializer(
-      ProcessReader* process_reader,
+      ProcessReaderMac* process_reader,
       const MachOImageSegmentReader* linkedit_segment,
       const std::string& module_info)
       : module_info_(module_info),
@@ -243,7 +243,7 @@
 
   std::string module_info_;
   CheckedMachAddressRange linkedit_range_;
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderMac* process_reader_;  // weak
   const MachOImageSegmentReader* linkedit_segment_;  // weak
 
   DISALLOW_COPY_AND_ASSIGN(MachOImageSymbolTableReaderInitializer);
@@ -259,7 +259,7 @@
 }
 
 bool MachOImageSymbolTableReader::Initialize(
-    ProcessReader* process_reader,
+    ProcessReaderMac* process_reader,
     const process_types::symtab_command* symtab_command,
     const process_types::dysymtab_command* dysymtab_command,
     const MachOImageSegmentReader* linkedit_segment,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h
index a097854..841b479a 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h
@@ -23,7 +23,7 @@
 
 #include "base/macros.h"
 #include "snapshot/mac/mach_o_image_segment_reader.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/mac/process_types.h"
 #include "util/misc/initialization_state_dcheck.h"
 
@@ -92,7 +92,7 @@
   //!
   //! \return `true` if the symbol table was read successfully. `false`
   //!     otherwise, with an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
+  bool Initialize(ProcessReaderMac* process_reader,
                   const process_types::symtab_command* symtab_command,
                   const process_types::dysymtab_command* dysymtab_command,
                   const MachOImageSegmentReader* linkedit_segment,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc
deleted file mode 100644
index ec1d460..0000000
--- a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "snapshot/mac/memory_snapshot_mac.h"
-
-#include <memory>
-
-#include "util/mach/task_memory.h"
-
-namespace crashpad {
-namespace internal {
-
-MemorySnapshotMac::MemorySnapshotMac()
-    : MemorySnapshot(),
-      process_reader_(nullptr),
-      address_(0),
-      size_(0),
-      initialized_() {
-}
-
-MemorySnapshotMac::~MemorySnapshotMac() {
-}
-
-void MemorySnapshotMac::Initialize(ProcessReader* process_reader,
-                                   uint64_t address,
-                                   uint64_t size) {
-  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
-  process_reader_ = process_reader;
-  address_ = address;
-  size_ = size;
-  INITIALIZATION_STATE_SET_VALID(initialized_);
-}
-
-uint64_t MemorySnapshotMac::Address() const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-  return address_;
-}
-
-size_t MemorySnapshotMac::Size() const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-  return size_;
-}
-
-bool MemorySnapshotMac::Read(Delegate* delegate) const {
-  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
-
-  if (size_ == 0) {
-    return delegate->MemorySnapshotDelegateRead(nullptr, size_);
-  }
-
-  std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]);
-  if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) {
-    return false;
-  }
-  return delegate->MemorySnapshotDelegateRead(buffer.get(), size_);
-}
-
-const MemorySnapshot* MemorySnapshotMac::MergeWithOtherSnapshot(
-    const MemorySnapshot* other) const {
-  return MergeWithOtherSnapshotImpl(this, other);
-}
-
-}  // namespace internal
-}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h
deleted file mode 100644
index f06fbf47..0000000
--- a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CRASHPAD_SNAPSHOT_MAC_MEMORY_SNAPSHOT_MAC_H_
-#define CRASHPAD_SNAPSHOT_MAC_MEMORY_SNAPSHOT_MAC_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "base/macros.h"
-#include "snapshot/mac/process_reader.h"
-#include "snapshot/memory_snapshot.h"
-#include "util/misc/initialization_state_dcheck.h"
-
-namespace crashpad {
-namespace internal {
-
-//! \brief A MemorySnapshot of a memory region in a process on the running
-//!     system, when the system runs macOS.
-class MemorySnapshotMac final : public MemorySnapshot {
- public:
-  MemorySnapshotMac();
-  ~MemorySnapshotMac() override;
-
-  //! \brief Initializes the object.
-  //!
-  //! Memory is read lazily. No attempt is made to read the memory snapshot data
-  //! until Read() is called, and the memory snapshot data is discared when
-  //! Read() returns.
-  //!
-  //! \param[in] process_reader A reader for the process being snapshotted.
-  //! \param[in] address The base address of the memory region to snapshot, in
-  //!     the snapshot process’ address space.
-  //! \param[in] size The size of the memory region to snapshot.
-  void Initialize(ProcessReader* process_reader,
-                  uint64_t address,
-                  uint64_t size);
-
-  // MemorySnapshot:
-
-  uint64_t Address() const override;
-  size_t Size() const override;
-  bool Read(Delegate* delegate) const override;
-  const MemorySnapshot* MergeWithOtherSnapshot(
-      const MemorySnapshot* other) const override;
-
- private:
-  template <class T>
-  friend const MemorySnapshot* MergeWithOtherSnapshotImpl(
-      const T* self,
-      const MemorySnapshot* other);
-
-  ProcessReader* process_reader_;  // weak
-  uint64_t address_;
-  uint64_t size_;
-  InitializationStateDcheck initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemorySnapshotMac);
-};
-
-}  // namespace internal
-}  // namespace crashpad
-
-#endif  // CRASHPAD_SNAPSHOT_MAC_MEMORY_SNAPSHOT_MAC_H_
diff --git a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc
index 19c4759d..4160897 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc
@@ -41,8 +41,8 @@
 }
 
 bool ModuleSnapshotMac::Initialize(
-    ProcessReader* process_reader,
-    const ProcessReader::Module& process_reader_module) {
+    ProcessReaderMac* process_reader,
+    const ProcessReaderMac::Module& process_reader_module) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
   process_reader_ = process_reader;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h
index 44c07910..fe2d40a1 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h
@@ -25,7 +25,7 @@
 #include "base/macros.h"
 #include "client/crashpad_info.h"
 #include "snapshot/crashpad_info_client_options.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/module_snapshot.h"
 #include "util/misc/initialization_state_dcheck.h"
 
@@ -45,15 +45,15 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the task containing the
+  //! \param[in] process_reader A ProcessReaderMac for the task containing the
   //!     module.
-  //! \param[in] process_reader_module The module within the ProcessReader for
-  //!     which the snapshot should be created.
+  //! \param[in] process_reader_module The module within the ProcessReaderMac
+  //!     for which the snapshot should be created.
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
-                  const ProcessReader::Module& process_reader_module);
+  bool Initialize(ProcessReaderMac* process_reader,
+                  const ProcessReaderMac::Module& process_reader_module);
 
   //! \brief Returns options from the module’s CrashpadInfo structure.
   //!
@@ -87,7 +87,7 @@
   std::string name_;
   time_t timestamp_;
   const MachOImageReader* mach_o_image_reader_;  // weak
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderMac* process_reader_;  // weak
   InitializationStateDcheck initialized_;
 
   DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotMac);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc
similarity index 94%
rename from third_party/crashpad/crashpad/snapshot/mac/process_reader.cc
rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc
index 6ddcff05..e142fd2 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 
 #include <AvailabilityMacros.h>
-#include <mach/mach_vm.h>
 #include <mach-o/loader.h>
+#include <mach/mach_vm.h>
 
 #include <algorithm>
 #include <utility>
@@ -71,7 +71,7 @@
 
 namespace crashpad {
 
-ProcessReader::Thread::Thread()
+ProcessReaderMac::Thread::Thread()
     : thread_context(),
       float_context(),
       debug_context(),
@@ -81,16 +81,13 @@
       thread_specific_data_address(0),
       port(THREAD_NULL),
       suspend_count(0),
-      priority(0) {
-}
+      priority(0) {}
 
-ProcessReader::Module::Module() : name(), reader(nullptr), timestamp(0) {
-}
+ProcessReaderMac::Module::Module() : name(), reader(nullptr), timestamp(0) {}
 
-ProcessReader::Module::~Module() {
-}
+ProcessReaderMac::Module::~Module() {}
 
-ProcessReader::ProcessReader()
+ProcessReaderMac::ProcessReaderMac()
     : process_info_(),
       threads_(),
       modules_(),
@@ -100,17 +97,16 @@
       initialized_(),
       is_64_bit_(false),
       initialized_threads_(false),
-      initialized_modules_(false) {
-}
+      initialized_modules_(false) {}
 
-ProcessReader::~ProcessReader() {
+ProcessReaderMac::~ProcessReaderMac() {
   for (const Thread& thread : threads_) {
     kern_return_t kr = mach_port_deallocate(mach_task_self(), thread.port);
     MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
   }
 }
 
-bool ProcessReader::Initialize(task_t task) {
+bool ProcessReaderMac::Initialize(task_t task) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
   if (!process_info_.InitializeWithTask(task)) {
@@ -126,12 +122,13 @@
   return true;
 }
 
-void ProcessReader::StartTime(timeval* start_time) const {
+void ProcessReaderMac::StartTime(timeval* start_time) const {
   bool rv = process_info_.StartTime(start_time);
   DCHECK(rv);
 }
 
-bool ProcessReader::CPUTimes(timeval* user_time, timeval* system_time) const {
+bool ProcessReaderMac::CPUTimes(timeval* user_time,
+                                timeval* system_time) const {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   // Calculate user and system time the same way the kernel does for
@@ -177,7 +174,7 @@
   return true;
 }
 
-const std::vector<ProcessReader::Thread>& ProcessReader::Threads() {
+const std::vector<ProcessReaderMac::Thread>& ProcessReaderMac::Threads() {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   if (!initialized_threads_) {
@@ -187,7 +184,7 @@
   return threads_;
 }
 
-const std::vector<ProcessReader::Module>& ProcessReader::Modules() {
+const std::vector<ProcessReaderMac::Module>& ProcessReaderMac::Modules() {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
   if (!initialized_modules_) {
@@ -197,7 +194,7 @@
   return modules_;
 }
 
-mach_vm_address_t ProcessReader::DyldAllImageInfo(
+mach_vm_address_t ProcessReaderMac::DyldAllImageInfo(
     mach_vm_size_t* all_image_info_size) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 
@@ -210,9 +207,9 @@
     return 0;
   }
 
-  // TODO(mark): Deal with statically linked executables which don’t use dyld.
-  // This may look for the module that matches the executable path in the same
-  // data set that vmmap uses.
+// TODO(mark): Deal with statically linked executables which don’t use dyld.
+// This may look for the module that matches the executable path in the same
+// data set that vmmap uses.
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
   // The task_dyld_info_data_t struct grew in 10.7, adding the format field.
@@ -237,7 +234,7 @@
   return dyld_info.all_image_info_addr;
 }
 
-void ProcessReader::InitializeThreads() {
+void ProcessReaderMac::InitializeThreads() {
   DCHECK(!initialized_threads_);
   DCHECK(threads_.empty());
 
@@ -378,7 +375,7 @@
   threads_need_owners.Disarm();
 }
 
-void ProcessReader::InitializeModules() {
+void ProcessReaderMac::InitializeModules() {
   DCHECK(!initialized_modules_);
   DCHECK(modules_.empty());
 
@@ -465,8 +462,8 @@
         image_info.imageLoadAddress == all_image_infos.dyldImageLoadAddress) {
       found_dyld = true;
       LOG(WARNING) << base::StringPrintf(
-            "found dylinker (%s) in dyld_all_image_infos::infoArray",
-            module.name.c_str());
+          "found dylinker (%s) in dyld_all_image_infos::infoArray",
+          module.name.c_str());
 
       LOG_IF(WARNING, file_type != MH_DYLINKER)
           << base::StringPrintf("dylinker (%s) has unexpected Mach-O type %d",
@@ -563,7 +560,7 @@
   }
 }
 
-mach_vm_address_t ProcessReader::CalculateStackRegion(
+mach_vm_address_t ProcessReaderMac::CalculateStackRegion(
     mach_vm_address_t stack_pointer,
     mach_vm_size_t* stack_region_size) {
   INITIALIZATION_STATE_DCHECK_VALID(initialized_);
@@ -675,10 +672,10 @@
   return region_base;
 }
 
-void ProcessReader::LocateRedZone(mach_vm_address_t* const start_address,
-                                  mach_vm_address_t* const region_base,
-                                  mach_vm_address_t* const region_size,
-                                  const unsigned int user_tag) {
+void ProcessReaderMac::LocateRedZone(mach_vm_address_t* const start_address,
+                                     mach_vm_address_t* const region_base,
+                                     mach_vm_address_t* const region_size,
+                                     const unsigned int user_tag) {
 #if defined(ARCH_CPU_X86_FAMILY)
   if (Is64Bit()) {
     // x86_64 has a red zone. See AMD64 ABI 0.99.8,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h
similarity index 96%
rename from third_party/crashpad/crashpad/snapshot/mac/process_reader.h
rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h
index ecca2a5..91836db 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_
-#define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_
+#ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_
+#define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_
 
 #include <mach/mach.h>
 #include <stdint.h>
@@ -37,7 +37,7 @@
 
 //! \brief Accesses information about another process, identified by a Mach
 //!     task.
-class ProcessReader {
+class ProcessReaderMac {
  public:
   //! \brief Contains information about a thread that belongs to a task
   //!     (process).
@@ -83,7 +83,7 @@
     //! \brief An image reader for the module.
     //!
     //! The lifetime of this MachOImageReader is scoped to the lifetime of the
-    //! ProcessReader that created it.
+    //! ProcessReaderMac that created it.
     //!
     //! This field may be `nullptr` if a reader could not be created for the
     //! module.
@@ -97,8 +97,8 @@
     time_t timestamp;
   };
 
-  ProcessReader();
-  ~ProcessReader();
+  ProcessReaderMac();
+  ~ProcessReaderMac();
 
   //! \brief Initializes this object. This method must be called before any
   //!     other.
@@ -244,9 +244,9 @@
   bool initialized_threads_;
   bool initialized_modules_;
 
-  DISALLOW_COPY_AND_ASSIGN(ProcessReader);
+  DISALLOW_COPY_AND_ASSIGN(ProcessReaderMac);
 };
 
 }  // namespace crashpad
 
-#endif  // CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_
+#endif  // CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
similarity index 88%
rename from third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc
rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
index c9f39e715..faec147 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 
 #include <AvailabilityMacros.h>
+#include <OpenCL/opencl.h>
 #include <mach-o/dyld.h>
 #include <mach-o/dyld_images.h>
 #include <mach/mach.h>
-#include <OpenCL/opencl.h>
 #include <string.h>
 #include <sys/stat.h>
 
@@ -48,8 +48,8 @@
 
 constexpr char kDyldPath[] = "/usr/lib/dyld";
 
-TEST(ProcessReader, SelfBasic) {
-  ProcessReader process_reader;
+TEST(ProcessReaderMac, SelfBasic) {
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
 #if !defined(ARCH_CPU_64_BITS)
@@ -80,7 +80,7 @@
 
  private:
   void MachMultiprocessParent() override {
-    ProcessReader process_reader;
+    ProcessReaderMac process_reader;
     ASSERT_TRUE(process_reader.Initialize(ChildTask()));
 
 #if !defined(ARCH_CPU_64_BITS)
@@ -116,7 +116,7 @@
   DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild);
 };
 
-TEST(ProcessReader, ChildBasic) {
+TEST(ProcessReaderMac, ChildBasic) {
   ProcessReaderChild process_reader_child;
   process_reader_child.Run();
 }
@@ -131,11 +131,12 @@
   return thread_id;
 }
 
-TEST(ProcessReader, SelfOneThread) {
-  ProcessReader process_reader;
+TEST(ProcessReaderMac, SelfOneThread) {
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
-  const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
+  const std::vector<ProcessReaderMac::Thread>& threads =
+      process_reader.Threads();
 
   // If other tests ran in this process previously, threads may have been
   // created and may still be running. This check must look for at least one
@@ -157,8 +158,7 @@
     int suspend_count;
   };
 
-  TestThreadPool() : thread_infos_() {
-  }
+  TestThreadPool() : thread_infos_() {}
 
   // Resumes suspended threads, signals each thread’s exit semaphore asking it
   // to exit, and joins each thread, blocking until they have all exited.
@@ -192,10 +192,8 @@
       thread_infos_.push_back(std::make_unique<ThreadInfo>());
       ThreadInfo* thread_info = thread_infos_.back().get();
 
-      int rv = pthread_create(&thread_info->pthread,
-                              nullptr,
-                              ThreadMain,
-                              thread_info);
+      int rv = pthread_create(
+          &thread_info->pthread, nullptr, ThreadMain, thread_info);
       ASSERT_EQ(rv, 0);
     }
 
@@ -210,8 +208,7 @@
          ++thread_index) {
       thread_t thread_port =
           pthread_mach_thread_np(thread_infos_[thread_index]->pthread);
-      for (size_t suspend_count = 0;
-           suspend_count < thread_index;
+      for (size_t suspend_count = 0; suspend_count < thread_index;
            ++suspend_count) {
         kern_return_t kr = thread_suspend(thread_port);
         EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_suspend");
@@ -222,8 +219,7 @@
     }
   }
 
-  uint64_t GetThreadInfo(size_t thread_index,
-                         ThreadExpectation* expectation) {
+  uint64_t GetThreadInfo(size_t thread_index, ThreadExpectation* expectation) {
     CHECK_LT(thread_index, thread_infos_.size());
 
     const auto& thread_info = thread_infos_[thread_index];
@@ -240,8 +236,7 @@
           stack_address(0),
           ready_semaphore(0),
           exit_semaphore(0),
-          suspend_count(0) {
-    }
+          suspend_count(0) {}
 
     ~ThreadInfo() {}
 
@@ -294,14 +289,14 @@
 
 using ThreadMap = std::map<uint64_t, TestThreadPool::ThreadExpectation>;
 
-// Verifies that all of the threads in |threads|, obtained from ProcessReader,
-// agree with the expectation in |thread_map|. If |tolerate_extra_threads| is
-// true, |threads| is allowed to contain threads that are not listed in
-// |thread_map|. This is useful when testing situations where code outside of
-// the test’s control (such as system libraries) may start threads, or may have
-// started threads prior to a test’s execution.
+// Verifies that all of the threads in |threads|, obtained from
+// ProcessReaderMac, agree with the expectation in |thread_map|. If
+// |tolerate_extra_threads| is true, |threads| is allowed to contain threads
+// that are not listed in |thread_map|. This is useful when testing situations
+// where code outside of the test’s control (such as system libraries) may start
+// threads, or may have started threads prior to a test’s execution.
 void ExpectSeveralThreads(ThreadMap* thread_map,
-                          const std::vector<ProcessReader::Thread>& threads,
+                          const std::vector<ProcessReaderMac::Thread>& threads,
                           const bool tolerate_extra_threads) {
   if (tolerate_extra_threads) {
     ASSERT_GE(threads.size(), thread_map->size());
@@ -310,7 +305,7 @@
   }
 
   for (size_t thread_index = 0; thread_index < threads.size(); ++thread_index) {
-    const ProcessReader::Thread& thread = threads[thread_index];
+    const ProcessReaderMac::Thread& thread = threads[thread_index];
     mach_vm_address_t thread_stack_region_end =
         thread.stack_region_address + thread.stack_region_size;
 
@@ -336,26 +331,26 @@
     // with any other thread’s. Each thread should have a unique value for its
     // ID and port, and each should have its own stack that doesn’t touch any
     // other thread’s stack.
-    for (size_t other_thread_index = 0;
-         other_thread_index < threads.size();
+    for (size_t other_thread_index = 0; other_thread_index < threads.size();
          ++other_thread_index) {
       if (other_thread_index == thread_index) {
         continue;
       }
 
-      const ProcessReader::Thread& other_thread = threads[other_thread_index];
+      const ProcessReaderMac::Thread& other_thread =
+          threads[other_thread_index];
 
       EXPECT_NE(other_thread.id, thread.id);
       EXPECT_NE(other_thread.port, thread.port);
 
       mach_vm_address_t other_thread_stack_region_end =
           other_thread.stack_region_address + other_thread.stack_region_size;
-      EXPECT_FALSE(
-          thread.stack_region_address >= other_thread.stack_region_address &&
-          thread.stack_region_address < other_thread_stack_region_end);
-      EXPECT_FALSE(
-          thread_stack_region_end > other_thread.stack_region_address &&
-          thread_stack_region_end <= other_thread_stack_region_end);
+      EXPECT_FALSE(thread.stack_region_address >=
+                       other_thread.stack_region_address &&
+                   thread.stack_region_address < other_thread_stack_region_end);
+      EXPECT_FALSE(thread_stack_region_end >
+                       other_thread.stack_region_address &&
+                   thread_stack_region_end <= other_thread_stack_region_end);
     }
   }
 
@@ -363,12 +358,12 @@
   EXPECT_TRUE(thread_map->empty());
 }
 
-TEST(ProcessReader, SelfSeveralThreads) {
-  // Set up the ProcessReader here, before any other threads are running. This
-  // tests that the threads it returns are lazily initialized as a snapshot of
-  // the threads at the time of the first call to Threads(), and not at the
+TEST(ProcessReaderMac, SelfSeveralThreads) {
+  // Set up the ProcessReaderMac here, before any other threads are running.
+  // This tests that the threads it returns are lazily initialized as a snapshot
+  // of the threads at the time of the first call to Threads(), and not at the
   // time the ProcessReader was created or initialized.
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
   TestThreadPool thread_pool;
@@ -392,7 +387,8 @@
     thread_map[thread_id] = expectation;
   }
 
-  const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
+  const std::vector<ProcessReaderMac::Thread>& threads =
+      process_reader.Threads();
 
   // Other tests that have run previously may have resulted in the creation of
   // threads that still exist, so pass true for |tolerate_extra_threads|.
@@ -403,7 +399,7 @@
   // shows up once.
   thread_t thread_self = MachThreadSelf();
   bool found_thread_self = false;
-  for (const ProcessReader::Thread& thread : threads) {
+  for (const ProcessReaderMac::Thread& thread : threads) {
     if (thread.port == thread_self) {
       EXPECT_FALSE(found_thread_self);
       found_thread_self = true;
@@ -416,15 +412,13 @@
 class ProcessReaderThreadedChild final : public MachMultiprocess {
  public:
   explicit ProcessReaderThreadedChild(size_t thread_count)
-      : MachMultiprocess(),
-        thread_count_(thread_count) {
-  }
+      : MachMultiprocess(), thread_count_(thread_count) {}
 
   ~ProcessReaderThreadedChild() {}
 
  private:
   void MachMultiprocessParent() override {
-    ProcessReader process_reader;
+    ProcessReaderMac process_reader;
     ASSERT_TRUE(process_reader.Initialize(ChildTask()));
 
     FileHandle read_handle = ReadPipeHandle();
@@ -433,8 +427,7 @@
     // addresses that should lie somewhere within each thread’s stack as values.
     // These IDs and addresses all come from the child process via the pipe.
     ThreadMap thread_map;
-    for (size_t thread_index = 0;
-         thread_index < thread_count_ + 1;
+    for (size_t thread_index = 0; thread_index < thread_count_ + 1;
          ++thread_index) {
       uint64_t thread_id;
       CheckedReadFileExactly(read_handle, &thread_id, sizeof(thread_id));
@@ -453,7 +446,8 @@
       thread_map[thread_id] = expectation;
     }
 
-    const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
+    const std::vector<ProcessReaderMac::Thread>& threads =
+        process_reader.Threads();
 
     // The child shouldn’t have any threads other than its main thread and the
     // ones it created in its pool, so pass false for |tolerate_extra_threads|.
@@ -484,8 +478,7 @@
                      sizeof(expectation.suspend_count));
 
     // Write an entry for everything in the thread pool.
-    for (size_t thread_index = 0;
-         thread_index < thread_count_;
+    for (size_t thread_index = 0; thread_index < thread_count_;
          ++thread_index) {
       uint64_t thread_id =
           thread_pool.GetThreadInfo(thread_index, &expectation);
@@ -509,14 +502,14 @@
   DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild);
 };
 
-TEST(ProcessReader, ChildOneThread) {
+TEST(ProcessReaderMac, ChildOneThread) {
   // The main thread plus zero child threads equals one thread.
   constexpr size_t kChildThreads = 0;
   ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads);
   process_reader_threaded_child.Run();
 }
 
-TEST(ProcessReader, ChildSeveralThreads) {
+TEST(ProcessReaderMac, ChildSeveralThreads) {
   constexpr size_t kChildThreads = 64;
   ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads);
   process_reader_threaded_child.Run();
@@ -537,10 +530,7 @@
 class ScopedOpenCLNoOpKernel {
  public:
   ScopedOpenCLNoOpKernel()
-      : context_(nullptr),
-        program_(nullptr),
-        kernel_(nullptr) {
-  }
+      : context_(nullptr), program_(nullptr), kernel_(nullptr) {}
 
   ~ScopedOpenCLNoOpKernel() {
     if (kernel_) {
@@ -566,10 +556,10 @@
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 && \
     MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
-    // cl_device_id is really available in OpenCL.framework back to 10.5, but in
-    // the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>,
-    // which has its own cl_device_id that was introduced in 10.10. That
-    // triggers erroneous availability warnings.
+// cl_device_id is really available in OpenCL.framework back to 10.5, but in
+// the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>,
+// which has its own cl_device_id that was introduced in 10.10. That
+// triggers erroneous availability warnings.
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wunguarded-availability"
 #define DISABLED_WUNGUARDED_AVAILABILITY
@@ -642,15 +632,16 @@
 #endif
 }
 
-TEST(ProcessReader, SelfModules) {
+TEST(ProcessReaderMac, SelfModules) {
   ScopedOpenCLNoOpKernel ensure_cl_kernels;
   ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());
 
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
   uint32_t dyld_image_count = _dyld_image_count();
-  const std::vector<ProcessReader::Module>& modules = process_reader.Modules();
+  const std::vector<ProcessReaderMac::Module>& modules =
+      process_reader.Modules();
 
   // There needs to be at least an entry for the main executable, for a dylib,
   // and for dyld.
@@ -718,10 +709,10 @@
 
  private:
   void MachMultiprocessParent() override {
-    ProcessReader process_reader;
+    ProcessReaderMac process_reader;
     ASSERT_TRUE(process_reader.Initialize(ChildTask()));
 
-    const std::vector<ProcessReader::Module>& modules =
+    const std::vector<ProcessReaderMac::Module>& modules =
         process_reader.Modules();
 
     // There needs to be at least an entry for the main executable, for a dylib,
@@ -829,7 +820,7 @@
   DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild);
 };
 
-TEST(ProcessReader, ChildModules) {
+TEST(ProcessReaderMac, ChildModules) {
   ScopedOpenCLNoOpKernel ensure_cl_kernels;
   ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc
index eaaf3dca..cf5233a 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc
@@ -218,9 +218,9 @@
 }
 
 void ProcessSnapshotMac::InitializeThreads() {
-  const std::vector<ProcessReader::Thread>& process_reader_threads =
+  const std::vector<ProcessReaderMac::Thread>& process_reader_threads =
       process_reader_.Threads();
-  for (const ProcessReader::Thread& process_reader_thread :
+  for (const ProcessReaderMac::Thread& process_reader_thread :
        process_reader_threads) {
     auto thread = std::make_unique<internal::ThreadSnapshotMac>();
     if (thread->Initialize(&process_reader_, process_reader_thread)) {
@@ -230,9 +230,9 @@
 }
 
 void ProcessSnapshotMac::InitializeModules() {
-  const std::vector<ProcessReader::Module>& process_reader_modules =
+  const std::vector<ProcessReaderMac::Module>& process_reader_modules =
       process_reader_.Modules();
-  for (const ProcessReader::Module& process_reader_module :
+  for (const ProcessReaderMac::Module& process_reader_module :
        process_reader_modules) {
     auto module = std::make_unique<internal::ModuleSnapshotMac>();
     if (module->Initialize(&process_reader_, process_reader_module)) {
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h
index e7195d941..06bac74 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h
@@ -30,7 +30,7 @@
 #include "snapshot/exception_snapshot.h"
 #include "snapshot/mac/exception_snapshot_mac.h"
 #include "snapshot/mac/module_snapshot_mac.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/mac/system_snapshot_mac.h"
 #include "snapshot/mac/thread_snapshot_mac.h"
 #include "snapshot/memory_map_region_snapshot.h"
@@ -143,7 +143,7 @@
   std::vector<std::unique_ptr<internal::ThreadSnapshotMac>> threads_;
   std::vector<std::unique_ptr<internal::ModuleSnapshotMac>> modules_;
   std::unique_ptr<internal::ExceptionSnapshotMac> exception_;
-  ProcessReader process_reader_;
+  ProcessReaderMac process_reader_;
   UUID report_id_;
   UUID client_id_;
   std::map<std::string, std::string> annotations_simple_map_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
index 35d81db..65c39ea 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
@@ -94,7 +94,7 @@
   namespace process_types {                                               \
                                                                           \
   /* static */                                                            \
-  size_t struct_name::ExpectedSize(ProcessReader* process_reader) {       \
+  size_t struct_name::ExpectedSize(ProcessReaderMac* process_reader) {    \
     if (!process_reader->Is64Bit()) {                                     \
       return internal::struct_name<internal::Traits32>::Size();           \
     } else {                                                              \
@@ -103,7 +103,7 @@
   }                                                                       \
                                                                           \
   /* static */                                                            \
-  bool struct_name::ReadInto(ProcessReader* process_reader,               \
+  bool struct_name::ReadInto(ProcessReaderMac* process_reader,            \
                              mach_vm_address_t address,                   \
                              struct_name* generic) {                      \
     if (!process_reader->Is64Bit()) {                                     \
@@ -117,7 +117,7 @@
                                                                           \
   /* static */                                                            \
   template <typename T>                                                   \
-  bool struct_name::ReadIntoInternal(ProcessReader* process_reader,       \
+  bool struct_name::ReadIntoInternal(ProcessReaderMac* process_reader,    \
                                      mach_vm_address_t address,           \
                                      struct_name* generic) {              \
     T specific;                                                           \
@@ -166,22 +166,22 @@
 // implementations in snapshot/mac/process_types/custom.cc.
 #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1
 
-#define PROCESS_TYPE_STRUCT_BEGIN(struct_name)                        \
-  namespace crashpad {                                                \
-  namespace process_types {                                           \
-  namespace internal {                                                \
-                                                                      \
-  /* static */                                                        \
-  template <typename Traits>                                          \
-  bool struct_name<Traits>::ReadInto(ProcessReader* process_reader,   \
-                                     mach_vm_address_t address,       \
-                                     struct_name<Traits>* specific) { \
-    return process_reader->Memory()->Read(                            \
-        address, sizeof(*specific), specific);                        \
-  }                                                                   \
-  }  /* namespace internal */                                         \
-  }  /* namespace process_types */                                    \
-  }  /* namespace crashpad */
+#define PROCESS_TYPE_STRUCT_BEGIN(struct_name)                         \
+  namespace crashpad {                                                 \
+  namespace process_types {                                            \
+  namespace internal {                                                 \
+                                                                       \
+  /* static */                                                         \
+  template <typename Traits>                                           \
+  bool struct_name<Traits>::ReadInto(ProcessReaderMac* process_reader, \
+                                     mach_vm_address_t address,        \
+                                     struct_name<Traits>* specific) {  \
+    return process_reader->Memory()->Read(                             \
+        address, sizeof(*specific), specific);                         \
+  }                                                                    \
+  } /* namespace internal */                                           \
+  } /* namespace process_types */                                      \
+  } /* namespace crashpad */
 
 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)
 
@@ -214,7 +214,7 @@
                                                                                \
   /* static */                                                                 \
   template <typename Traits>                                                   \
-  bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader,       \
+  bool struct_name<Traits>::ReadArrayInto(ProcessReaderMac* process_reader,    \
                                           mach_vm_address_t address,           \
                                           size_t count,                        \
                                           struct_name<Traits>* specific) {     \
@@ -225,7 +225,7 @@
   } /* namespace internal */                                                   \
                                                                                \
   /* static */                                                                 \
-  bool struct_name::ReadArrayInto(ProcessReader* process_reader,               \
+  bool struct_name::ReadArrayInto(ProcessReaderMac* process_reader,            \
                                   mach_vm_address_t address,                   \
                                   size_t count,                                \
                                   struct_name* generic) {                      \
@@ -241,7 +241,7 @@
                                                                                \
   /* static */                                                                 \
   template <typename T>                                                        \
-  bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader,       \
+  bool struct_name::ReadArrayIntoInternal(ProcessReaderMac* process_reader,    \
                                           mach_vm_address_t address,           \
                                           size_t count,                        \
                                           struct_name* generic) {              \
@@ -293,7 +293,7 @@
                                                                   \
   /* static */                                                    \
   size_t struct_name::ExpectedSizeForVersion(                     \
-      ProcessReader* process_reader,                              \
+      ProcessReaderMac* process_reader,                           \
       decltype(struct_name::version_field) version) {             \
     if (!process_reader->Is64Bit()) {                             \
       return internal::struct_name<                               \
@@ -304,8 +304,8 @@
     }                                                             \
   }                                                               \
                                                                   \
-  }  /* namespace process_types */                                \
-  }  /* namespace crashpad */
+  } /* namespace process_types */                                 \
+  } /* namespace crashpad */
 
 #define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field)
 
@@ -354,7 +354,7 @@
   } /* namespace internal */                                           \
                                                                        \
   /* static */                                                         \
-  size_t struct_name::MinimumSize(ProcessReader* process_reader) {     \
+  size_t struct_name::MinimumSize(ProcessReaderMac* process_reader) {  \
     if (!process_reader->Is64Bit()) {                                  \
       return internal::struct_name<internal::Traits32>::MinimumSize(); \
     } else {                                                           \
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.h b/third_party/crashpad/crashpad/snapshot/mac/process_types.h
index 350b406..6a5f9c1 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_types.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.h
@@ -21,7 +21,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 
 namespace crashpad {
 namespace process_types {
@@ -80,14 +80,14 @@
                                                                                \
     /* Initializes an object with data read from |process_reader| at           \
      * |address|, properly genericized. */                                     \
-    bool Read(ProcessReader* process_reader, mach_vm_address_t address) {      \
+    bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) {   \
       return ReadInto(process_reader, address, this);                          \
     }                                                                          \
                                                                                \
     /* Reads |count| objects from |process_reader| beginning at |address|, and \
      * genericizes the objects. The caller must provide storage for |count|    \
      * objects in |generic|. */                                                \
-    static bool ReadArrayInto(ProcessReader* process_reader,                   \
+    static bool ReadArrayInto(ProcessReaderMac* process_reader,                \
                               mach_vm_address_t address,                       \
                               size_t count,                                    \
                               struct_name* generic);                           \
@@ -102,47 +102,48 @@
      * on the process’ bitness. This can be used prior to reading any data     \
      * from a process. For versioned and sized structures,                     \
      * ExpectedSizeForVersion() and MinimumSize() may also be useful. */       \
-    static size_t ExpectedSize(ProcessReader* process_reader);
+    static size_t ExpectedSize(ProcessReaderMac* process_reader);
 
 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)              \
     member_type member_name __VA_ARGS__;
 
-#define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field)              \
-    /* Similar to ExpectedSize(), but computes the expected size of a          \
-     * structure based on the process’ bitness and a custom value, such as a   \
-     * structure version number. This can be used prior to reading any data    \
-     * from a process. */                                                      \
-    static size_t ExpectedSizeForVersion(                                      \
-        ProcessReader* process_reader,                                         \
-        decltype(struct_name::version_field) version);
+#define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field)            \
+  /* Similar to ExpectedSize(), but computes the expected size of a          \
+   * structure based on the process’ bitness and a custom value, such as a   \
+   * structure version number. This can be used prior to reading any data    \
+   * from a process. */                                                      \
+  static size_t ExpectedSizeForVersion(                                      \
+      ProcessReaderMac* process_reader,                                      \
+      decltype(struct_name::version_field) version);
 
-#define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field)                     \
-  /* Similar to ExpectedSize(), but computes the minimum size of a             \
-   * structure based on the process’ bitness, typically including enough of    \
-   * a structure to contain its size field. This can be used prior to          \
-   * reading any data from a process. */                                       \
-  static size_t MinimumSize(ProcessReader* process_reader);
+#define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field)                    \
+  /* Similar to ExpectedSize(), but computes the minimum size of a            \
+   * structure based on the process’ bitness, typically including enough of   \
+   * a structure to contain its size field. This can be used prior to         \
+   * reading any data from a process. */                                      \
+  static size_t MinimumSize(ProcessReaderMac* process_reader);
 
-#define PROCESS_TYPE_STRUCT_END(struct_name)                                   \
-   private:                                                                    \
-    /* The static form of Read(). Populates the struct at |generic|. */        \
-    static bool ReadInto(ProcessReader* process_reader,                        \
-                         mach_vm_address_t address,                            \
-                         struct_name* generic);                                \
-                                                                               \
-    template <typename T>                                                      \
-    static bool ReadIntoInternal(ProcessReader* process_reader,                \
-                                 mach_vm_address_t address,                    \
-                                 struct_name* generic);                        \
-    template <typename T>                                                      \
-    static bool ReadArrayIntoInternal(ProcessReader* process_reader,           \
-                                      mach_vm_address_t address,               \
-                                      size_t count,                            \
-                                      struct_name* generic);                   \
-    size_t size_;                                                              \
-  };                                                                           \
-  }  /* namespace process_types */                                             \
-  }  /* namespace crashpad */
+#define PROCESS_TYPE_STRUCT_END(struct_name)                          \
+ private:                                                             \
+  /* The static form of Read(). Populates the struct at |generic|. */ \
+  static bool ReadInto(ProcessReaderMac* process_reader,              \
+                       mach_vm_address_t address,                     \
+                       struct_name* generic);                         \
+                                                                      \
+  template <typename T>                                               \
+  static bool ReadIntoInternal(ProcessReaderMac* process_reader,      \
+                               mach_vm_address_t address,             \
+                               struct_name* generic);                 \
+  template <typename T>                                               \
+  static bool ReadArrayIntoInternal(ProcessReaderMac* process_reader, \
+                                    mach_vm_address_t address,        \
+                                    size_t count,                     \
+                                    struct_name* generic);            \
+  size_t size_;                                                       \
+  }                                                                   \
+  ;                                                                   \
+  } /* namespace process_types */                                     \
+  } /* namespace crashpad */
 
 #include "snapshot/mac/process_types/all.proctype"
 
@@ -163,37 +164,37 @@
 // remote process into the generic form.
 #define PROCESS_TYPE_STRUCT_DECLARE_INTERNAL 1
 
-#define PROCESS_TYPE_STRUCT_BEGIN(struct_name)                                 \
-  namespace crashpad {                                                         \
-  namespace process_types {                                                    \
-  namespace internal {                                                         \
-  template <typename Traits>                                                   \
-  struct struct_name {                                                         \
-   public:                                                                     \
-    using Long = typename Traits::Long;                                        \
-    using ULong = typename Traits::ULong;                                      \
-    using Pointer = typename Traits::Pointer;                                  \
-    using IntPtr = typename Traits::IntPtr;                                    \
-    using UIntPtr = typename Traits::UIntPtr;                                  \
-    using Reserved32_32Only = typename Traits::Reserved32_32Only;              \
-    using Reserved32_64Only = typename Traits::Reserved32_64Only;              \
-    using Reserved64_64Only = typename Traits::Reserved64_64Only;              \
-    using Nothing = typename Traits::Nothing;                                  \
-                                                                               \
-    /* Read(), ReadArrayInto(), and Size() are as in the generic user-visible  \
-     * struct above. */                                                        \
-    bool Read(ProcessReader* process_reader, mach_vm_address_t address) {      \
-      return ReadInto(process_reader, address, this);                          \
-    }                                                                          \
-    static bool ReadArrayInto(ProcessReader* process_reader,                   \
-                              mach_vm_address_t address,                       \
-                              size_t count,                                    \
-                              struct_name<Traits>* specific);                  \
-    static size_t Size() { return sizeof(struct_name<Traits>); }               \
-                                                                               \
-    /* Translates a struct from the representation used in the remote process  \
-     * into the generic form. */                                               \
-    void GenericizeInto(process_types::struct_name* generic,                   \
+#define PROCESS_TYPE_STRUCT_BEGIN(struct_name)                                \
+  namespace crashpad {                                                        \
+  namespace process_types {                                                   \
+  namespace internal {                                                        \
+  template <typename Traits>                                                  \
+  struct struct_name {                                                        \
+   public:                                                                    \
+    using Long = typename Traits::Long;                                       \
+    using ULong = typename Traits::ULong;                                     \
+    using Pointer = typename Traits::Pointer;                                 \
+    using IntPtr = typename Traits::IntPtr;                                   \
+    using UIntPtr = typename Traits::UIntPtr;                                 \
+    using Reserved32_32Only = typename Traits::Reserved32_32Only;             \
+    using Reserved32_64Only = typename Traits::Reserved32_64Only;             \
+    using Reserved64_64Only = typename Traits::Reserved64_64Only;             \
+    using Nothing = typename Traits::Nothing;                                 \
+                                                                              \
+    /* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \
+     * struct above. */                                                       \
+    bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) {  \
+      return ReadInto(process_reader, address, this);                         \
+    }                                                                         \
+    static bool ReadArrayInto(ProcessReaderMac* process_reader,               \
+                              mach_vm_address_t address,                      \
+                              size_t count,                                   \
+                              struct_name<Traits>* specific);                 \
+    static size_t Size() { return sizeof(struct_name<Traits>); }              \
+                                                                              \
+    /* Translates a struct from the representation used in the remote process \
+     * into the generic form. */                                              \
+    void GenericizeInto(process_types::struct_name* generic,                  \
                         size_t* specific_size);
 
 #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...)              \
@@ -209,16 +210,17 @@
   /* MinimumSize() is as in the generic user-visible struct above. */          \
   static size_t MinimumSize();
 
-#define PROCESS_TYPE_STRUCT_END(struct_name)                                   \
-   private:                                                                    \
-    /* ReadInto() is as in the generic user-visible struct above. */           \
-    static bool ReadInto(ProcessReader* process_reader,                        \
-                         mach_vm_address_t address,                            \
-                         struct_name<Traits>* specific);                       \
-  };                                                                           \
-  }  /* namespace internal */                                                  \
-  }  /* namespace process_types */                                             \
-  }  /* namespace crashpad */
+#define PROCESS_TYPE_STRUCT_END(struct_name)                       \
+ private:                                                          \
+  /* ReadInto() is as in the generic user-visible struct above. */ \
+  static bool ReadInto(ProcessReaderMac* process_reader,           \
+                       mach_vm_address_t address,                  \
+                       struct_name<Traits>* specific);             \
+  }                                                                \
+  ;                                                                \
+  } /* namespace internal */                                       \
+  } /* namespace process_types */                                  \
+  } /* namespace crashpad */
 
 #include "snapshot/mac/process_types/all.proctype"
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
index b9cb0e79..7c7b172 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -75,7 +75,7 @@
 }
 
 template <typename T>
-bool ReadIntoVersioned(ProcessReader* process_reader,
+bool ReadIntoVersioned(ProcessReaderMac* process_reader,
                        mach_vm_address_t address,
                        T* specific) {
   mach_vm_address_t field_address;
@@ -95,7 +95,7 @@
 }
 
 template <typename T>
-bool ReadIntoSized(ProcessReader* process_reader,
+bool ReadIntoSized(ProcessReaderMac* process_reader,
                    mach_vm_address_t address,
                    T* specific) {
   mach_vm_address_t field_address;
@@ -156,7 +156,7 @@
 // static
 template <typename Traits>
 bool dyld_all_image_infos<Traits>::ReadInto(
-    ProcessReader* process_reader,
+    ProcessReaderMac* process_reader,
     mach_vm_address_t address,
     dyld_all_image_infos<Traits>* specific) {
   return ReadIntoVersioned(process_reader, address, specific);
@@ -178,7 +178,7 @@
 // static
 template <typename Traits>
 bool crashreporter_annotations_t<Traits>::ReadInto(
-    ProcessReader* process_reader,
+    ProcessReaderMac* process_reader,
     mach_vm_address_t address,
     crashreporter_annotations_t<Traits>* specific) {
   return ReadIntoVersioned(process_reader, address, specific);
@@ -186,30 +186,30 @@
 
 // static
 template <typename Traits>
-bool CrashpadInfo<Traits>::ReadInto(ProcessReader* process_reader,
+bool CrashpadInfo<Traits>::ReadInto(ProcessReaderMac* process_reader,
                                     mach_vm_address_t address,
                                     CrashpadInfo<Traits>* specific) {
   return ReadIntoSized(process_reader, address, specific);
 }
 
 // Explicit template instantiation of the above.
-#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits)                                    \
-  template size_t                                                              \
-  dyld_all_image_infos<Traits##lp_bits>::ExpectedSizeForVersion(               \
-      decltype(dyld_all_image_infos<Traits##lp_bits>::version));               \
-  template bool dyld_all_image_infos<Traits##lp_bits>::ReadInto(               \
-      ProcessReader*,                                                          \
-      mach_vm_address_t,                                                       \
-      dyld_all_image_infos<Traits##lp_bits>*);                                 \
-  template size_t                                                              \
-  crashreporter_annotations_t<Traits##lp_bits>::ExpectedSizeForVersion(        \
-      decltype(crashreporter_annotations_t<Traits##lp_bits>::version));        \
-  template bool crashreporter_annotations_t<Traits##lp_bits>::ReadInto(        \
-      ProcessReader*,                                                          \
-      mach_vm_address_t,                                                       \
-      crashreporter_annotations_t<Traits##lp_bits>*);                          \
-  template bool CrashpadInfo<Traits##lp_bits>::ReadInto(                       \
-      ProcessReader*, mach_vm_address_t, CrashpadInfo<Traits##lp_bits>*);
+#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits)                             \
+  template size_t                                                       \
+  dyld_all_image_infos<Traits##lp_bits>::ExpectedSizeForVersion(        \
+      decltype(dyld_all_image_infos<Traits##lp_bits>::version));        \
+  template bool dyld_all_image_infos<Traits##lp_bits>::ReadInto(        \
+      ProcessReaderMac*,                                                \
+      mach_vm_address_t,                                                \
+      dyld_all_image_infos<Traits##lp_bits>*);                          \
+  template size_t                                                       \
+  crashreporter_annotations_t<Traits##lp_bits>::ExpectedSizeForVersion( \
+      decltype(crashreporter_annotations_t<Traits##lp_bits>::version)); \
+  template bool crashreporter_annotations_t<Traits##lp_bits>::ReadInto( \
+      ProcessReaderMac*,                                                \
+      mach_vm_address_t,                                                \
+      crashreporter_annotations_t<Traits##lp_bits>*);                   \
+  template bool CrashpadInfo<Traits##lp_bits>::ReadInto(                \
+      ProcessReaderMac*, mach_vm_address_t, CrashpadInfo<Traits##lp_bits>*);
 
 #include "snapshot/mac/process_types/flavors.h"
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
index 8ab15c8..f116c4d 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -101,7 +101,7 @@
   }
 #endif
 
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc
index 140e7f4..21f254e 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc
@@ -25,7 +25,7 @@
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "snapshot/cpu_context.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/posix/timezone.h"
 #include "util/mac/mac_util.h"
 #include "util/numeric/in_range_cast.h"
@@ -104,7 +104,7 @@
 SystemSnapshotMac::~SystemSnapshotMac() {
 }
 
-void SystemSnapshotMac::Initialize(ProcessReader* process_reader,
+void SystemSnapshotMac::Initialize(ProcessReaderMac* process_reader,
                                    const timeval* snapshot_time) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h
index 2ac2ef90..62b2ae6 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h
@@ -25,7 +25,7 @@
 
 namespace crashpad {
 
-class ProcessReader;
+class ProcessReaderMac;
 
 namespace internal {
 
@@ -40,9 +40,9 @@
   //! \param[in] process_reader A reader for the process being snapshotted.
   //!     \n\n
   //!     It seems odd that a system snapshot implementation would need a
-  //!     ProcessReader, but some of the information reported about the system
-  //!     depends on the process it’s being reported for. For example, the
-  //!     architecture returned by GetCPUArchitecture() should be the
+  //!     ProcessReaderMac, but some of the information reported about the
+  //!     system depends on the process it’s being reported for. For example,
+  //!     the architecture returned by GetCPUArchitecture() should be the
   //!     architecture of the process, which may be different than the native
   //!     architecture of the system: an x86_64 system can run both x86_64 and
   //!     32-bit x86 processes.
@@ -53,7 +53,8 @@
   //!     Otherwise, it would need to base its determination on the current
   //!     time, which may be different than the snapshot time for snapshots
   //!     generated around the daylight saving transition time.
-  void Initialize(ProcessReader* process_reader, const timeval* snapshot_time);
+  void Initialize(ProcessReaderMac* process_reader,
+                  const timeval* snapshot_time);
 
   // SystemSnapshot:
 
@@ -83,7 +84,7 @@
  private:
   std::string os_version_full_;
   std::string os_version_build_;
-  ProcessReader* process_reader_;  // weak
+  ProcessReaderMac* process_reader_;  // weak
   const timeval* snapshot_time_;  // weak
   int os_version_major_;
   int os_version_minor_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc
index 646021b..69048eb 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc
@@ -20,7 +20,7 @@
 
 #include "build/build_config.h"
 #include "gtest/gtest.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "test/errors.h"
 #include "util/mac/mac_util.h"
 
@@ -30,7 +30,7 @@
 
 // SystemSnapshotMac objects would be cumbersome to construct in each test that
 // requires one, because of the repetitive and mechanical work necessary to set
-// up a ProcessReader and timeval, along with the checks to verify that these
+// up a ProcessReaderMac and timeval, along with the checks to verify that these
 // operations succeed. This test fixture class handles the initialization work
 // so that individual tests don’t have to.
 class SystemSnapshotMacTest : public testing::Test {
@@ -55,7 +55,7 @@
   }
 
  private:
-  ProcessReader process_reader_;
+  ProcessReaderMac process_reader_;
   timeval snapshot_time_;
   internal::SystemSnapshotMac system_snapshot_;
 
diff --git a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc
index b042f75..f45fc41 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc
+++ b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc
@@ -16,7 +16,7 @@
 
 #include "base/logging.h"
 #include "snapshot/mac/cpu_context_mac.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 
 namespace crashpad {
 namespace internal {
@@ -38,8 +38,8 @@
 }
 
 bool ThreadSnapshotMac::Initialize(
-    ProcessReader* process_reader,
-    const ProcessReader::Thread& process_reader_thread) {
+    ProcessReaderMac* process_reader,
+    const ProcessReaderMac::Thread& process_reader_thread) {
   INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 
   thread_ = process_reader_thread.port;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h
index 2833443..8f5d722 100644
--- a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h
+++ b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h
@@ -21,14 +21,15 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "snapshot/cpu_context.h"
-#include "snapshot/mac/memory_snapshot_mac.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "snapshot/memory_snapshot.h"
+#include "snapshot/memory_snapshot_generic.h"
 #include "snapshot/thread_snapshot.h"
 #include "util/misc/initialization_state_dcheck.h"
 
 namespace crashpad {
 
-class ProcessReader;
+class ProcessReaderMac;
 
 namespace internal {
 
@@ -41,15 +42,15 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the task containing the
+  //! \param[in] process_reader A ProcessReaderMac for the task containing the
   //!     thread.
-  //! \param[in] process_reader_thread The thread within the ProcessReader for
-  //!     which the snapshot should be created.
+  //! \param[in] process_reader_thread The thread within the ProcessReaderMac
+  //!     for which the snapshot should be created.
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
-  bool Initialize(ProcessReader* process_reader,
-                  const ProcessReader::Thread& process_reader_thread);
+  bool Initialize(ProcessReaderMac* process_reader,
+                  const ProcessReaderMac::Thread& process_reader_thread);
 
   // ThreadSnapshot:
 
@@ -69,7 +70,7 @@
   } context_union_;
 #endif
   CPUContext context_;
-  MemorySnapshotMac stack_;
+  MemorySnapshotGeneric<ProcessReaderMac> stack_;
   uint64_t thread_id_;
   uint64_t thread_specific_data_address_;
   thread_t thread_;
diff --git a/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h b/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h
new file mode 100644
index 0000000..402e913
--- /dev/null
+++ b/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h
@@ -0,0 +1,107 @@
+// Copyright 2014 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_SNAPSHOT_MEMORY_SNAPSHOT_GENERIC_H_
+#define CRASHPAD_SNAPSHOT_MEMORY_SNAPSHOT_GENERIC_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "base/macros.h"
+#include "snapshot/memory_snapshot.h"
+#include "util/misc/address_types.h"
+#include "util/misc/initialization_state_dcheck.h"
+#include "util/process/process_memory.h"
+
+namespace crashpad {
+namespace internal {
+
+//! \brief A MemorySnapshot of a memory region in a process on the running
+//!     system. Used on Mac, Linux, Android, and Fuchsia, templated on the
+//!     platform-specific ProcessReader type.
+template <class ProcessReaderType>
+class MemorySnapshotGeneric final : public MemorySnapshot {
+ public:
+  MemorySnapshotGeneric() = default;
+  ~MemorySnapshotGeneric() = default;
+
+  //! \brief Initializes the object.
+  //!
+  //! Memory is read lazily. No attempt is made to read the memory snapshot data
+  //! until Read() is called, and the memory snapshot data is discared when
+  //! Read() returns.
+  //!
+  //! \param[in] process_reader A reader for the process being snapshotted.
+  //! \param[in] address The base address of the memory region to snapshot, in
+  //!     the snapshot process’ address space.
+  //! \param[in] size The size of the memory region to snapshot.
+  void Initialize(ProcessReaderType* process_reader,
+                  VMAddress address,
+                  VMSize size) {
+    INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
+    process_reader_ = process_reader;
+    address_ = address;
+    size_ = size;
+    INITIALIZATION_STATE_SET_VALID(initialized_);
+  }
+
+  // MemorySnapshot:
+
+  uint64_t Address() const override {
+  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+  return address_;
+  }
+
+  size_t Size() const override {
+    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+    return size_;
+  }
+
+  bool Read(Delegate* delegate) const override {
+    INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+    if (size_ == 0) {
+      return delegate->MemorySnapshotDelegateRead(nullptr, size_);
+    }
+
+    std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]);
+    if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) {
+      return false;
+    }
+    return delegate->MemorySnapshotDelegateRead(buffer.get(), size_);
+  }
+
+  const MemorySnapshot* MergeWithOtherSnapshot(
+      const MemorySnapshot* other) const override {
+    return MergeWithOtherSnapshotImpl(this, other);
+  }
+
+ private:
+  template <class T>
+  friend const MemorySnapshot* MergeWithOtherSnapshotImpl(
+      const T* self,
+      const MemorySnapshot* other);
+
+  ProcessReaderType* process_reader_;  // weak
+  uint64_t address_;
+  uint64_t size_;
+  InitializationStateDcheck initialized_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemorySnapshotGeneric);
+};
+
+}  // namespace internal
+}  // namespace crashpad
+
+#endif  // CRASHPAD_SNAPSHOT_GENERIC_MEMORY_SNAPSHOT_GENERIC_H_
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot.gyp b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
index da19234..b199841 100644
--- a/third_party/crashpad/crashpad/snapshot/snapshot.gyp
+++ b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
@@ -49,6 +49,8 @@
         'elf/elf_image_reader.h',
         'elf/elf_symbol_table_reader.cc',
         'elf/elf_symbol_table_reader.h',
+        'elf/module_snapshot_elf.cc',
+        'elf/module_snapshot_elf.h',
         'exception_snapshot.h',
         'handle_snapshot.cc',
         'handle_snapshot.h',
@@ -58,12 +60,8 @@
         'linux/debug_rendezvous.h',
         'linux/exception_snapshot_linux.cc',
         'linux/exception_snapshot_linux.h',
-        'linux/memory_snapshot_linux.cc',
-        'linux/memory_snapshot_linux.h',
-        'linux/module_snapshot_linux.cc',
-        'linux/module_snapshot_linux.h',
-        'linux/process_reader.cc',
-        'linux/process_reader.h',
+        'linux/process_reader_linux.cc',
+        'linux/process_reader_linux.h',
         'linux/process_snapshot_linux.cc',
         'linux/process_snapshot_linux.h',
         'linux/signal_context.h',
@@ -83,12 +81,10 @@
         'mac/mach_o_image_segment_reader.h',
         'mac/mach_o_image_symbol_table_reader.cc',
         'mac/mach_o_image_symbol_table_reader.h',
-        'mac/memory_snapshot_mac.cc',
-        'mac/memory_snapshot_mac.h',
         'mac/module_snapshot_mac.cc',
         'mac/module_snapshot_mac.h',
-        'mac/process_reader.cc',
-        'mac/process_reader.h',
+        'mac/process_reader_mac.cc',
+        'mac/process_reader_mac.h',
         'mac/process_snapshot_mac.cc',
         'mac/process_snapshot_mac.h',
         'mac/process_types.cc',
@@ -110,6 +106,7 @@
         'mac/thread_snapshot_mac.h',
         'memory_snapshot.cc',
         'memory_snapshot.h',
+        'memory_snapshot_generic.h',
         'minidump/minidump_annotation_reader.cc',
         'minidump/minidump_annotation_reader.h',
         'minidump/minidump_simple_string_dictionary_reader.cc',
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
index 277bf6e..6f0fc90e 100644
--- a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
+++ b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
@@ -81,13 +81,13 @@
         'elf/elf_image_reader_test_note.S',
         'linux/debug_rendezvous_test.cc',
         'linux/exception_snapshot_linux_test.cc',
-        'linux/process_reader_test.cc',
+        'linux/process_reader_linux_test.cc',
         'linux/system_snapshot_linux_test.cc',
         'mac/cpu_context_mac_test.cc',
         'mac/mach_o_image_annotations_reader_test.cc',
         'mac/mach_o_image_reader_test.cc',
         'mac/mach_o_image_segment_reader_test.cc',
-        'mac/process_reader_test.cc',
+        'mac/process_reader_mac_test.cc',
         'mac/process_types_test.cc',
         'mac/system_snapshot_mac_test.cc',
         'minidump/process_snapshot_minidump_test.cc',
@@ -182,6 +182,19 @@
       'sources': [
         'crashpad_info_size_test_module.cc',
       ],
+      'include_dirs': [
+        '..',
+      ],
+      'conditions': [
+        ['OS=="linux" or OS=="android"', {
+          'sources': [
+            'crashpad_info_size_test_note.S',
+          ],
+          'dependencies': [
+            '../util/util.gyp:crashpad_util',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'crashpad_snapshot_test_module_small',
@@ -195,6 +208,19 @@
       'sources': [
         'crashpad_info_size_test_module.cc',
       ],
+      'include_dirs': [
+        '..',
+      ],
+      'conditions': [
+        ['OS=="linux" or OS=="android"', {
+          'sources': [
+            'crashpad_info_size_test_note.S',
+          ],
+          'dependencies': [
+            '../util/util.gyp:crashpad_util',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'crashpad_snapshot_test_both_dt_hash_styles',
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc
index 146c66a..759cc13 100644
--- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc
@@ -15,21 +15,12 @@
 #include <intrin.h>
 #include <windows.h>
 
-#include "base/files/file_path.h"
 #include "base/logging.h"
+#include "build/build_config.h"
 #include "client/crashpad_client.h"
-#include "util/file/file_io.h"
-#include "util/misc/from_pointer_cast.h"
+#include "util/misc/capture_context.h"
 #include "util/win/address_types.h"
 
-namespace {
-
-__declspec(noinline) crashpad::WinVMAddress CurrentAddress() {
-  return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress());
-}
-
-}  // namespace
-
 int wmain(int argc, wchar_t* argv[]) {
   CHECK_EQ(argc, 2);
 
@@ -38,8 +29,25 @@
 
   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
   PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle";
-  crashpad::WinVMAddress break_address = CurrentAddress();
-  crashpad::CheckedWriteFile(out, &break_address, sizeof(break_address));
+
+  CONTEXT context;
+  crashpad::CaptureContext(&context);
+#if defined(ARCH_CPU_64_BITS)
+  crashpad::WinVMAddress break_address = context.Rip;
+#else
+  crashpad::WinVMAddress break_address = context.Eip;
+#endif
+
+  // This does not used CheckedWriteFile() because at high optimization
+  // settings, a lot of logging code can be inlined, causing there to be a large
+  // number of instructions between where the IP is captured and the actual
+  // __debugbreak(). Instead call Windows' WriteFile() to minimize the amount of
+  // code here. Because the next line is going to crash in any case, there's
+  // minimal difference in behavior aside from an indication of what broke when
+  // the other end experiences a ReadFile() error.
+  DWORD bytes_written;
+  WriteFile(
+      out, &break_address, sizeof(break_address), &bytes_written, nullptr);
 
   __debugbreak();
 
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc
index f55f503..e2c524ae 100644
--- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc
@@ -18,18 +18,9 @@
 #include "base/logging.h"
 #include "client/crashpad_client.h"
 #include "client/simulate_crash.h"
-#include "util/file/file_io.h"
-#include "util/misc/from_pointer_cast.h"
+#include "util/misc/capture_context.h"
 #include "util/win/address_types.h"
 
-namespace {
-
-__declspec(noinline) crashpad::WinVMAddress CurrentAddress() {
-  return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress());
-}
-
-}  // namespace
-
 int wmain(int argc, wchar_t* argv[]) {
   CHECK_EQ(argc, 2);
 
@@ -38,8 +29,25 @@
 
   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
   PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle";
-  crashpad::WinVMAddress current_address = CurrentAddress();
-  crashpad::CheckedWriteFile(out, &current_address, sizeof(current_address));
+
+  CONTEXT context;
+  crashpad::CaptureContext(&context);
+#if defined(ARCH_CPU_64_BITS)
+  crashpad::WinVMAddress break_address = context.Rip;
+#else
+  crashpad::WinVMAddress break_address = context.Eip;
+#endif
+
+  // This does not used CheckedWriteFile() because at high optimization
+  // settings, a lot of logging code can be inlined, causing there to be a large
+  // number of instructions between where the IP is captured and the actual
+  // __debugbreak(). Instead call Windows' WriteFile() to minimize the amount of
+  // code here. Because the next line is going to crash in any case, there's
+  // minimal difference in behavior aside from an indication of what broke when
+  // the other end experiences a ReadFile() error.
+  DWORD bytes_written;
+  WriteFile(
+      out, &break_address, sizeof(break_address), &bytes_written, nullptr);
 
   CRASHPAD_SIMULATE_CRASH();
 
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h
index 0d21668..f6e29d9 100644
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h
@@ -52,8 +52,8 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the process that sustained
-  //!     the exception.
+  //! \param[in] process_reader A ProcessReaderWin for the process that
+  //!     sustained the exception.
   //! \param[in] thread_id The thread ID in which the exception occurred.
   //! \param[in] exception_pointers The address of an `EXCEPTION_POINTERS`
   //!     record in the target process, passed through from the exception
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
index a1ab8c6..376de7c 100644
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
@@ -103,7 +103,7 @@
     // Verify the exception happened at the expected location with a bit of
     // slop space to allow for reading the current PC before the exception
     // happens. See TestCrashingChild().
-    constexpr uint64_t kAllowedOffset = 64;
+    constexpr uint64_t kAllowedOffset = 100;
     EXPECT_GT(snapshot.Exception()->ExceptionAddress(), break_near_);
     EXPECT_LT(snapshot.Exception()->ExceptionAddress(),
               break_near_ + kAllowedOffset);
@@ -204,7 +204,7 @@
 
     // Verify the dump was captured at the expected location with some slop
     // space.
-    constexpr uint64_t kAllowedOffset = 64;
+    constexpr uint64_t kAllowedOffset = 100;
     EXPECT_GT(snapshot.Exception()->Context()->InstructionPointer(),
               dump_near_);
     EXPECT_LT(snapshot.Exception()->Context()->InstructionPointer(),
diff --git a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h
index 414f0a4..693588db0 100644
--- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h
+++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h
@@ -47,10 +47,10 @@
 
   //! \brief Initializes the object.
   //!
-  //! \param[in] process_reader A ProcessReader for the task containing the
-  //!     module.
-  //! \param[in] process_reader_module The module within the ProcessReader for
-  //!     which the snapshot should be created.
+  //! \param[in] process_reader A ProcessReaderWin for the process containing
+  //!     the module.
+  //! \param[in] process_reader_module The module within the ProcessReaderWin
+  //!     for which the snapshot should be created.
   //!
   //! \return `true` if the snapshot could be created, `false` otherwise with
   //!     an appropriate message logged.
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc b/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc
index 73a0ca7..2fa0258 100644
--- a/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc
@@ -21,8 +21,8 @@
 
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "util/misc/capture_context.h"
 #include "util/misc/time.h"
-#include "util/win/capture_context.h"
 #include "util/win/nt_internals.h"
 #include "util/win/ntstatus_logging.h"
 #include "util/win/process_structs.h"
diff --git a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc
index 4c99497..c87a6a6 100644
--- a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc
@@ -134,22 +134,24 @@
   EXPECT_EQ(standard_offset_seconds % (15 * 60), 0)
       << "standard_offset_seconds " << standard_offset_seconds;
 
-  if (dst_status == SystemSnapshot::kDoesNotObserveDaylightSavingTime) {
-    EXPECT_EQ(daylight_offset_seconds, standard_offset_seconds);
-    EXPECT_EQ(daylight_name, standard_name);
-  } else {
-    EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0)
-        << "daylight_offset_seconds " << daylight_offset_seconds;
+  // dst_status of kDoesNotObserveDaylightSavingTime can mean only that the
+  // adjustment is not automatic, as opposed to daylight/standard differences
+  // not existing at all. So it cannot be asserted that the two offsets are the
+  // same in that case.
 
-    // In contemporary usage, dst_delta_seconds will almost always be one hour,
-    // except for Lord Howe Island, Australia, which uses a 30-minute delta.
-    // Throughout history, other variations existed. See
-    // https://www.timeanddate.com/time/dst/.
-    int dst_delta_seconds = daylight_offset_seconds - standard_offset_seconds;
-    if (dst_delta_seconds != 60 * 60 && dst_delta_seconds != 30 * 60) {
-      FAIL() << "dst_delta_seconds " << dst_delta_seconds;
-    }
+  EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0)
+      << "daylight_offset_seconds " << daylight_offset_seconds;
 
+  // In contemporary usage, dst_delta_seconds will almost always be one hour,
+  // except for Lord Howe Island, Australia, which uses a 30-minute delta.
+  // Throughout history, other variations existed. See
+  // https://www.timeanddate.com/time/dst/.
+  int dst_delta_seconds = daylight_offset_seconds - standard_offset_seconds;
+  if (dst_delta_seconds != 60 * 60 && dst_delta_seconds != 30 * 60) {
+    FAIL() << "dst_delta_seconds " << dst_delta_seconds;
+  }
+
+  if (dst_status != SystemSnapshot::kDoesNotObserveDaylightSavingTime) {
     EXPECT_NE(standard_name, daylight_name);
   }
 }
diff --git a/third_party/crashpad/crashpad/test/BUILD.gn b/third_party/crashpad/crashpad/test/BUILD.gn
index f754174..0808096 100644
--- a/third_party/crashpad/crashpad/test/BUILD.gn
+++ b/third_party/crashpad/crashpad/test/BUILD.gn
@@ -74,8 +74,6 @@
       "linux/fake_ptrace_connection.h",
       "linux/get_tls.cc",
       "linux/get_tls.h",
-      "linux/scoped_pr_set_ptracer.cc",
-      "linux/scoped_pr_set_ptracer.h",
     ]
   }
 
@@ -96,7 +94,6 @@
 
   if (crashpad_is_fuchsia) {
     sources += [ "multiprocess_exec_fuchsia.cc" ]
-    libs = [ "launchpad" ]
   }
 
   public_configs = [ "..:crashpad_config" ]
@@ -121,6 +118,14 @@
       "../snapshot",
     ]
   }
+
+  if (crashpad_is_win) {
+    libs = [ "shell32.lib" ]
+  }
+
+  if (crashpad_is_fuchsia) {
+    libs = [ "launchpad" ]
+  }
 }
 
 source_set("test_test") {
diff --git a/third_party/crashpad/crashpad/test/mac/dyld.cc b/third_party/crashpad/crashpad/test/mac/dyld.cc
index 6fa2176..fb2156e 100644
--- a/third_party/crashpad/crashpad/test/mac/dyld.cc
+++ b/third_party/crashpad/crashpad/test/mac/dyld.cc
@@ -21,7 +21,7 @@
 #include <stdint.h>
 
 #include "base/logging.h"
-#include "snapshot/mac/process_reader.h"
+#include "snapshot/mac/process_reader_mac.h"
 #include "test/scoped_module_handle.h"
 #include "util/numeric/safe_assignment.h"
 
@@ -74,7 +74,7 @@
 #endif
 
   // On 10.13 and later, do it the hard way.
-  ProcessReader process_reader;
+  ProcessReaderMac process_reader;
   if (!process_reader.Initialize(mach_task_self())) {
     return nullptr;
   }
diff --git a/third_party/crashpad/crashpad/test/multiprocess.h b/third_party/crashpad/crashpad/test/multiprocess.h
index 1d3ee9b..aac9288 100644
--- a/third_party/crashpad/crashpad/test/multiprocess.h
+++ b/third_party/crashpad/crashpad/test/multiprocess.h
@@ -92,6 +92,12 @@
   //!     expected to kill the child.
   void SetExpectedChildTermination(TerminationReason reason, int code);
 
+#if !defined(OS_WIN)
+  //! \brief Sets termination reason and code appropriately for a child that
+  //!     terminates via `__builtin_trap()`.
+  void SetExpectedChildTerminationBuiltinTrap();
+#endif  // !OS_WIN
+
  protected:
   ~Multiprocess();
 
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
index e630608..7d571f9 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
@@ -86,6 +86,10 @@
   code_ = code;
 }
 
+void Multiprocess::SetExpectedChildTerminationBuiltinTrap() {
+  SetExpectedChildTermination(kTerminationNormal, -1);
+}
+
 Multiprocess::~Multiprocess() {
   delete info_;
 }
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc
index 0104b0f3..99a1b01f 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc
@@ -98,6 +98,35 @@
   exec.Run();
 };
 
+#if !defined(OS_WIN)
+
+CRASHPAD_CHILD_TEST_MAIN(BuiltinTrapChild) {
+  __builtin_trap();
+  return EXIT_SUCCESS;
+}
+
+class TestBuiltinTrapTermination final : public MultiprocessExec {
+ public:
+  TestBuiltinTrapTermination() {
+    SetChildTestMainFunction("BuiltinTrapChild");
+    SetExpectedChildTerminationBuiltinTrap();
+  }
+
+  ~TestBuiltinTrapTermination() = default;
+
+ private:
+  void MultiprocessParent() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(TestBuiltinTrapTermination);
+};
+
+TEST(MultiprocessExec, BuiltinTrapTermination) {
+  TestBuiltinTrapTermination test;
+  test.Run();
+}
+
+#endif  // !OS_WIN
+
 }  // namespace
 }  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc
index f2761ea..8c77015 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc
@@ -23,7 +23,9 @@
 #include "build/build_config.h"
 
 #if defined(OS_POSIX)
+#if !defined(OS_FUCHSIA)
 #include <sys/resource.h>
+#endif  // !OS_FUCHSIA
 #include <unistd.h>
 #elif defined(OS_WIN)
 #include <windows.h>
diff --git a/third_party/crashpad/crashpad/test/multiprocess_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
index c638b48a..96b8ad2 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_posix.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
@@ -157,6 +157,14 @@
   code_ = code;
 }
 
+void Multiprocess::SetExpectedChildTerminationBuiltinTrap() {
+#if defined(ARCH_CPU_ARM64)
+  SetExpectedChildTermination(kTerminationSignal, SIGTRAP);
+#else
+  SetExpectedChildTermination(kTerminationSignal, SIGILL);
+#endif
+}
+
 Multiprocess::~Multiprocess() {
 }
 
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp
index a3721ef..2973708 100644
--- a/third_party/crashpad/crashpad/test/test.gyp
+++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -45,8 +45,6 @@
         'linux/fake_ptrace_connection.h',
         'linux/get_tls.cc',
         'linux/get_tls.h',
-        'linux/scoped_pr_set_ptracer.cc',
-        'linux/scoped_pr_set_ptracer.h',
         'mac/dyld.cc',
         'mac/dyld.h',
         'mac/exception_swallower.cc',
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc
index f6471d08..0d7db06 100644
--- a/third_party/crashpad/crashpad/test/test_paths.cc
+++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -127,6 +127,10 @@
 // static
 base::FilePath TestPaths::ExpectedExecutableBasename(
     const base::FilePath::StringType& name) {
+#if defined(OS_FUCHSIA)
+  // Apps in Fuchsia packages are always named "app".
+  return base::FilePath("app");
+#else  // OS_FUCHSIA
 #if defined(CRASHPAD_IS_IN_CHROMIUM)
   base::FilePath::StringType executable_name(
       FILE_PATH_LITERAL("crashpad_tests"));
@@ -139,6 +143,7 @@
 #endif  // OS_WIN
 
   return base::FilePath(executable_name);
+#endif  // OS_FUCHSIA
 }
 
 // static
@@ -195,7 +200,11 @@
 #endif  // OS_WIN
 
 #if defined(OS_FUCHSIA)
-      directory = base::FilePath(FILE_PATH_LITERAL("/pkg/lib"));
+      // TODO(scottmg): .so files are currently deployed into /boot/lib, where
+      // they'll be found (without a path) by the loader. Application packaging
+      // infrastructure is in progress, so this will likely change again in the
+      // future.
+      directory = base::FilePath();
 #endif
       break;
   }
diff --git a/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad b/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad
index fc4a514..8bf0a91 100644
--- a/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad
+++ b/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad
@@ -1,4 +1,3 @@
 This directory is a placeholder for Fuchsia tools that will be downloaded by
-CIPD (https://github.com/luci/luci-go/tree/master/cipd). The toolchain.ensure
-files specifies which CIPD packages to retrieve, at which versions, and where
-they're stored locally. The CIPD update happens as part of gclient runhooks.
+CIPD (https://github.com/luci/luci-go/tree/master/cipd). The CIPD update happens
+as part of gclient runhooks.
diff --git a/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn b/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn
index 1a02611..db5f4a56 100644
--- a/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn
+++ b/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn
@@ -138,6 +138,10 @@
       ":gtest",
       ":gtest_main",
     ]
+
+    if (crashpad_is_win) {
+      cflags = [ "/wd4702" ]  # unreachable code
+    }
   }
 
   test("gtest_environment_test") {
diff --git a/third_party/crashpad/crashpad/third_party/linux/README.crashpad b/third_party/crashpad/crashpad/third_party/linux/README.crashpad
new file mode 100644
index 0000000..8bf0a91
--- /dev/null
+++ b/third_party/crashpad/crashpad/third_party/linux/README.crashpad
@@ -0,0 +1,3 @@
+This directory is a placeholder for Fuchsia tools that will be downloaded by
+CIPD (https://github.com/luci/luci-go/tree/master/cipd). The CIPD update happens
+as part of gclient runhooks.
diff --git a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
index db0f99a1..0723ba3 100644
--- a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
+++ b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
@@ -89,6 +89,7 @@
         "/wd4245",  # conversion from 't1' to 't2', signed/unsigned mismatch
         "/wd4267",  # conversion from 'size_t' to 't', possible loss of data
         "/wd4324",  # structure was padded due to alignment specifier
+        "/wd4702",  # unreachable code
       ]
     } else {
       defines += [
diff --git a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
index cc21698..b4c2a15b 100644
--- a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
+++ b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
@@ -584,16 +584,13 @@
       file_reader = std::move(file_path_reader);
     }
 
-    CrashReportDatabase::NewReport* new_report;
+    std::unique_ptr<CrashReportDatabase::NewReport> new_report;
     CrashReportDatabase::OperationStatus status =
         database->PrepareNewCrashReport(&new_report);
     if (status != CrashReportDatabase::kNoError) {
       return EXIT_FAILURE;
     }
 
-    CrashReportDatabase::CallErrorWritingCrashReport
-        call_error_writing_crash_report(database.get(), new_report);
-
     char buf[4096];
     FileOperationResult read_result;
     do {
@@ -601,16 +598,13 @@
       if (read_result < 0) {
         return EXIT_FAILURE;
       }
-      if (read_result > 0 &&
-          !LoggingWriteFile(new_report->handle, buf, read_result)) {
+      if (read_result > 0 && !new_report->Writer()->Write(buf, read_result)) {
         return EXIT_FAILURE;
       }
     } while (read_result > 0);
 
-    call_error_writing_crash_report.Disarm();
-
     UUID uuid;
-    status = database->FinishedWritingCrashReport(new_report, &uuid);
+    status = database->FinishedWritingCrashReport(std::move(new_report), &uuid);
     if (status != CrashReportDatabase::kNoError) {
       return EXIT_FAILURE;
     }
diff --git a/third_party/crashpad/crashpad/tools/generate_dump.cc b/third_party/crashpad/crashpad/tools/generate_dump.cc
index a470bfd..c1fbde8 100644
--- a/third_party/crashpad/crashpad/tools/generate_dump.cc
+++ b/third_party/crashpad/crashpad/tools/generate_dump.cc
@@ -47,6 +47,8 @@
 #include "util/win/xp_compat.h"
 #elif defined(OS_FUCHSIA)
 #include "snapshot/fuchsia/process_snapshot_fuchsia.h"
+#elif defined(OS_LINUX)
+#include "snapshot/linux/process_snapshot_linux.h"
 #endif  // OS_MACOSX
 
 namespace crashpad {
@@ -199,6 +201,12 @@
     if (!process_snapshot.Initialize(ZX_HANDLE_INVALID)) {
       return EXIT_FAILURE;
     }
+#elif defined(OS_LINUX)
+    // TODO(jperaza): https://crashpad.chromium.org/bug/30.
+    ProcessSnapshotLinux process_snapshot;
+    if (!process_snapshot.Initialize(nullptr)) {
+      return EXIT_FAILURE;
+    }
 #endif  // OS_MACOSX
 
     FileWriter file_writer;
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn
index 13a5da8..4c90785f 100644
--- a/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -14,6 +14,13 @@
 
 import("../build/crashpad_buildconfig.gni")
 
+declare_args() {
+  if (crashpad_is_linux) {
+    # Whether the libcurl-based HTTPTransport implementation should be built.
+    enable_http_transport_libcurl = true
+  }
+}
+
 if (crashpad_is_mac) {
   if (crashpad_is_in_chromium) {
     import("//build/config/sysroot.gni")
@@ -83,7 +90,9 @@
     "misc/address_types.h",
     "misc/arraysize_unsafe.h",
     "misc/as_underlying_type.h",
+    "misc/capture_context.h",
     "misc/clock.h",
+    "misc/elf_note_types.h",
     "misc/from_pointer_cast.h",
     "misc/implicit_cast.h",
     "misc/initialization_state.h",
@@ -142,6 +151,7 @@
     "string/split_string.cc",
     "string/split_string.h",
     "synchronization/semaphore.h",
+    "thread/stoppable.h",
     "thread/thread.cc",
     "thread/thread.h",
     "thread/thread_log_messages.cc",
@@ -231,6 +241,7 @@
       "mach/task_for_pid.h",
       "mach/task_memory.cc",
       "mach/task_memory.h",
+      "misc/capture_context_mac.S",
       "misc/clock_mac.cc",
       "misc/paths_mac.cc",
       "net/http_transport_mac.mm",
@@ -241,7 +252,11 @@
   }
 
   if (crashpad_is_linux) {
-    sources += [ "net/http_transport_libcurl.cc" ]
+    if (enable_http_transport_libcurl) {
+      sources += [ "net/http_transport_libcurl.cc" ]
+    } else {
+      sources += [ "net/http_transport_none.cc" ]
+    }
   }
 
   if (crashpad_is_linux || crashpad_is_android) {
@@ -267,11 +282,14 @@
       "linux/ptrace_connection.h",
       "linux/ptracer.cc",
       "linux/ptracer.h",
+      "linux/scoped_pr_set_ptracer.cc",
+      "linux/scoped_pr_set_ptracer.h",
       "linux/scoped_ptrace_attach.cc",
       "linux/scoped_ptrace_attach.h",
       "linux/thread_info.cc",
       "linux/thread_info.h",
       "linux/traits.h",
+      "misc/capture_context_linux.S",
       "misc/paths_linux.cc",
       "posix/process_info_linux.cc",
       "process/process_memory_linux.cc",
@@ -303,7 +321,6 @@
       "synchronization/semaphore_win.cc",
       "thread/thread_win.cc",
       "win/address_types.h",
-      "win/capture_context.h",
       "win/checked_win_address_range.h",
       "win/command_line.cc",
       "win/command_line.h",
@@ -357,12 +374,12 @@
     # https://crbug.com/762167.
     if (host_os == "win") {
       sources += [
-        "win/capture_context.asm",
+        "misc/capture_context_win.asm",
         "win/safe_terminate_process.asm",
       ]
     } else {
       sources += [
-        "win/capture_context_broken.cc",
+        "misc/capture_context_broken.cc",
         "win/safe_terminate_process_broken.cc",
       ]
     }
@@ -371,7 +388,7 @@
   if (crashpad_is_fuchsia) {
     sources += [
       "misc/paths_fuchsia.cc",
-      "net/http_transport_fuchsia.cc",
+      "net/http_transport_none.cc",
       "process/process_memory_fuchsia.cc",
       "process/process_memory_fuchsia.h",
     ]
@@ -402,16 +419,22 @@
     include_dirs += [ "$root_build_dir/gen" ]
   }
 
-  if (crashpad_is_linux) {
+  if (crashpad_is_linux && enable_http_transport_libcurl) {
     libs = [ "curl" ]
   }
 
   if (crashpad_is_win) {
-    cflags = [
-      "/wd4201",  # nonstandard extension used : nameless struct/union.
-      "/wd4577",  # 'noexcept' used with no exception handling mode specified.
+    libs = [
+      "user32.lib",
+
+      # TODO(jperaza): version.lib is needed for Windows 7 compatibility.
+      # mincore.lib may be linked against instead when targeting Windows 8+.
+      "version.lib",
+
+      "winhttp.lib",
     ]
-    libs = [ "winhttp.lib" ]
+
+    cflags = [ "/wd4201" ]  # nonstandard extension used: nameless struct/union.
 
     if (current_cpu == "x86") {
       asmflags = [ "/safeseh" ]
@@ -430,6 +453,7 @@
     "file/filesystem_test.cc",
     "file/string_file_test.cc",
     "misc/arraysize_unsafe_test.cc",
+    "misc/capture_context_test_util.h",
     "misc/clock_test.cc",
     "misc/from_pointer_cast_test.cc",
     "misc/initialization_state_dcheck_test.cc",
@@ -463,7 +487,16 @@
     "thread/worker_thread_test.cc",
   ]
 
-  if (!crashpad_is_android && !crashpad_is_fuchsia) {
+  if (!crashpad_is_fuchsia) {
+    sources += [
+      # No NativeCPUContext defined for Fuchsia yet.
+      # https://crashpad.chromium.org/bug/196.
+      "misc/capture_context_test.cc",
+    ]
+  }
+
+  if (!crashpad_is_android && !crashpad_is_fuchsia &&
+      (!crashpad_is_linux || enable_http_transport_libcurl)) {
     # Android and Fuchsia will each require an HTTPTransport implementation
     # (libcurl isn’t in either’s SDK) and a solution to
     # http_transport_test_server.py, because Python isn’t available on either.
@@ -471,8 +504,10 @@
     # the build host with a method to forward requests from the device to the
     # host.
     #
-    # TODO(scottmg): Fuchsia will also require an implementation of
-    # MultiprocessExec for testing.
+    # Linux optionally compiles in a libcurl-based HTTPTransport, but since curl
+    # isn't in a base Debian sysroot (which is what Chromium builds against),
+    # maintain an option to exclude that, for now.
+    # https://crashpad.chromium.org/bug/220.
     sources += [ "net/http_transport_test.cc" ]
   }
 
@@ -508,6 +543,7 @@
       "mach/scoped_task_suspend_test.cc",
       "mach/symbolic_constants_mach_test.cc",
       "mach/task_memory_test.cc",
+      "misc/capture_context_test_util_mac.cc",
     ]
   }
 
@@ -519,6 +555,7 @@
       "linux/ptrace_broker_test.cc",
       "linux/ptracer_test.cc",
       "linux/scoped_ptrace_attach_test.cc",
+      "misc/capture_context_test_util_linux.cc",
     ]
   }
 
@@ -532,7 +569,7 @@
 
   if (crashpad_is_win) {
     sources += [
-      "win/capture_context_test.cc",
+      "misc/capture_context_test_util_win.cc",
       "win/command_line_test.cc",
       "win/critical_section_with_debug_info_test.cc",
       "win/exception_handler_server_test.cc",
@@ -568,7 +605,10 @@
   }
 
   if (crashpad_is_win) {
-    libs = [ "rpcrt4.lib" ]
+    libs = [
+      "rpcrt4.lib",
+      "dbghelp.lib",
+    ]
     data_deps = [
       ":crashpad_util_test_process_info_test_child",
       ":crashpad_util_test_safe_terminate_process_test_child",
diff --git a/third_party/crashpad/crashpad/util/file/file_io.h b/third_party/crashpad/crashpad/util/file/file_io.h
index 044a0a6..050c074 100644
--- a/third_party/crashpad/crashpad/util/file/file_io.h
+++ b/third_party/crashpad/crashpad/util/file/file_io.h
@@ -404,6 +404,11 @@
                                           FileWriteMode mode,
                                           FilePermissions permissions);
 
+// Fuchsia does not currently support any sort of file locking. See
+// https://crashpad.chromium.org/bug/196 and
+// https://crashpad.chromium.org/bug/217.
+#if !defined(OS_FUCHSIA)
+
 //! \brief Locks the given \a file using `flock()` on POSIX or `LockFileEx()` on
 //!     Windows.
 //!
@@ -433,6 +438,8 @@
 //! \return `true` on success, or `false` and a message will be logged.
 bool LoggingUnlockFile(FileHandle file);
 
+#endif  // !OS_FUCHSIA
+
 //! \brief Wraps `lseek()` or `SetFilePointerEx()`. Logs an error if the
 //!     operation fails.
 //!
diff --git a/third_party/crashpad/crashpad/util/file/file_io_posix.cc b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
index 2993279..f311616 100644
--- a/third_party/crashpad/crashpad/util/file/file_io_posix.cc
+++ b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
@@ -157,6 +157,8 @@
   return fd;
 }
 
+#if !defined(OS_FUCHSIA)
+
 bool LoggingLockFile(FileHandle file, FileLocking locking) {
   int operation = (locking == FileLocking::kShared) ? LOCK_SH : LOCK_EX;
   int rv = HANDLE_EINTR(flock(file, operation));
@@ -170,6 +172,8 @@
   return rv == 0;
 }
 
+#endif  // !OS_FUCHSIA
+
 FileOffset LoggingSeekFile(FileHandle file, FileOffset offset, int whence) {
   off_t rv = lseek(file, offset, whence);
   PLOG_IF(ERROR, rv < 0) << "lseek";
diff --git a/third_party/crashpad/crashpad/util/file/file_io_test.cc b/third_party/crashpad/crashpad/util/file/file_io_test.cc
index fdcf7e9..4446c320 100644
--- a/third_party/crashpad/crashpad/util/file/file_io_test.cc
+++ b/third_party/crashpad/crashpad/util/file/file_io_test.cc
@@ -523,6 +523,11 @@
   FileShareModeTest(ReadOrWrite::kWrite, ReadOrWrite::kWrite);
 }
 
+// Fuchsia does not currently support any sort of file locking. See
+// https://crashpad.chromium.org/bug/196 and
+// https://crashpad.chromium.org/bug/217.
+#if !defined(OS_FUCHSIA)
+
 TEST(FileIO, MultipleSharedLocks) {
   ScopedTempDir temp_dir;
   base::FilePath shared_file =
@@ -648,6 +653,8 @@
   LockingTest(FileLocking::kShared, FileLocking::kExclusive);
 }
 
+#endif  // !OS_FUCHSIA
+
 TEST(FileIO, FileSizeByHandle) {
   EXPECT_EQ(LoggingFileSizeByHandle(kInvalidFileHandle), -1);
 
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
index b1f19f6..c2234da 100644
--- a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
+++ b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
@@ -65,6 +65,14 @@
 
 bool MoveFileOrDirectory(const base::FilePath& source,
                          const base::FilePath& dest) {
+#if defined(OS_FUCHSIA)
+  // Fuchsia fails and sets errno to EINVAL if source and dest are the same.
+  // Upstream bug is ZX-1729.
+  if (!source.empty() && source == dest) {
+    return true;
+  }
+#endif  // OS_FUCHSIA
+
   if (rename(source.value().c_str(), dest.value().c_str()) != 0) {
     PLOG(ERROR) << "rename " << source.value().c_str() << ", "
                 << dest.value().c_str();
diff --git a/third_party/crashpad/crashpad/util/linux/ptracer.cc b/third_party/crashpad/crashpad/util/linux/ptracer.cc
index 2011581..84447362 100644
--- a/third_party/crashpad/crashpad/util/linux/ptracer.cc
+++ b/third_party/crashpad/crashpad/util/linux/ptracer.cc
@@ -285,9 +285,9 @@
     switch (errno) {
 #if defined(ARCH_CPU_ARMEL)
       case EIO:
-        if (GetGeneralPurposeRegistersLegacy(tid, context, can_log)) {
-          return sizeof(context->t32);
-        }
+        return GetGeneralPurposeRegistersLegacy(tid, context, can_log)
+                   ? sizeof(context->t32)
+                   : 0;
 #endif  // ARCH_CPU_ARMEL
       default:
         PLOG_IF(ERROR, can_log) << "ptrace";
diff --git a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc
similarity index 70%
rename from third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc
rename to third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc
index bc9695ae..c7aeefc 100644
--- a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc
+++ b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc
@@ -12,29 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "test/linux/scoped_pr_set_ptracer.h"
+#include "util/linux/scoped_pr_set_ptracer.h"
 
 #include <errno.h>
 #include <sys/prctl.h>
 
-#include "gtest/gtest.h"
-#include "test/errors.h"
+#include "base/logging.h"
 
 namespace crashpad {
-namespace test {
 
-ScopedPrSetPtracer::ScopedPrSetPtracer(pid_t pid) {
+ScopedPrSetPtracer::ScopedPrSetPtracer(pid_t pid, bool may_log)
+    : success_(false), may_log_(may_log) {
   success_ = prctl(PR_SET_PTRACER, pid, 0, 0, 0) == 0;
-  if (!success_) {
-    EXPECT_EQ(errno, EINVAL) << ErrnoMessage("prctl");
-  }
+  PLOG_IF(ERROR, !success_ && may_log && errno != EINVAL) << "prctl";
 }
 
 ScopedPrSetPtracer::~ScopedPrSetPtracer() {
   if (success_) {
-    EXPECT_EQ(prctl(PR_SET_PTRACER, 0, 0, 0, 0), 0) << ErrnoMessage("prctl");
+    int res = prctl(PR_SET_PTRACER, 0, 0, 0, 0);
+    PLOG_IF(ERROR, res != 0 && may_log_) << "prctl";
   }
 }
 
-}  // namespace test
 }  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h
similarity index 69%
rename from third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h
rename to third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h
index df9cff7..2bc8677 100644
--- a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h
+++ b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h
@@ -12,36 +12,40 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_
-#define CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_
+#ifndef CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_
+#define CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_
 
 #include <sys/types.h>
 
 #include "base/macros.h"
 
 namespace crashpad {
-namespace test {
 
 class ScopedPrSetPtracer {
  public:
-  //! \brief Uses `PR_SET_PTRACER` to set \a pid as the caller's ptracer or
-  //!     expects `EINVAL`.
+  //! \brief Uses `PR_SET_PTRACER` to set \a pid as the caller's ptracer.
   //!
   //! `PR_SET_PTRACER` is only supported if the Yama Linux security module (LSM)
   //! is enabled. Otherwise, `prctl(PR_SET_PTRACER, ...)` fails with `EINVAL`.
   //! See linux-4.9.20/security/yama/yama_lsm.c yama_task_prctl() and
   //! linux-4.9.20/kernel/sys.c [sys_]prctl().
-  explicit ScopedPrSetPtracer(pid_t pid);
+  //!
+  //! An error message will be logged on failure only if \a may_log is `true`
+  //! and `prctl` does not fail with `EINVAL`;
+  //!
+  //! \param[in] pid The process ID of the process to make the caller's ptracer.
+  //! \param[in] may_log if `true`, this class may log error messages.
+  ScopedPrSetPtracer(pid_t pid, bool may_log);
 
   ~ScopedPrSetPtracer();
 
  private:
   bool success_;
+  bool may_log_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedPrSetPtracer);
 };
 
-}  // namespace test
 }  // namespace crashpad
 
-#endif  // CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_
+#endif  // CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_
diff --git a/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc b/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc
index 78552e77..d009e682 100644
--- a/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc
+++ b/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc
@@ -20,9 +20,9 @@
 
 #include "gtest/gtest.h"
 #include "test/errors.h"
-#include "test/linux/scoped_pr_set_ptracer.h"
 #include "test/multiprocess.h"
 #include "util/file/file_io.h"
+#include "util/linux/scoped_pr_set_ptracer.h"
 
 namespace crashpad {
 namespace test {
@@ -75,7 +75,7 @@
   }
 
   void MultiprocessChild() override {
-    ScopedPrSetPtracer set_ptracer(getppid());
+    ScopedPrSetPtracer set_ptracer(getppid(), /* may_log= */ true);
 
     char c = '\0';
     CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
@@ -98,7 +98,7 @@
 
  private:
   void MultiprocessParent() override {
-    ScopedPrSetPtracer set_ptracer(ChildPID());
+    ScopedPrSetPtracer set_ptracer(ChildPID(), /* may_log= */ true);
     char c = '\0';
     CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
 
@@ -140,7 +140,7 @@
 
  private:
   void MultiprocessParent() override {
-    ScopedPrSetPtracer set_ptracer(ChildPID());
+    ScopedPrSetPtracer set_ptracer(ChildPID(), /* may_log= */ true);
     char c = '\0';
     CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
 
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context.h b/third_party/crashpad/crashpad/util/misc/capture_context.h
new file mode 100644
index 0000000..5c1838a
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_MISC_CAPTURE_CONTEXT_H_
+#define CRASHPAD_UTIL_MISC_CAPTURE_CONTEXT_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_MACOSX)
+#include <mach/mach.h>
+#elif defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+#include <ucontext.h>
+#endif  // OS_MACOSX
+
+namespace crashpad {
+
+#if defined(OS_MACOSX)
+#if defined(ARCH_CPU_X86_FAMILY)
+using NativeCPUContext = x86_thread_state;
+#endif
+#elif defined(OS_WIN)
+using NativeCPUContext = CONTEXT;
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+using NativeCPUContext = ucontext_t;
+#endif  // OS_MACOSX
+
+// No NativeCPUContext defined for Fuchsia yet.
+// https://crashpad.chromium.org/bug/196.
+#if !defined(OS_FUCHSIA)
+
+//! \brief Saves the CPU context.
+//!
+//! The CPU context will be captured as accurately and completely as possible,
+//! containing an atomic snapshot at the point of this function’s return. This
+//! function does not modify any registers.
+//!
+//! This function is a replacement for `RtlCaptureContext()` and `getcontext()`
+//! which contain bugs and/or limitations.
+//!
+//! On 32-bit x86, `RtlCaptureContext()` requires that `ebp` be used as a frame
+//! pointer, and returns `ebp`, `esp`, and `eip` out of sync with the other
+//! registers. Both the 32-bit x86 and 64-bit x86_64 versions of
+//! `RtlCaptureContext()` capture only the state of the integer registers,
+//! ignoring floating-point and vector state.
+//!
+//! \param[out] cpu_context The structure to store the context in.
+//!
+//! \note The ABI may require that this function's argument is passed by
+//!     register, preventing this fuction from saving the original value of that
+//!     register. This occurs in the following circumstances:
+//!
+//!     OS          | Architecture | Register
+//!     ------------|--------------|---------
+//!     Win         | x86_64       | `%%rcx`
+//!     macOS/Linux | x86_64       | `%%rdi`
+//!     Linux       | ARM/ARM64    | `r0`/`x0`
+//!
+//!     Additionally, the value `LR` on ARM/ARM64 will be the return address of
+//!     this function.
+//!
+//!     If the value of these register prior to calling this function are needed
+//!     they must be obtained separately prior to calling this function. For
+//!     example:
+//!     \code
+//!       uint64_t rdi;
+//!       asm("movq %%rdi, %0" : "=m"(rdi));
+//!     \endcode
+void CaptureContext(NativeCPUContext* cpu_context);
+
+#endif  // !OS_FUCHSIA
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_MISC_CAPTURE_CONTEXT_H_
diff --git a/third_party/crashpad/crashpad/util/win/capture_context_broken.cc b/third_party/crashpad/crashpad/util/misc/capture_context_broken.cc
similarity index 90%
rename from third_party/crashpad/crashpad/util/win/capture_context_broken.cc
rename to third_party/crashpad/crashpad/util/misc/capture_context_broken.cc
index 4a641515..ab7a5974 100644
--- a/third_party/crashpad/crashpad/util/win/capture_context_broken.cc
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_broken.cc
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "util/win/capture_context.h"
+#include "util/misc/capture_context.h"
 
 #include "base/logging.h"
 
 namespace crashpad {
 
-void CaptureContext(CONTEXT* context) {
+void CaptureContext(NativeCPUContext* context) {
   // Don't use this file in production.
   CHECK(false)
       << "Don't use this! For cross builds only. See https://crbug.com/762167.";
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
new file mode 100644
index 0000000..c16d0c7
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
@@ -0,0 +1,324 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// namespace crashpad {
+// void CaptureContext(ucontext_t* context);
+// }  // namespace crashpad
+#define CAPTURECONTEXT_SYMBOL _ZN8crashpad14CaptureContextEP8ucontext
+
+  .text
+  .globl CAPTURECONTEXT_SYMBOL
+#if defined(__i386__) || defined(__x86_64__)
+  .balign 16, 0x90
+#elif defined(__arm__) || defined(__aarch64__)
+  .balign 4, 0x0
+#endif
+
+CAPTURECONTEXT_SYMBOL:
+
+#if defined(__i386__)
+
+  .cfi_startproc
+
+  pushl %ebp
+  .cfi_def_cfa_offset 8
+  .cfi_offset %ebp, -8
+  movl %esp, %ebp
+  .cfi_def_cfa_register %ebp
+
+  // Note that 16-byte stack alignment is not maintained because this function
+  // does not call out to any other.
+
+  // pushfl first, because some instructions (but probably none used here)
+  // affect %eflags. %eflags will be in -4(%ebp).
+  pushfl
+
+  // Save the original value of %eax, and use %eax to hold the ucontext_t*
+  // argument. The original value of %eax will be in -8(%ebp).
+  pushl %eax
+  movl 8(%ebp), %eax
+
+  // Save the original value of %ecx, and use %ecx as a scratch register.
+  pushl %ecx
+
+  // The segment registers are 16 bits wide, but mcontext_t declares them
+  // as unsigned 32-bit values, so zero the top half.
+  xorl %ecx, %ecx
+  movw %gs, %cx
+  movl %ecx, 0x14(%eax)  // context->uc_mcontext.xgs
+  movw %fs, %cx
+  movl %ecx, 0x18(%eax)  // context->uc_mcontext.xfs
+  movw %es, %cx
+  movl %ecx, 0x1c(%eax)  // context->uc_mcontext.xes
+  movw %ds, %cx
+  movl %ecx, 0x20(%eax)  // context->uc_mcontext.xds
+
+  // General-purpose registers whose values haven’t changed can be captured
+  // directly.
+  movl %edi, 0x24(%eax)  // context->uc_mcontext.edi
+  movl %esi, 0x28(%eax)  // context->uc_mcontext.esi
+
+  // The original %ebp was saved on the stack in this function’s prologue.
+  movl (%ebp), %ecx
+  movl %ecx, 0x2c(%eax)  // context->uc_mcontext.ebp
+
+  // %esp was saved in %ebp in this function’s prologue, but the caller’s %esp
+  // is 8 more than this value: 4 for the original %ebp saved on the stack in
+  // this function’s prologue, and 4 for the return address saved on the stack
+  // by the call instruction that reached this function.
+  leal 8(%ebp), %ecx
+  movl %ecx, 0x30(%eax)  // context->uc_mcontext.esp
+
+  // More general-purpose registers
+  movl %ebx, 0x34(%eax)  // context->uc_mcontext.ebx
+  movl %edx, 0x38(%eax)  // context->uc_mcontext.edx
+
+  // The original %ecx was saved on the stack above.
+  movl -12(%ebp), %ecx
+  movl %ecx, 0x3c(%eax)  // context->uc_mcontext.ecx
+
+  // The original %eax was saved on the stack above.
+  movl -8(%ebp), %ecx
+  movl %ecx, 0x40(%eax)  // context->uc_mcontext.eax
+
+  // trapno and err are unused so zero them out.
+  xorl %ecx, %ecx
+  movl %ecx, 0x44(%eax)  // context->uc_mcontext.trapno
+  movl %ecx, 0x48(%eax)  // context->uc_mcontext.err
+
+  // %eip can’t be accessed directly, but the return address saved on the stack
+  // by the call instruction that reached this function can be used.
+  movl 4(%ebp), %ecx
+  movl %ecx, 0x4c(%eax)  // context->uc_mcontext.eip
+
+  // More segment registers
+  xorl %ecx, %ecx
+  movw %cs, %cx
+  movl %ecx, 0x50(%eax)  // context->uc_mcontext.xcs
+
+  // The original %eflags was saved on the stack above.
+  movl -4(%ebp), %ecx
+  movl %ecx, 0x54(%eax)  // context->uc_mcontext.eflags
+
+  // uesp is unused so zero it out.
+  xorl %ecx, %ecx
+  movl %ecx, 0x58(%eax)  // context->uc_mcontext.uesp
+
+  // The last segment register.
+  movw %ss, %cx
+  movl %ecx, 0x5c(%eax)  // context->uc_mcontext.xss
+
+  // TODO(jperaza): save floating-point registers.
+
+  // Clean up by restoring clobbered registers, even those considered volatile
+  // by the ABI, so that the captured context represents the state at this
+  // function’s exit.
+  popl %ecx
+  popl %eax
+  popfl
+
+  popl %ebp
+
+  ret
+
+  .cfi_endproc
+
+#elif defined(__x86_64__)
+
+  .cfi_startproc
+
+  pushq %rbp
+  .cfi_def_cfa_offset 16
+  .cfi_offset %rbp, -16
+  movq %rsp, %rbp
+  .cfi_def_cfa_register %rbp
+
+  // Note that 16-byte stack alignment is not maintained because this function
+  // does not call out to any other.
+
+  // pushfq first, because some instructions (but probably none used here)
+  // affect %rflags. %rflags will be in -8(%rbp).
+  pushfq
+
+  // General-purpose registers whose values haven’t changed can be captured
+  // directly.
+  movq %r8, 0x28(%rdi)  // context->uc_mcontext.r8
+  movq %r9, 0x30(%rdi)  // context->uc_mcontext.r9
+  movq %r10, 0x38(%rdi)  // context->uc_mcontext.r10
+  movq %r11, 0x40(%rdi)  // context->uc_mcontext.r11
+  movq %r12, 0x48(%rdi)  // context->uc_mcontext.r12
+  movq %r13, 0x50(%rdi)  // context->uc_mcontext.r13
+  movq %r14, 0x58(%rdi)  // context->uc_mcontext.r14
+  movq %r15, 0x60(%rdi)  // context->uc_mcontext.r15
+
+  // Because of the calling convention, there’s no way to recover the value of
+  // the caller’s %rdi as it existed prior to calling this function. This
+  // function captures a snapshot of the register state at its return, which
+  // involves %rdi containing a pointer to its first argument. Callers that
+  // require the value of %rdi prior to calling this function should obtain it
+  // separately. For example:
+  //   uint64_t rdi;
+  //   asm("movq %%rdi, %0" : "=m"(rdi));
+  movq %rdi, 0x68(%rdi)  // context->uc_mcontext.rdi
+
+  movq %rsi, 0x70(%rdi)  // context->uc_mcontext.rsi
+
+  // Use %r8 as a scratch register now that it has been saved.
+  // The original %rbp was saved on the stack in this function’s prologue.
+  movq (%rbp), %r8
+  movq %r8, 0x78(%rdi)  // context->uc_mcontext.rbp
+
+  // Save the remaining general-purpose registers.
+  movq %rbx, 0x80(%rdi)  // context->uc_mcontext.rbx
+  movq %rdx, 0x88(%rdi)  // context->uc_mcontext.rdx
+  movq %rax, 0x90(%rdi)  // context->uc_mcontext.rax
+  movq %rcx, 0x98(%rdi)  // context->uc_mcontext.rcx
+
+  // %rsp was saved in %rbp in this function’s prologue, but the caller’s %rsp
+  // is 16 more than this value: 8 for the original %rbp saved on the stack in
+  // this function’s prologue, and 8 for the return address saved on the stack
+  // by the call instruction that reached this function.
+  leaq 16(%rbp), %r8
+  movq %r8, 0xa0(%rdi)  // context->uc_mcontext.rsp
+
+  // %rip can’t be accessed directly, but the return address saved on the stack
+  // by the call instruction that reached this function can be used.
+  movq 8(%rbp), %r8
+  movq %r8, 0xa8(%rdi)  // context->uc_mcontext.rip
+
+  // The original %rflags was saved on the stack above.
+  movq -8(%rbp), %r8
+  movq %r8, 0xb0(%rdi)  // context->uc_mcontext.eflags
+
+  // Save the segment registers
+  movw %cs, 0xb8(%rdi)  // context->uc_mcontext.cs
+  movw %gs, 0xba(%rdi)  // context->uc_mcontext.gs
+  movw %fs, 0xbc(%rdi)  // context->uc_mcontext.fs
+
+  xorw %ax, %ax
+  movw %ax, 0xbe(%rdi)  // context->uc_mcontext.padding
+
+  // Zero out the remainder of the unused pseudo-registers
+  xorq %r8, %r8
+  movq %r8, 0xc0(%rdi)  // context->uc_mcontext.err
+  movq %r8, 0xc8(%rdi)  // context->uc_mcontext.trapno
+  movq %r8, 0xd0(%rdi)  // context->uc_mcontext.oldmask
+  movq %r8, 0xd8(%rdi)  // context->uc_mcontext.cr2
+
+  // Clean up by restoring clobbered registers, even those considered volatile
+  // by the ABI, so that the captured context represents the state at this
+  // function’s exit.
+  movq 0x90(%rdi), %rax
+  movq 0x28(%rdi), %r8
+
+  // TODO(jperaza): save floating-point registers.
+
+  popfq
+
+  popq %rbp
+
+  ret
+
+  .cfi_endproc
+
+#elif defined(__arm__)
+
+  // The original r0 can't be recovered.
+  str r0, [r0, #0x20]
+
+  // Now advance r0 to point to the register array.
+  add r0, r0, #0x24
+
+  // Save registers r1-r12 at context->uc_mcontext.regs[i].
+  stm r0, {r1-r12}
+
+  // Restore r0.
+  sub r0, r0, #0x24
+
+  // Save named general purpose registers.
+  str FP, [r0, #0x4c]  // context->uc_mcontext.fp
+  str IP, [r0, #0x50]  // context->uc_mcontext.ip
+  str SP, [r0, #0x54]  // context->uc_mcontext.sp
+
+  // The original LR can't be recovered.
+  str LR, [r0, #0x58]  // context->uc_mcontext.lr
+
+  // The link register holds the return address for this function.
+  str LR, [r0, #0x5c]  // context->uc_mcontext.pc
+
+  // Use r1 as a scratch register.
+
+  // CPSR is a deprecated synonym for APSR.
+  mrs r1, APSR
+  str r1, [r0, #0x60]  // context->uc_mcontext.cpsr
+
+  // Zero out unused fields.
+  mov r1, #0x0
+  str r1, [r0, #0x14]  // context->uc_mcontext.trap_no
+  str r1, [r0, #0x18]  // context->uc_mcontext.error_code
+  str r1, [r0, #0x1c]  // context->uc_mcontext.oldmask
+  str r1, [r0, #0x64]  // context->uc_mcontext.fault_address
+
+  // Restore r1.
+  ldr r1, [r0, #0x24]
+
+  // TODO(jperaza): save floating-point registers.
+
+  mov PC, LR
+
+#elif defined(__aarch64__)
+
+  // Zero out fault_address, which is unused.
+  str x31, [x0, #0xb0]  // context->uc_mcontext.fault_address
+
+  // Save general purpose registers in context->uc_mcontext.regs[i].
+  // The original x0 can't be recovered.
+  stp x0, x1, [x0, #0xb8]
+  stp x2, x3, [x0, #0xc8]
+  stp x4, x5, [x0, #0xd8]
+  stp x6, x7, [x0, #0xe8]
+  stp x8, x9, [x0, #0xf8]
+  stp x10, x11, [x0, #0x108]
+  stp x12, x13, [x0, #0x118]
+  stp x14, x15, [x0, #0x128]
+  stp x16, x17, [x0, #0x138]
+  stp x18, x19, [x0, #0x148]
+  stp x20, x21, [x0, #0x158]
+  stp x22, x23, [x0, #0x168]
+  stp x24, x25, [x0, #0x178]
+  stp x26, x27, [x0, #0x188]
+  stp x28, x29, [x0, #0x198]
+
+  // The original LR can't be recovered.
+  str LR, [x0, #0x1a8]
+
+  // Use x1 as a scratch register.
+  mov x1, SP
+  str x1, [x0, #0x1b0] // context->uc_mcontext.sp
+
+  // The link register holds the return address for this function.
+  str LR, [x0, #0x1b8]  // context->uc_mcontext.pc
+
+  // NZCV, pstate, and CPSR are synonyms.
+  mrs x1, NZCV
+  str x1, [x0, #0x1c0]  // context->uc_mcontext.pstate
+
+  // Restore x1 from the saved context.
+  ldr x1, [x0, #0xc0]
+
+  // TODO(jperaza): save floating-point registers.
+
+  ret
+
+#endif  // __i386__
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac.S b/third_party/crashpad/crashpad/util/misc/capture_context_mac.S
similarity index 99%
rename from third_party/crashpad/crashpad/client/capture_context_mac.S
rename to third_party/crashpad/crashpad/util/misc/capture_context_mac.S
index 942d841..39c6ca6a 100644
--- a/third_party/crashpad/crashpad/client/capture_context_mac.S
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_mac.S
@@ -22,7 +22,7 @@
   .section __TEXT,__text,regular,pure_instructions
   .private_extern CAPTURECONTEXT_SYMBOL
   .globl CAPTURECONTEXT_SYMBOL
-  .align 4, 0x90
+  .balign 16, 0x90
 CAPTURECONTEXT_SYMBOL:
 
 #if defined(__i386__)
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
new file mode 100644
index 0000000..e31883e7
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/misc/capture_context.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "gtest/gtest.h"
+#include "util/misc/address_sanitizer.h"
+#include "util/misc/capture_context_test_util.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+void TestCaptureContext() {
+  NativeCPUContext context_1;
+  CaptureContext(&context_1);
+
+  {
+    SCOPED_TRACE("context_1");
+    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1));
+  }
+
+  // The program counter reference value is this function’s address. The
+  // captured program counter should be slightly greater than or equal to the
+  // reference program counter.
+  uintptr_t pc = ProgramCounterFromContext(context_1);
+
+#if !defined(ADDRESS_SANITIZER)
+  // AddressSanitizer can cause enough code bloat that the “nearby” check would
+  // likely fail.
+  const uintptr_t kReferencePC =
+      reinterpret_cast<uintptr_t>(TestCaptureContext);
+  EXPECT_PRED2([](uintptr_t actual,
+                  uintptr_t reference) { return actual - reference < 64u; },
+               pc,
+               kReferencePC);
+#endif  // !defined(ADDRESS_SANITIZER)
+
+  // Declare sp and context_2 here because all local variables need to be
+  // declared before computing the stack pointer reference value, so that the
+  // reference value can be the lowest value possible.
+  uintptr_t sp;
+  NativeCPUContext context_2;
+
+  // The stack pointer reference value is the lowest address of a local variable
+  // in this function. The captured program counter will be slightly less than
+  // or equal to the reference stack pointer.
+  const uintptr_t kReferenceSP =
+      std::min(std::min(reinterpret_cast<uintptr_t>(&context_1),
+                        reinterpret_cast<uintptr_t>(&context_2)),
+               std::min(reinterpret_cast<uintptr_t>(&pc),
+                        reinterpret_cast<uintptr_t>(&sp)));
+  sp = StackPointerFromContext(context_1);
+  EXPECT_PRED2([](uintptr_t actual,
+                  uintptr_t reference) { return reference - actual < 512u; },
+               sp,
+               kReferenceSP);
+
+  // Capture the context again, expecting that the stack pointer stays the same
+  // and the program counter increases. Strictly speaking, there’s no guarantee
+  // that these conditions will hold, although they do for known compilers even
+  // under typical optimization.
+  CaptureContext(&context_2);
+
+  {
+    SCOPED_TRACE("context_2");
+    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2));
+  }
+
+  EXPECT_EQ(StackPointerFromContext(context_2), sp);
+  EXPECT_GT(ProgramCounterFromContext(context_2), pc);
+}
+
+TEST(CaptureContext, CaptureContext) {
+  ASSERT_NO_FATAL_FAILURE(TestCaptureContext());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h b/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h
new file mode 100644
index 0000000..5a5ff7d
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/misc/capture_context.h"
+
+#include <stdint.h>
+
+namespace crashpad {
+namespace test {
+
+//! \brief Sanity check conditions that should be true for any NativeCPUContext
+//!     produced by CaptureContext().
+//!
+//! If the context structure has fields that tell whether it’s valid, such as
+//! magic numbers or size fields, sanity-checks those fields for validity with
+//! fatal gtest assertions. For other fields, where it’s possible to reason
+//! about their validity based solely on their contents, sanity-checks via
+//! nonfatal gtest assertions.
+//!
+//! \param[in] context The context to check.
+void SanityCheckContext(const NativeCPUContext& context);
+
+//! \brief Return the value of the program counter from a NativeCPUContext.
+uintptr_t ProgramCounterFromContext(const NativeCPUContext& context);
+
+//! \brief Return the value of the stack pointer from a NativeCPUContext.
+uintptr_t StackPointerFromContext(const NativeCPUContext& context);
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
new file mode 100644
index 0000000..fb64e5d
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/misc/capture_context_test_util.h"
+
+#include "base/logging.h"
+#include "gtest/gtest.h"
+#include "util/misc/from_pointer_cast.h"
+
+namespace crashpad {
+namespace test {
+
+void SanityCheckContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  // Nothing to do here yet.
+#elif defined(ARCH_CPU_X86_64)
+  EXPECT_EQ(context.uc_mcontext.gregs[REG_RDI],
+            FromPointerCast<intptr_t>(&context));
+#elif defined(ARCH_CPU_ARMEL)
+  EXPECT_EQ(context.uc_mcontext.arm_r0, FromPointerCast<uintptr_t>(&context));
+#elif defined(ARCH_CPU_ARM64)
+  EXPECT_EQ(context.uc_mcontext.regs[0], FromPointerCast<uintptr_t>(&context));
+#endif
+}
+
+uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.uc_mcontext.gregs[REG_EIP];
+#elif defined(ARCH_CPU_X86_64)
+  return context.uc_mcontext.gregs[REG_RIP];
+#elif defined(ARCH_CPU_ARMEL)
+  return context.uc_mcontext.arm_pc;
+#elif defined(ARCH_CPU_ARM64)
+  return context.uc_mcontext.pc;
+#endif
+}
+
+uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.uc_mcontext.gregs[REG_ESP];
+#elif defined(ARCH_CPU_X86_64)
+  return context.uc_mcontext.gregs[REG_RSP];
+#elif defined(ARCH_CPU_ARMEL)
+  return context.uc_mcontext.arm_sp;
+#elif defined(ARCH_CPU_ARM64)
+  return context.uc_mcontext.sp;
+#endif
+}
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc
new file mode 100644
index 0000000..afe0916
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc
@@ -0,0 +1,84 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/misc/capture_context_test_util.h"
+
+#include "gtest/gtest.h"
+#include "util/misc/implicit_cast.h"
+
+namespace crashpad {
+namespace test {
+
+void SanityCheckContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor),
+            implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32));
+  ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count),
+            implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT));
+#elif defined(ARCH_CPU_X86_64)
+  ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor),
+            implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64));
+  ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count),
+            implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT));
+#endif
+
+#if defined(ARCH_CPU_X86_FAMILY)
+// The segment registers are only capable of storing 16-bit quantities, but
+// the context structure provides native integer-width fields for them. Ensure
+// that the high bits are all clear.
+//
+// Many bit positions in the flags register are reserved and will always read
+// a known value. Most reserved bits are always 0, but bit 1 is always 1.
+// Check that the reserved bits are all set to their expected values. Note
+// that the set of reserved bits may be relaxed over time with newer CPUs, and
+// that this test may need to be changed to reflect these developments. The
+// current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel
+// Software Developer’s Manual, Volume 1: Basic Architecture (253665-051),
+// 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume
+// 2: System Programming (24593-3.24), 3.1.6 “RFLAGS Register”.
+#if defined(ARCH_CPU_X86)
+  EXPECT_EQ(context.uts.ts32.__cs & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__ds & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__es & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__fs & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__gs & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__ss & ~0xffff, 0u);
+  EXPECT_EQ(context.uts.ts32.__eflags & 0xffc0802a, 2u);
+#elif defined(ARCH_CPU_X86_64)
+  EXPECT_EQ(context.uts.ts64.__cs & ~UINT64_C(0xffff), 0u);
+  EXPECT_EQ(context.uts.ts64.__fs & ~UINT64_C(0xffff), 0u);
+  EXPECT_EQ(context.uts.ts64.__gs & ~UINT64_C(0xffff), 0u);
+  EXPECT_EQ(context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a), 2u);
+#endif
+#endif
+}
+
+uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.uts.ts32.__eip;
+#elif defined(ARCH_CPU_X86_64)
+  return context.uts.ts64.__rip;
+#endif
+}
+
+uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.uts.ts32.__esp;
+#elif defined(ARCH_CPU_X86_64)
+  return context.uts.ts64.__rsp;
+#endif
+}
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc
new file mode 100644
index 0000000..239beac
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc
@@ -0,0 +1,114 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/misc/capture_context_test_util.h"
+
+#include "base/macros.h"
+#include "gtest/gtest.h"
+
+namespace crashpad {
+namespace test {
+
+void SanityCheckContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  constexpr uint32_t must_have = CONTEXT_i386 | CONTEXT_CONTROL |
+                                 CONTEXT_INTEGER | CONTEXT_SEGMENTS |
+                                 CONTEXT_FLOATING_POINT;
+  ASSERT_EQ(context.ContextFlags & must_have, must_have);
+  constexpr uint32_t may_have = CONTEXT_EXTENDED_REGISTERS;
+  ASSERT_EQ(context.ContextFlags & ~(must_have | may_have), 0u);
+#elif defined(ARCH_CPU_X86_64)
+  ASSERT_EQ(
+      context.ContextFlags,
+      static_cast<DWORD>(CONTEXT_AMD64 | CONTEXT_CONTROL | CONTEXT_INTEGER |
+                         CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT));
+#endif
+
+#if defined(ARCH_CPU_X86_FAMILY)
+  // Many bit positions in the flags register are reserved and will always read
+  // a known value. Most reserved bits are always 0, but bit 1 is always 1.
+  // Check that the reserved bits are all set to their expected values. Note
+  // that the set of reserved bits may be relaxed over time with newer CPUs, and
+  // that this test may need to be changed to reflect these developments. The
+  // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel
+  // Software Developer’s Manual, Volume 1: Basic Architecture (253665-055),
+  // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume
+  // 2: System Programming (24593-3.25), 3.1.6 “RFLAGS Register”.
+  EXPECT_EQ(context.EFlags & 0xffc0802a, 2u);
+
+  // CaptureContext() doesn’t capture debug registers, so make sure they read 0.
+  EXPECT_EQ(context.Dr0, 0u);
+  EXPECT_EQ(context.Dr1, 0u);
+  EXPECT_EQ(context.Dr2, 0u);
+  EXPECT_EQ(context.Dr3, 0u);
+  EXPECT_EQ(context.Dr6, 0u);
+  EXPECT_EQ(context.Dr7, 0u);
+#endif
+
+#if defined(ARCH_CPU_X86)
+  // fxsave doesn’t write these bytes.
+  for (size_t i = 464; i < arraysize(context.ExtendedRegisters); ++i) {
+    SCOPED_TRACE(i);
+    EXPECT_EQ(context.ExtendedRegisters[i], 0);
+  }
+#elif defined(ARCH_CPU_X86_64)
+  // mxcsr shows up twice in the context structure. Make sure the values are
+  // identical.
+  EXPECT_EQ(context.FltSave.MxCsr, context.MxCsr);
+
+  // fxsave doesn’t write these bytes.
+  for (size_t i = 0; i < arraysize(context.FltSave.Reserved4); ++i) {
+    SCOPED_TRACE(i);
+    EXPECT_EQ(context.FltSave.Reserved4[i], 0);
+  }
+
+  // CaptureContext() doesn’t use these fields.
+  EXPECT_EQ(context.P1Home, 0u);
+  EXPECT_EQ(context.P2Home, 0u);
+  EXPECT_EQ(context.P3Home, 0u);
+  EXPECT_EQ(context.P4Home, 0u);
+  EXPECT_EQ(context.P5Home, 0u);
+  EXPECT_EQ(context.P6Home, 0u);
+  for (size_t i = 0; i < arraysize(context.VectorRegister); ++i) {
+    SCOPED_TRACE(i);
+    EXPECT_EQ(context.VectorRegister[i].Low, 0u);
+    EXPECT_EQ(context.VectorRegister[i].High, 0u);
+  }
+  EXPECT_EQ(context.VectorControl, 0u);
+  EXPECT_EQ(context.DebugControl, 0u);
+  EXPECT_EQ(context.LastBranchToRip, 0u);
+  EXPECT_EQ(context.LastBranchFromRip, 0u);
+  EXPECT_EQ(context.LastExceptionToRip, 0u);
+  EXPECT_EQ(context.LastExceptionFromRip, 0u);
+#endif
+}
+
+uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.Eip;
+#elif defined(ARCH_CPU_X86_64)
+  return context.Rip;
+#endif
+}
+
+uintptr_t StackPointerFromContext(const NativeCPUContext& context) {
+#if defined(ARCH_CPU_X86)
+  return context.Esp;
+#elif defined(ARCH_CPU_X86_64)
+  return context.Rsp;
+#endif
+}
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/win/capture_context.asm b/third_party/crashpad/crashpad/util/misc/capture_context_win.asm
similarity index 100%
rename from third_party/crashpad/crashpad/util/win/capture_context.asm
rename to third_party/crashpad/crashpad/util/misc/capture_context_win.asm
diff --git a/third_party/crashpad/crashpad/util/misc/elf_note_types.h b/third_party/crashpad/crashpad/util/misc/elf_note_types.h
new file mode 100644
index 0000000..77c9043
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/misc/elf_note_types.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
+#define CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
+
+// This header defines types of ELF "notes" that are embedded sections. These
+// can be read by ElfImageReader in the snapshot library, and are created in
+// client modules. All notes used by Crashpad use the name "Crashpad" and one of
+// the types defined here. Note that this file is #included into .S files, so
+// must be relatively plain (no C++ features).
+
+#define CRASHPAD_ELF_NOTE_NAME "Crashpad"
+
+// Used by ElfImageReader for testing purposes.
+#define CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST 1
+
+// Used by the client library to stash a pointer to the CrashpadInfo structure
+// for retrieval by the module snapshot. 'OFNI' == 0x4f464e49 which appears as
+// "INFO" in readelf -x.
+#define CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO 0x4f464e49
+
+#endif  // CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.cc b/third_party/crashpad/crashpad/util/misc/metrics.cc
index f4fb588..7d191f7 100644
--- a/third_party/crashpad/crashpad/util/misc/metrics.cc
+++ b/third_party/crashpad/crashpad/util/misc/metrics.cc
@@ -61,8 +61,7 @@
 }
 
 // static
-void Metrics::CrashReportSize(FileHandle file) {
-  const FileOffset size = LoggingFileSizeByHandle(file);
+void Metrics::CrashReportSize(FileOffset size) {
   UMA_HISTOGRAM_CUSTOM_COUNTS(
       "Crashpad.CrashReportSize", size, 0, 20 * 1024 * 1024, 50);
 }
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.h b/third_party/crashpad/crashpad/util/misc/metrics.h
index b4bea910..54ccb84 100644
--- a/third_party/crashpad/crashpad/util/misc/metrics.h
+++ b/third_party/crashpad/crashpad/util/misc/metrics.h
@@ -50,7 +50,7 @@
 
   //! \brief Reports the size of a crash report file in bytes. Should be called
   //!     when a new report is written to disk.
-  static void CrashReportSize(FileHandle file);
+  static void CrashReportSize(FileOffset size);
 
   //! \brief Reports on a crash upload attempt, and if it succeeded.
   static void CrashUploadAttempted(bool successful);
@@ -119,6 +119,16 @@
     //! \brief There was a database error in attempt to complete the report.
     kFinishedWritingCrashReportFailed = 7,
 
+    //! \brief An attempt to directly `ptrace` the target failed.
+    //!
+    //! This value is only used on Linux/Android.
+    kDirectPtraceFailed = 8,
+
+    //! \brief An attempt to `ptrace` via a PtraceBroker failed.
+    //!
+    //! This value is only used on Linux/Android.
+    kBrokeredPtraceFailed = 9,
+
     //! \brief The number of values in this enumeration; not a valid value.
     kMaxValue
   };
diff --git a/third_party/crashpad/crashpad/util/misc/uuid.cc b/third_party/crashpad/crashpad/util/misc/uuid.cc
index 92fba760..ffd49708 100644
--- a/third_party/crashpad/crashpad/util/misc/uuid.cc
+++ b/third_party/crashpad/crashpad/util/misc/uuid.cc
@@ -84,6 +84,10 @@
   return true;
 }
 
+bool UUID::InitializeFromString(const base::StringPiece16& string) {
+  return InitializeFromString(UTF16ToUTF8(string));
+}
+
 bool UUID::InitializeWithNew() {
 #if defined(OS_MACOSX)
   uuid_t uuid;
diff --git a/third_party/crashpad/crashpad/util/misc/uuid.h b/third_party/crashpad/crashpad/util/misc/uuid.h
index 4e5884e2..af801222 100644
--- a/third_party/crashpad/crashpad/util/misc/uuid.h
+++ b/third_party/crashpad/crashpad/util/misc/uuid.h
@@ -63,6 +63,7 @@
   //!     been initialized with the data. `false` if the string could not be
   //!     parsed, with the object state untouched.
   bool InitializeFromString(const base::StringPiece& string);
+  bool InitializeFromString(const base::StringPiece16& string);
 
   //! \brief Initializes the %UUID using a standard system facility to generate
   //!     the value.
diff --git a/third_party/crashpad/crashpad/util/misc/uuid_test.cc b/third_party/crashpad/crashpad/util/misc/uuid_test.cc
index 72b8216..c05c5c1b 100644
--- a/third_party/crashpad/crashpad/util/misc/uuid_test.cc
+++ b/third_party/crashpad/crashpad/util/misc/uuid_test.cc
@@ -214,6 +214,31 @@
   // Mixed case.
   uuid.InitializeFromString("5762C15D-50b5-4171-a2e9-7429C9EC6CAB");
   EXPECT_EQ(uuid.ToString(), "5762c15d-50b5-4171-a2e9-7429c9ec6cab");
+
+  // Test accepting a StringPiece16.
+  // clang-format off
+  static constexpr base::char16 kChar16UUID[] = {
+      'f', '3', '2', 'e', '5', 'b', 'd', 'c', '-',
+      '2', '6', '8', '1', '-',
+      '4', 'c', '7', '3', '-',
+      'a', '4', 'e', '6', '-',
+      '3', '3', '3', 'f', 'f', 'd', '3', '3', 'b', '3', '3', '3',
+  };
+  // clang-format on
+  EXPECT_TRUE(uuid.InitializeFromString(
+      base::StringPiece16(kChar16UUID, arraysize(kChar16UUID))));
+  EXPECT_EQ(uuid.ToString(), "f32e5bdc-2681-4c73-a4e6-333ffd33b333");
+
+#if defined(OS_WIN)
+  // Test accepting a StringPiece16 via L"" literals on Windows.
+  EXPECT_TRUE(
+      uuid.InitializeFromString(L"F32E5BDC-2681-4C73-A4E6-444FFD44B444"));
+  EXPECT_EQ(uuid.ToString(), "f32e5bdc-2681-4c73-a4e6-444ffd44b444");
+
+  EXPECT_TRUE(
+      uuid.InitializeFromString(L"5762C15D-50b5-4171-a2e9-5555C5EC5CAB"));
+  EXPECT_EQ(uuid.ToString(), "5762c15d-50b5-4171-a2e9-5555c5ec5cab");
+#endif  // OS_WIN
 }
 
 #if defined(OS_WIN)
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_fuchsia.cc b/third_party/crashpad/crashpad/util/net/http_transport_none.cc
similarity index 100%
rename from third_party/crashpad/crashpad/util/net/http_transport_fuchsia.cc
rename to third_party/crashpad/crashpad/util/net/http_transport_none.cc
diff --git a/third_party/crashpad/crashpad/util/posix/signals.h b/third_party/crashpad/crashpad/util/posix/signals.h
index ade093bfa..dc55059 100644
--- a/third_party/crashpad/crashpad/util/posix/signals.h
+++ b/third_party/crashpad/crashpad/util/posix/signals.h
@@ -24,6 +24,9 @@
 //! \brief Utilities for handling POSIX signals.
 class Signals {
  public:
+  //! \brief A signal number used by Crashpad to simulate signals.
+  static constexpr int kSimulatedSigno = -1;
+
   //! \brief The type used for `struct sigaction::sa_sigaction`.
   using Handler = void (*)(int, siginfo_t*, void*);
 
diff --git a/third_party/crashpad/crashpad/util/thread/stoppable.h b/third_party/crashpad/crashpad/util/thread/stoppable.h
new file mode 100644
index 0000000..e7a5127
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/thread/stoppable.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_THREAD_STOPPABLE_H_
+#define CRASHPAD_UTIL_THREAD_STOPPABLE_H_
+
+#include "base/macros.h"
+
+namespace crashpad {
+
+//! \brief An interface for operations that may be Started and Stopped.
+class Stoppable {
+ public:
+  virtual ~Stoppable() = default;
+
+  //! \brief Starts the operation.
+  virtual void Start() = 0;
+
+  //! \brief Stops the operation.
+  virtual void Stop() = 0;
+
+ protected:
+  Stoppable() = default;
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_THREAD_STOPPABLE_H_
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp
index 0000ee2..e0394e2 100644
--- a/third_party/crashpad/crashpad/util/util.gyp
+++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -73,6 +73,8 @@
         'linux/ptrace_connection.h',
         'linux/ptracer.cc',
         'linux/ptracer.h',
+        'linux/scoped_pr_set_ptracer.cc',
+        'linux/scoped_pr_set_ptracer.h',
         'linux/scoped_ptrace_attach.cc',
         'linux/scoped_ptrace_attach.h',
         'linux/thread_info.cc',
@@ -125,10 +127,15 @@
         'misc/address_types.h',
         'misc/arraysize_unsafe.h',
         'misc/as_underlying_type.h',
+        'misc/capture_context.h',
+        'misc/capture_context_linux.S',
+        'misc/capture_context_mac.S',
+        'misc/capture_context_win.asm',
         'misc/clock.h',
         'misc/clock_mac.cc',
         'misc/clock_posix.cc',
         'misc/clock_win.cc',
+        'misc/elf_note_types.h',
         'misc/from_pointer_cast.h',
         'misc/implicit_cast.h',
         'misc/initialization_state.h',
@@ -223,6 +230,7 @@
         'synchronization/semaphore_posix.cc',
         'synchronization/semaphore_win.cc',
         'synchronization/semaphore.h',
+        'thread/stoppable.h',
         'thread/thread.cc',
         'thread/thread.h',
         'thread/thread_log_messages.cc',
@@ -232,8 +240,6 @@
         'thread/worker_thread.cc',
         'thread/worker_thread.h',
         'win/address_types.h',
-        'win/capture_context.asm',
-        'win/capture_context.h',
         'win/checked_win_address_range.h',
         'win/command_line.cc',
         'win/command_line.h',
@@ -340,6 +346,8 @@
               '$(SDKROOT)/usr/lib/libbsm.dylib',
             ],
           },
+        }, { # else: OS!=mac
+          'sources!': [ 'misc/capture_context_mac.S' ],
         }],
         ['OS=="win"', {
           'link_settings': {
@@ -369,7 +377,7 @@
           ],
         }, {  # else: OS!="win"
           'sources!': [
-            'win/capture_context.asm',
+            'misc/capture_context_win.asm',
             'win/safe_terminate_process.asm',
           ],
         }],
@@ -381,6 +389,7 @@
           },
         }, {  # else: OS!="linux"
           'sources!': [
+            'misc/capture_context_linux.S',
             'net/http_transport_libcurl.cc',
           ],
         }],
@@ -394,6 +403,7 @@
         ['OS=="android"', {
           'sources/': [
             ['include', '^linux/'],
+            ['include', '^misc/capture_context_linux\\.S$'],
             ['include', '^misc/paths_linux\\.cc$'],
             ['include', '^posix/process_info_linux\\.cc$'],
             ['include', '^process/process_memory_linux\\.cc$'],
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp
index a287327..d07dc82a 100644
--- a/third_party/crashpad/crashpad/util/util_test.gyp
+++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -67,6 +67,11 @@
         'mach/symbolic_constants_mach_test.cc',
         'mach/task_memory_test.cc',
         'misc/arraysize_unsafe_test.cc',
+        'misc/capture_context_test.cc',
+        'misc/capture_context_test_util.h',
+        'misc/capture_context_test_util_linux.cc',
+        'misc/capture_context_test_util_mac.cc',
+        'misc/capture_context_test_util_win.cc',
         'misc/clock_test.cc',
         'misc/from_pointer_cast_test.cc',
         'misc/initialization_state_dcheck_test.cc',
@@ -105,7 +110,6 @@
         'thread/thread_log_messages_test.cc',
         'thread/thread_test.cc',
         'thread/worker_thread_test.cc',
-        'win/capture_context_test.cc',
         'win/command_line_test.cc',
         'win/critical_section_with_debug_info_test.cc',
         'win/exception_handler_server_test.cc',
@@ -156,6 +160,7 @@
         ['OS=="android"', {
           'sources/': [
             ['include', '^linux/'],
+            ['include', '^misc/capture_context_test_util_linux\\.cc$'],
           ],
         }],
       ],
diff --git a/third_party/crashpad/crashpad/util/win/capture_context.h b/third_party/crashpad/crashpad/util/win/capture_context.h
deleted file mode 100644
index 2f501f8..0000000
--- a/third_party/crashpad/crashpad/util/win/capture_context.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CRASHPAD_CLIENT_CAPTURE_CONTEXT_WIN_H_
-#define CRASHPAD_CLIENT_CAPTURE_CONTEXT_WIN_H_
-
-#include <windows.h>
-
-namespace crashpad {
-
-//! \brief Saves the CPU context.
-//!
-//! The CPU context will be captured as accurately and completely as possible,
-//! containing an atomic snapshot at the point of this function’s return. This
-//! function does not modify any registers.
-//!
-//! This function captures all integer registers as well as the floating-point
-//! and vector (SSE) state. It does not capture debug registers, which are
-//! inaccessible by user code.
-//!
-//! This function is a replacement for `RtlCaptureContext()`, which contains
-//! bugs and limitations. On 32-bit x86, `RtlCaptureContext()` requires that
-//! `ebp` be used as a frame pointer, and returns `ebp`, `esp`, and `eip` out of
-//! sync with the other registers. Both the 32-bit x86 and 64-bit x86_64
-//! versions of `RtlCaptureContext()` capture only the state of the integer
-//! registers, ignoring floating-point and vector state.
-//!
-//! \param[out] context The structure to store the context in.
-//!
-//! \note On x86_64, the value for `rcx` will be populated with the address of
-//!     this function’s argument, as mandated by the ABI.
-void CaptureContext(CONTEXT* context);
-
-}  // namespace crashpad
-
-#endif  // CRASHPAD_CLIENT_CAPTURE_CONTEXT_WIN_H_
diff --git a/third_party/crashpad/crashpad/util/win/capture_context_test.cc b/third_party/crashpad/crashpad/util/win/capture_context_test.cc
deleted file mode 100644
index 292e4749..0000000
--- a/third_party/crashpad/crashpad/util/win/capture_context_test.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2015 The Crashpad Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "util/win/capture_context.h"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "gtest/gtest.h"
-
-namespace crashpad {
-namespace test {
-namespace {
-
-// If the context structure has fields that tell whether it’s valid, such as
-// magic numbers or size fields, sanity-checks those fields for validity with
-// fatal gtest assertions. For other fields, where it’s possible to reason about
-// their validity based solely on their contents, sanity-checks via nonfatal
-// gtest assertions.
-void SanityCheckContext(const CONTEXT& context) {
-#if defined(ARCH_CPU_X86)
-  constexpr uint32_t must_have = CONTEXT_i386 |
-                                 CONTEXT_CONTROL |
-                                 CONTEXT_INTEGER |
-                                 CONTEXT_SEGMENTS |
-                                 CONTEXT_FLOATING_POINT;
-  ASSERT_EQ(context.ContextFlags & must_have, must_have);
-  constexpr uint32_t may_have = CONTEXT_EXTENDED_REGISTERS;
-  ASSERT_EQ(context.ContextFlags & ~(must_have | may_have), 0u);
-#elif defined(ARCH_CPU_X86_64)
-  ASSERT_EQ(context.ContextFlags,
-            static_cast<DWORD>(CONTEXT_AMD64 | CONTEXT_CONTROL |
-                CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT));
-#endif
-
-#if defined(ARCH_CPU_X86_FAMILY)
-  // Many bit positions in the flags register are reserved and will always read
-  // a known value. Most reserved bits are always 0, but bit 1 is always 1.
-  // Check that the reserved bits are all set to their expected values. Note
-  // that the set of reserved bits may be relaxed over time with newer CPUs, and
-  // that this test may need to be changed to reflect these developments. The
-  // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel
-  // Software Developer’s Manual, Volume 1: Basic Architecture (253665-055),
-  // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume
-  // 2: System Programming (24593-3.25), 3.1.6 “RFLAGS Register”.
-  EXPECT_EQ(context.EFlags & 0xffc0802a, 2u);
-
-  // CaptureContext() doesn’t capture debug registers, so make sure they read 0.
-  EXPECT_EQ(context.Dr0, 0u);
-  EXPECT_EQ(context.Dr1, 0u);
-  EXPECT_EQ(context.Dr2, 0u);
-  EXPECT_EQ(context.Dr3, 0u);
-  EXPECT_EQ(context.Dr6, 0u);
-  EXPECT_EQ(context.Dr7, 0u);
-#endif
-
-#if defined(ARCH_CPU_X86)
-  // fxsave doesn’t write these bytes.
-  for (size_t i = 464; i < arraysize(context.ExtendedRegisters); ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_EQ(context.ExtendedRegisters[i], 0);
-  }
-#elif defined(ARCH_CPU_X86_64)
-  // mxcsr shows up twice in the context structure. Make sure the values are
-  // identical.
-  EXPECT_EQ(context.FltSave.MxCsr, context.MxCsr);
-
-  // fxsave doesn’t write these bytes.
-  for (size_t i = 0; i < arraysize(context.FltSave.Reserved4); ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_EQ(context.FltSave.Reserved4[i], 0);
-  }
-
-  // CaptureContext() doesn’t use these fields.
-  EXPECT_EQ(context.P1Home, 0u);
-  EXPECT_EQ(context.P2Home, 0u);
-  EXPECT_EQ(context.P3Home, 0u);
-  EXPECT_EQ(context.P4Home, 0u);
-  EXPECT_EQ(context.P5Home, 0u);
-  EXPECT_EQ(context.P6Home, 0u);
-  for (size_t i = 0; i < arraysize(context.VectorRegister); ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_EQ(context.VectorRegister[i].Low, 0u);
-    EXPECT_EQ(context.VectorRegister[i].High, 0u);
-  }
-  EXPECT_EQ(context.VectorControl, 0u);
-  EXPECT_EQ(context.DebugControl, 0u);
-  EXPECT_EQ(context.LastBranchToRip, 0u);
-  EXPECT_EQ(context.LastBranchFromRip, 0u);
-  EXPECT_EQ(context.LastExceptionToRip, 0u);
-  EXPECT_EQ(context.LastExceptionFromRip, 0u);
-#endif
-}
-
-// A CPU-independent function to return the program counter.
-uintptr_t ProgramCounterFromContext(const CONTEXT& context) {
-#if defined(ARCH_CPU_X86)
-  return context.Eip;
-#elif defined(ARCH_CPU_X86_64)
-  return context.Rip;
-#endif
-}
-
-// A CPU-independent function to return the stack pointer.
-uintptr_t StackPointerFromContext(const CONTEXT& context) {
-#if defined(ARCH_CPU_X86)
-  return context.Esp;
-#elif defined(ARCH_CPU_X86_64)
-  return context.Rsp;
-#endif
-}
-
-void TestCaptureContext() {
-  CONTEXT context_1;
-  CaptureContext(&context_1);
-
-  {
-    SCOPED_TRACE("context_1");
-    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1));
-  }
-
-  // The program counter reference value is this function’s address. The
-  // captured program counter should be slightly greater than or equal to the
-  // reference program counter.
-  uintptr_t pc = ProgramCounterFromContext(context_1);
-
-  // Declare sp and context_2 here because all local variables need to be
-  // declared before computing the stack pointer reference value, so that the
-  // reference value can be the lowest value possible.
-  uintptr_t sp;
-  CONTEXT context_2;
-
-  // The stack pointer reference value is the lowest address of a local variable
-  // in this function. The captured program counter will be slightly less than
-  // or equal to the reference stack pointer.
-  const uintptr_t kReferenceSP =
-      std::min(std::min(reinterpret_cast<uintptr_t>(&context_1),
-                        reinterpret_cast<uintptr_t>(&context_2)),
-               std::min(reinterpret_cast<uintptr_t>(&pc),
-                        reinterpret_cast<uintptr_t>(&sp)));
-  sp = StackPointerFromContext(context_1);
-  EXPECT_LT(kReferenceSP - sp, 512u);
-
-  // Capture the context again, expecting that the stack pointer stays the same
-  // and the program counter increases. Strictly speaking, there’s no guarantee
-  // that these conditions will hold, although they do for known compilers even
-  // under typical optimization.
-  CaptureContext(&context_2);
-
-  {
-    SCOPED_TRACE("context_2");
-    ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2));
-  }
-
-  EXPECT_EQ(StackPointerFromContext(context_2), sp);
-  EXPECT_GT(ProgramCounterFromContext(context_2), pc);
-}
-
-TEST(CaptureContextWin, CaptureContext) {
-  ASSERT_NO_FATAL_FAILURE(TestCaptureContext());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace crashpad
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc
index 78a96b2..caf7461 100644
--- a/third_party/leveldatabase/env_chromium.cc
+++ b/third_party/leveldatabase/env_chromium.cc
@@ -532,7 +532,7 @@
 
 Options::Options() {
 // Note: Ensure that these default values correspond to those in
-// components/leveldb/public/interfaces/leveldb.mojom.
+// components/services/leveldb/public/interfaces/leveldb.mojom.
 // TODO(cmumford) Create struct-trait for leveldb.mojom.OpenOptions to force
 // users to pass in a leveldb_env::Options instance (and it's defaults).
 //
diff --git a/tools/bisect_repackage/bisect_repackage.py b/tools/bisect_repackage/bisect_repackage.py
index 22b1bfb..77e91e6 100644
--- a/tools/bisect_repackage/bisect_repackage.py
+++ b/tools/bisect_repackage/bisect_repackage.py
@@ -46,7 +46,6 @@
         'default_apps/',
         'icudtl.dat',
         'libclearkeycdm.so',
-        'libclearkeycdmadapter.so',
         'libwidevinecdm.so',
         'libwidevinecdmadapter.so',
         'locales/',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f5d2c6d..2eedbc8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -7414,6 +7414,8 @@
   <int value="5" label="kPrepareNewCrashReportFailed"/>
   <int value="6" label="kMinidumpWriteFailed"/>
   <int value="7" label="kFinishWritingCrashReportFailed"/>
+  <int value="8" label="kDirectPtraceFailed"/>
+  <int value="9" label="kBrokeredPtraceFailed"/>
 </enum>
 
 <enum name="CrashpadExceptionProcessingState">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 906d4b2..f725102 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -48508,7 +48508,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>The time from the connection start to connection establish.</summary>
 </histogram>
 
@@ -48518,7 +48517,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>The time waiting to be ready to start connecting.</summary>
 </histogram>
 
@@ -48529,7 +48527,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Each bucket is the number of connection type of socket stream.
   </summary>
@@ -48542,7 +48539,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>The time a socket stream was open.</summary>
 </histogram>
 
@@ -48552,7 +48548,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Each bucket is the number of protocol type on socket stream.
   </summary>
@@ -48564,7 +48559,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>Number of bytes on a socket stream.</summary>
 </histogram>
 
@@ -48574,7 +48568,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>Number of reads on a socket stream.</summary>
 </histogram>
 
@@ -48584,7 +48577,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>Number of bytes on a socket stream.</summary>
 </histogram>
 
@@ -48594,7 +48586,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>Number of Write on a socket stream.</summary>
 </histogram>
 
@@ -50131,7 +50122,6 @@
     enum="WebSocketNewPerMessageDeflateContextTakeoverMode">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of WebSockets that accepted permessage-deflate extension
     for each context take over mode. Used by the new Chromium-based WebSocket
@@ -50142,7 +50132,6 @@
 <histogram name="Net.WebSocket.Duration" units="ms">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     The time from a WebSocket is successfully opened until it's closed. Used to
     study how WebSockets are used.
@@ -50152,7 +50141,6 @@
 <histogram name="Net.WebSocket.ErrorCodes" enum="NetErrorCodes">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Positive net error codes that WebSockets end with, including OK and ABORTED.
   </summary>
@@ -50162,7 +50150,6 @@
     enum="WebSocketNewHandshakeResult">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Results of WebSocket handshakes. Use this histogram as a baseline for
     investigating feature usage counters.
@@ -50172,7 +50159,6 @@
 <histogram name="Net.WebSocket.ResponseCode" enum="HttpResponseCode">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>All HTTP status codes seen during WebSocket handshakes.</summary>
 </histogram>
 
@@ -99981,7 +99967,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of changes to WebSocket.binaryType after the connection
     opened, per connection. Assignments that match the existing binaryType are
@@ -99999,7 +99984,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of WebSocket handshake for each result. Use this histogram
     as a baseline for investigating feature usage counters.
@@ -100009,7 +99993,6 @@
 <histogram name="WebCore.WebSocket.MessageSize.Receive" units="bytes">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     The sizes of binary WebSocket messages received, broken down by type. One
     entry per message. Clamped to 100 MB.
@@ -100019,7 +100002,6 @@
 <histogram name="WebCore.WebSocket.MessageSize.Send" units="bytes">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     The sizes of binary WebSocket messages sent, broken down by type. One entry
     per message. Clamped to 100 MB.
@@ -100034,7 +100016,6 @@
   </obsolete>
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of WebSockets that accepted permessage-deflate extension
     for each context take over mode. Used by the old Blink-based WebSocket
@@ -100045,7 +100026,6 @@
 <histogram name="WebCore.WebSocket.ReceiveType" enum="WebSocketReceiveType">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of messages for each message type and set binary type.
   </summary>
@@ -100054,7 +100034,6 @@
 <histogram name="WebCore.WebSocket.SendType" enum="WebSocketSendType">
   <owner>yhirano@chromium.org</owner>
   <owner>ricea@chromium.org</owner>
-  <owner>tyoshino@chromium.org</owner>
   <summary>
     Count the number of send() method calls on WebSockets for each argument
     type.
@@ -100069,7 +100048,6 @@
     The support for ArrayBuffer was un-deprecated in the WHATWG spec for XHR,
     and subsequently un-deprecated in Blink.
   </obsolete>
-  <owner>tyoshino@chromium.org</owner>
   <owner>costan@gmail.com</owner>
   <summary>
     Count the number of XHR.send() calls for each argument type to see when we
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py
index 2e626ae..16eec51 100755
--- a/tools/perf/core/results_dashboard.py
+++ b/tools/perf/core/results_dashboard.py
@@ -32,6 +32,21 @@
 CACHE_DIR = 'results_dashboard'
 CACHE_FILENAME = 'results_to_retry'
 
+ERROR_NO_OAUTH_TOKEN = (
+    'No oauth token provided, cannot upload HistogramSet. Discarding.')
+
+
+class SendResultException(Exception):
+  pass
+
+
+class SendResultsRetryException(SendResultException):
+  pass
+
+
+class SendResultsFatalException(SendResultException):
+  pass
+
 
 def SendResults(data, url, tmp_dir, json_url_file=None,
                 send_as_histograms=False, oauth_token=None):
@@ -73,8 +88,6 @@
   for error in errors:
     print error
   if fatal_error:
-    print 'Error uploading to dashboard.'
-    print '@@@STEP_EXCEPTION@@@'
     return False
   return True
 
@@ -134,25 +147,20 @@
       errors.append('Could not parse JSON: %s' % line)
       continue
 
-    if is_histogramset:
-      # TODO(eakuefner): Remove this discard logic once all bots use histograms.
-      if oauth_token is None:
-        print 'No oauth token provided, cannot upload HistogramSet. Discarding.'
-        fatal_error = True
-        break
-      error = _SendHistogramJson(url, json.dumps(data), oauth_token)
-    else:
-      error = _SendResultsJson(url, json.dumps(data))
+    data_type = ('histogram' if is_histogramset else 'chartjson')
 
-    # If the dashboard returned an error, we will re-try next time.
-    if error:
-      if 'HTTPError: 400' in error:
-        # If the remote app rejects the JSON, it's probably malformed,
-        # so we don't want to retry it.
-        print 'Discarding JSON, error:\n%s' % error
-        fatal_error = True
-        break
+    try:
+      if is_histogramset:
+        # TODO(eakuefner): Remove this discard logic once all bots use
+        # histograms.
+        if oauth_token is None:
+          raise SendResultsFatalException(ERROR_NO_OAUTH_TOKEN)
 
+        _SendHistogramJson(url, json.dumps(data), oauth_token)
+      else:
+        _SendResultsJson(url, json.dumps(data))
+    except SendResultsRetryException as e:
+      error = 'Error while uploading %s data: %s' % (data_type, str(e))
       if index != len(cache_lines) - 1:
         # The very last item in the cache_lines list is the new results line.
         # If this line is not the new results line, then this results line
@@ -163,6 +171,17 @@
       lines_to_retry = [l.strip() for l in cache_lines[index:] if l.strip()]
       errors.append(error)
       break
+    except SendResultsFatalException as e:
+      error = 'Error uploading %s data: %s' % (data_type, str(e))
+      errors.append(error)
+      fatal_error = True
+      break
+    except Exception:
+      error = 'Unexpected error while uploading %s data: %s' % (
+          data_type, traceback.format_exc())
+      errors.append(error)
+      fatal_error = True
+      break
 
   # Write any failing requests to the cache file.
   cache = open(cache_file_name, 'wb')
@@ -471,8 +490,13 @@
   try:
     urllib2.urlopen(req)
   except (urllib2.HTTPError, urllib2.URLError, httplib.HTTPException):
-    return traceback.format_exc()
-  return None
+    error = traceback.format_exc()
+
+    if 'HTTPError: 400' in error:
+      # If the remote app rejects the JSON, it's probably malformed,
+      # so we don't want to retry it.
+      raise SendResultsFatalException('Discarding JSON, error:\n%s' % error)
+    raise SendResultsRetryException()
 
 def _Httplib2Request(url, data, oauth_token):
   data = urllib.urlencode({'data': data})
@@ -498,14 +522,19 @@
     None if successful, or an error string if there were errors.
   """
   try:
-    _, content = _Httplib2Request(url, histogramset_json, oauth_token)
-    result = json.loads(content) or {}
-    error = result.get('error')
-    if error is not None:
-      return 'HTTP error: %s\n' % error
-  except (httplib2.HttpLib2Error, ValueError):
-    return traceback.format_exc()
-  return None
+    response, _ = _Httplib2Request(url, histogramset_json, oauth_token)
+
+    # A 500 is presented on an exception on the dashboard side, timeout,
+    # exception, etc. The dashboard can also send back 400 and 403, we could
+    # recover from 403 (auth error), but 400 is generally malformed data.
+    if response.status == 403:
+      raise SendResultsRetryException(traceback.format_exc())
+
+    if response.status != 200:
+      raise SendResultsFatalException('HTTP Response %d: %s' % (
+          response.status, response.reason))
+  except httplib2.HttpLib2Error:
+    raise SendResultsRetryException(traceback.format_exc())
 
 def _DashboardUrl(url, data):
   """Returns link to the dashboard if possible.
diff --git a/tools/perf/core/upload_results_to_perf_dashboard.py b/tools/perf/core/upload_results_to_perf_dashboard.py
index db7b06b..00cd771a 100755
--- a/tools/perf/core/upload_results_to_perf_dashboard.py
+++ b/tools/perf/core/upload_results_to_perf_dashboard.py
@@ -137,7 +137,8 @@
   if dashboard_json:
     if options.output_json_file:
       with open(options.output_json_file, 'w') as output_file:
-        json.dump(dashboard_json, output_file)
+        json.dump(dashboard_json, output_file,
+            indent=4, separators=(',', ': '))
     if not results_dashboard.SendResults(
         dashboard_json,
         options.results_url,
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 6ac39ab..ac0e4ef8 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -36,6 +36,7 @@
  <item id="cast_socket" hash_code="115192205" type="0" content_hash_code="63056899" os_list="linux,windows" file_path="components/cast_channel/cast_socket.cc"/>
  <item id="cast_udp_socket" hash_code="22573197" type="0" content_hash_code="75328301" os_list="linux,windows" file_path="media/cast/net/udp_socket_client.cc"/>
  <item id="cast_udp_transport" hash_code="5576536" type="0" content_hash_code="107643273" os_list="linux,windows" file_path="media/cast/net/udp_transport_impl.cc"/>
+ <item id="certificate_reporting_service_test" hash_code="98123372" type="0" content_hash_code="136253658" os_list="linux,windows" file_path="chrome/browser/safe_browsing/certificate_reporting_service.cc"/>
  <item id="certificate_verifier" hash_code="113553577" type="0" content_hash_code="62346354" os_list="linux,windows" file_path="net/cert_net/cert_net_fetcher_impl.cc"/>
  <item id="chrome_apps_socket_api" hash_code="8591273" type="0" content_hash_code="70868355" os_list="linux,windows" file_path="extensions/browser/api/socket/socket.cc"/>
  <item id="chrome_cleaner" hash_code="27071967" type="0" content_hash_code="111240292" os_list="windows" file_path="chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc"/>
@@ -177,8 +178,9 @@
  <item id="privet_http_impl" hash_code="71251498" type="0" content_hash_code="107348604" os_list="linux,windows" file_path="chrome/browser/printing/cloud_print/privet_http_impl.cc"/>
  <item id="profile_avatar" hash_code="51164680" type="0" content_hash_code="113550845" os_list="linux,windows" file_path="chrome/browser/profiles/profile_avatar_downloader.cc"/>
  <item id="profile_resetter_upload" hash_code="105330607" type="0" content_hash_code="129329171" os_list="linux,windows" file_path="chrome/browser/profile_resetter/reset_report_uploader.cc"/>
- <item id="proxy_config_direct" hash_code="119015679" type="0" content_hash_code="131944978" os_list="linux,windows" file_path="net/proxy_resolution/proxy_config_with_annotation.cc"/>
- <item id="proxy_config_settings" hash_code="136468456" type="0" content_hash_code="136747792" os_list="linux,windows" file_path="components/proxy_config/pref_proxy_config_tracker_impl.cc"/>
+ <item id="proxy_config_direct" hash_code="119015679" type="0" content_hash_code="119931568" os_list="linux,windows" file_path="net/proxy_resolution/proxy_config_with_annotation.cc"/>
+ <item id="proxy_config_headless" hash_code="133221587" type="0" content_hash_code="77459277" os_list="linux,windows" file_path="headless/lib/browser/headless_url_request_context_getter.cc"/>
+ <item id="proxy_config_settings" hash_code="136468456" type="0" content_hash_code="19527377" os_list="linux,windows" file_path="components/proxy_config/pref_proxy_config_tracker_impl.cc"/>
  <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="linux,windows" file_path="net/proxy_resolution/pac_file_fetcher_impl.cc"/>
  <item id="puch_client_channel" hash_code="34459548" type="0" content_hash_code="92475475" os_list="linux,windows" file_path="components/invalidation/impl/push_client_channel.cc"/>
  <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_client_session.cc"/>
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 98adab0f..b5c83d4 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -300,6 +300,7 @@
       search_model_->search_box();
   search_box()->set_placeholder_text(search_box_model->hint_text());
   search_box()->SetAccessibleName(search_box_model->accessible_name());
+  SchedulePaint();
 }
 
 void SearchBoxView::SelectionModelChanged() {
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
index d649232f..ae9abce 100644
--- a/ui/events/event_rewriter_unittest.cc
+++ b/ui/events/event_rewriter_unittest.cc
@@ -11,28 +11,14 @@
 
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/events/test/test_event_processor.h"
 
 namespace ui {
 
 namespace {
 
-// To test the handling of |EventRewriter|s through |EventSource|,
-// we rewrite and test event types.
-class TestEvent : public Event {
- public:
-  explicit TestEvent(EventType type)
-      : Event(type, base::TimeTicks(), 0), unique_id_(next_unique_id_++) {}
-  ~TestEvent() override {}
-  int unique_id() const { return unique_id_; }
-
- private:
-  static int next_unique_id_;
-  int unique_id_;
-};
-
-int TestEvent::next_unique_id_ = 0;
-
 // TestEventRewriteProcessor is set up with a sequence of event types,
 // and fails if the events received via OnEventFromSource() do not match
 // this sequence. These expected event types are consumed on receipt.
@@ -58,6 +44,28 @@
   DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor);
 };
 
+std::unique_ptr<Event> CreateEventForType(EventType type) {
+  switch (type) {
+    case ET_CANCEL_MODE:
+      return std::make_unique<CancelModeEvent>();
+    case ET_MOUSE_DRAGGED:
+    case ET_MOUSE_PRESSED:
+    case ET_MOUSE_RELEASED:
+      return std::make_unique<MouseEvent>(type, gfx::Point(), gfx::Point(),
+                                          base::TimeTicks::Now(), 0, 0);
+    case ET_KEY_PRESSED:
+    case ET_KEY_RELEASED:
+      return std::make_unique<KeyEvent>(type, ui::VKEY_TAB, DomCode::NONE, 0);
+    case ET_SCROLL_FLING_CANCEL:
+    case ET_SCROLL_FLING_START:
+      return std::make_unique<ScrollEvent>(
+          type, gfx::Point(), base::TimeTicks::Now(), 0, 0, 0, 0, 0, 0);
+    default:
+      NOTREACHED() << type;
+      return nullptr;
+  }
+}
+
 // Trivial EventSource that does nothing but send events.
 class TestEventRewriteSource : public EventSource {
  public:
@@ -65,7 +73,7 @@
       : processor_(processor) {}
   EventProcessor* GetEventSink() override { return processor_; }
   void Send(EventType type) {
-    std::unique_ptr<Event> event(new TestEvent(type));
+    auto event = CreateEventForType(type);
     SendEventToSink(event.get());
   }
 
@@ -88,7 +96,7 @@
       const Event& event,
       std::unique_ptr<Event>* rewritten_event) override {
     if (status_ == EVENT_REWRITE_REWRITTEN)
-      rewritten_event->reset(new TestEvent(type_));
+      *rewritten_event = CreateEventForType(type_);
     return status_;
   }
   EventRewriteStatus NextDispatchEvent(
@@ -123,10 +131,10 @@
       return EVENT_REWRITE_CONTINUE;
     if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
         (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) {
-      last_rewritten_event_ = new TestEvent(find->second.type);
-      rewritten_event->reset(last_rewritten_event_);
+      *rewritten_event = CreateEventForType(find->second.type);
+      last_rewritten_event_ = rewritten_event->get();
     } else {
-      last_rewritten_event_ = 0;
+      last_rewritten_event_ = nullptr;
     }
     state_ = find->second.state;
     return find->second.status;
@@ -135,10 +143,8 @@
       const Event& last_event,
       std::unique_ptr<Event>* new_event) override {
     EXPECT_TRUE(last_rewritten_event_);
-    const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event);
-    EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id());
-    const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get());
-    EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id());
+    EXPECT_EQ(last_rewritten_event_, &last_event);
+    EXPECT_FALSE(new_event->get() && new_event->get() == &last_event);
     return RewriteEvent(last_event, new_event);
   }
 
@@ -151,7 +157,7 @@
   };
   typedef std::map<RewriteCase, RewriteResult> RewriteRules;
   RewriteRules rules_;
-  TestEvent* last_rewritten_event_;
+  Event* last_rewritten_event_;
   int state_;
 };
 
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc
index fcdffe5d..e45be7c 100644
--- a/ui/events/event_source.cc
+++ b/ui/events/event_source.cc
@@ -11,6 +11,17 @@
 #include "ui/events/event_sink.h"
 
 namespace ui {
+namespace {
+
+bool IsLocatedEventWithDifferentLocations(const Event& event) {
+  if (!event.IsLocatedEvent())
+    return false;
+  const LocatedEvent* located_event = event.AsLocatedEvent();
+  return located_event->target() &&
+         located_event->location_f() != located_event->root_location_f();
+}
+
+}  // namespace
 
 EventSource::EventSource() {}
 
@@ -30,12 +41,23 @@
 }
 
 EventDispatchDetails EventSource::SendEventToSink(Event* event) {
+  std::unique_ptr<ui::Event> event_for_rewriting_ptr;
+  Event* event_for_rewriting = event;
+  if (!rewriter_list_.empty() && IsLocatedEventWithDifferentLocations(*event)) {
+    // EventRewriters don't expect an event with differing location and
+    // root-location (because they don't honor the target). Provide such an
+    // event for rewriters.
+    event_for_rewriting_ptr = ui::Event::Clone(*event);
+    event_for_rewriting_ptr->AsLocatedEvent()->set_location_f(
+        event_for_rewriting_ptr->AsLocatedEvent()->root_location_f());
+    event_for_rewriting = event_for_rewriting_ptr.get();
+  }
   std::unique_ptr<Event> rewritten_event;
   EventRewriteStatus status = EVENT_REWRITE_CONTINUE;
   EventRewriterList::const_iterator it = rewriter_list_.begin(),
                                     end = rewriter_list_.end();
   for (; it != end; ++it) {
-    status = (*it)->RewriteEvent(*event, &rewritten_event);
+    status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event);
     if (status == EVENT_REWRITE_DISCARD) {
       CHECK(!rewritten_event);
       return EventDispatchDetails();
diff --git a/ui/gfx/skia_paint_util.cc b/ui/gfx/skia_paint_util.cc
index df9dcded..83753af 100644
--- a/ui/gfx/skia_paint_util.cc
+++ b/ui/gfx/skia_paint_util.cc
@@ -7,7 +7,7 @@
 #include "base/memory/ptr_util.h"
 #include "cc/paint/paint_image_builder.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
+#include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
 #include "ui/gfx/image/image_skia_rep.h"
@@ -87,11 +87,10 @@
                            SkIntToScalar(shadow.y()));
 
     SkPaint* paint = looper_builder.addLayer(layer_info);
-    // SkBlurMaskFilter's blur radius defines the range to extend the blur from
+    // Skia's blur radius defines the range to extend the blur from
     // original mask, which is half of blur amount as defined in ShadowValue.
-    paint->setMaskFilter(SkBlurMaskFilter::Make(
-        kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2),
-        SkBlurMaskFilter::kHighQuality_BlurFlag));
+    paint->setMaskFilter(SkMaskFilter::MakeBlur(
+        kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2)));
     paint->setColorFilter(
         SkColorFilter::MakeModeFilter(shadow.color(), SkBlendMode::kSrcIn));
   }
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc
index 2fbae691..db2856f 100644
--- a/ui/gfx/skia_util.cc
+++ b/ui/gfx/skia_util.cc
@@ -12,7 +12,6 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColorPriv.h"
 #include "third_party/skia/include/core/SkUnPreMultiply.h"
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "third_party/skia/include/effects/SkLayerDrawLooper.h"
 #include "ui/gfx/geometry/quad_f.h"
diff --git a/ui/ozone/platform/wayland/fake_server.cc b/ui/ozone/platform/wayland/fake_server.cc
index 6a34b6a..7eae750 100644
--- a/ui/ozone/platform/wayland/fake_server.cc
+++ b/ui/ozone/platform/wayland/fake_server.cc
@@ -356,26 +356,31 @@
   obj->resource_ = nullptr;
 }
 
+template <class T>
+void SetImplementation(wl_resource* resource,
+                       const void* implementation,
+                       T* user_data) {
+  wl_resource_set_implementation(resource, implementation, user_data,
+                                 &ServerObject::OnResourceDestroyed);
+}
+
 MockXdgSurface::MockXdgSurface(wl_resource* resource,
                                const void* implementation)
     : ServerObject(resource) {
-  wl_resource_set_implementation(resource, implementation, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, implementation, this);
 }
 
 MockXdgSurface::~MockXdgSurface() {}
 
 MockXdgTopLevel::MockXdgTopLevel(wl_resource* resource)
     : MockXdgSurface(resource, &zxdg_surface_v6_impl) {
-  wl_resource_set_implementation(resource, &zxdg_toplevel_v6_impl, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, &zxdg_toplevel_v6_impl, this);
 }
 
 MockXdgTopLevel::~MockXdgTopLevel() {}
 
 MockSurface::MockSurface(wl_resource* resource) : ServerObject(resource) {
-  wl_resource_set_implementation(resource, &surface_impl, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, &surface_impl, this);
 }
 
 MockSurface::~MockSurface() {
@@ -390,22 +395,19 @@
 }
 
 MockPointer::MockPointer(wl_resource* resource) : ServerObject(resource) {
-  wl_resource_set_implementation(resource, &pointer_impl, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, &pointer_impl, this);
 }
 
 MockPointer::~MockPointer() {}
 
 MockKeyboard::MockKeyboard(wl_resource* resource) : ServerObject(resource) {
-  wl_resource_set_implementation(resource, &keyboard_impl, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, &keyboard_impl, this);
 }
 
 MockKeyboard::~MockKeyboard() {}
 
 MockTouch::MockTouch(wl_resource* resource) : ServerObject(resource) {
-  wl_resource_set_implementation(resource, &touch_impl, this,
-                                 &ServerObject::OnResourceDestroyed);
+  SetImplementation(resource, &touch_impl, this);
 }
 
 MockTouch::~MockTouch() {}
@@ -442,8 +444,7 @@
   }
   if (!global->resource_)
     global->resource_ = resource;
-  wl_resource_set_implementation(resource, global->implementation_, global,
-                                 &Global::OnResourceDestroyed);
+  SetImplementation(resource, global->implementation_, global);
   global->OnBind();
 }
 
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc
index fcafd03..5f577fd3 100644
--- a/url/run_all_unittests.cc
+++ b/url/run_all_unittests.cc
@@ -24,5 +24,5 @@
 
   return base::LaunchUnitTests(
       argc, argv,
-      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
+      base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
 }