diff --git a/DEPS b/DEPS
index e0155b37..278523d1 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '8ef78eae93114236b6eea4f525ea8cb9570da1e1',
+  'skia_revision': '083bc1576a0e3e214496be9d8803e4bd6ba0b45d',
   # 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': '6d7c52f868ecedb5e6ca0ac3da5917fcadb9c108',
+  'v8_revision': '4b7de4a5360c971058b3b1bbb410fcedcb93f450',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '624fbdcf55b017215693a1817d89d3e9f1ea5af1',
+  'angle_revision': 'd082819ca2ad1cadafc2cb261212ee064124a8cc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '2b4d11c0f13384ede1954c56264acd5da176465c',
+  'pdfium_revision': 'e8b02fb54234ed66eeab30927b4495ecc9ca1669',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -165,7 +165,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '69f64b27039708e61e1e9ce5d3a580235c667332',
+  'catapult_revision': '2ba11d1c2b02d6c962975c7bb1e20ab49d159008',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -655,7 +655,7 @@
   },
 
   'src/third_party/ffmpeg':
-    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'bbe6b81a6c310d4931cc8a5164d1a374652e054a',
+    Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '458e9fd3f8e8c913a739389c65dfaf1f77ee9106',
 
   'src/third_party/flac':
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@@ -853,7 +853,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '3448987ab20aa05716ffc4aedf6d02e23f75920b',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '2beb5c9f91e7166c2c9d01c94bf84767815121e4',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + '01c1d1d76f139345c442bfc8e61b4e1cba809059',
@@ -1106,7 +1106,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '5f45e6651864ffc14a5adfc64d8c5248e123d1a4',
+    Var('webrtc_git') + '/src.git' + '@' + '957c62e0d63eca6ac8b6c77d0391675d33fa0fe8',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1137,7 +1137,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1b448050d611114d6afbab145368ba3248f9234e',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@421d954080fe05338595cbc6712f9d9a5918af1f',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
index 22a7f12..1e4419a 100644
--- a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
+++ b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
@@ -17,6 +17,7 @@
 
 # web payments api not enabled in webiew, crbug.com/667069
 interface PaymentAddress
+interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent
 interface PaymentRequest : EventTarget
 interface PaymentRequestUpdateEvent : Event
 interface PaymentResponse : EventTarget
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 13b97a9..b493d5b 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1385,6 +1385,7 @@
     "//gpu/command_buffer/client:gles2_interface",
     "//media",
     "//net",
+    "//services/content/public/cpp",
     "//services/data_decoder/public/cpp",
     "//services/preferences/public/cpp",
     "//services/service_manager/public/cpp",
@@ -1392,6 +1393,7 @@
     "//services/ws/public/cpp/host",
     "//services/ws/public/cpp/input_devices:input_device_controller",
     "//services/ws/public/mojom/input_devices",
+    "//services/ws/remote_view_host",
 
     # TODO(msw): Remove this; only ash_with_content should depend on webkit.
     "//ash/app_list/presenter",
diff --git a/ash/DEPS b/ash/DEPS
index 9b2c422..9b22df7 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -28,6 +28,7 @@
   "+mash/shelf/public",
   "+mojo/public",
   "+services/catalog/public",
+  "+services/content/public",
   "+services/preferences/public",
   "+services/service_manager/embedder",
   "+services/service_manager/public",
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 9e15ccc..971806b9 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -1099,7 +1099,9 @@
       if (event->location().y() < kAppListHomeLaucherGesturesThreshold) {
         if (delegate_->ProcessHomeLauncherGesture(event->type(),
                                                   gfx::Point())) {
+          SetIsInDrag(false);
           event->SetHandled();
+          HandleClickOrTap(event);
           return;
         }
       }
@@ -1122,6 +1124,7 @@
       views::View::ConvertPointToScreen(this, &location_in_screen);
       if (delegate_->ProcessHomeLauncherGesture(event->type(),
                                                 location_in_screen)) {
+        SetIsInDrag(true);
         event->SetHandled();
         return;
       }
@@ -1140,6 +1143,7 @@
       views::View::ConvertPointToScreen(this, &location_in_screen);
       if (delegate_->ProcessHomeLauncherGesture(event->type(),
                                                 location_in_screen)) {
+        SetIsInDrag(false);
         event->SetHandled();
         return;
       }
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index f4390e0..ce2e849 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -603,32 +603,47 @@
   drag_view_->SetPosition(drag_view_start_ + drag_vector);
 
   last_drag_point_ = point;
-  const GridIndex last_reorder_drop_target = reorder_drop_target_;
-  const GridIndex last_folder_drop_target = folder_drop_target_;
-  DropAttempt last_drop_attempt = drop_attempt_;
-  CalculateDropTarget();
+  const GridIndex last_drop_target = drop_target_;
+  DropTargetRegion last_drop_target_region = drop_target_region_;
+  UpdateDropTargetRegion();
 
   MaybeStartPageFlipTimer(last_drag_point_);
 
-  if (last_folder_drop_target != folder_drop_target_ ||
-      last_reorder_drop_target != reorder_drop_target_ ||
-      last_drop_attempt != drop_attempt_) {
-    if (drop_attempt_ == DROP_FOR_REORDER) {
-      folder_dropping_timer_.Stop();
-      reorder_timer_.Start(FROM_HERE,
-                           base::TimeDelta::FromMilliseconds(kReorderDelay),
-                           this, &AppsGridView::OnReorderTimer);
-    } else if (drop_attempt_ == DROP_FOR_FOLDER) {
+  if (last_drop_target != drop_target_ ||
+      last_drop_target_region != drop_target_region_) {
+    if (drop_target_region_ == ON_ITEM && DraggedItemCanEnterFolder() &&
+        DropTargetIsValidFolder()) {
       reorder_timer_.Stop();
       folder_dropping_timer_.Start(
           FROM_HERE,
           base::TimeDelta::FromMilliseconds(
               AppListConfig::instance().folder_dropping_delay()),
           this, &AppsGridView::OnFolderDroppingTimer);
+    } else if ((drop_target_region_ == ON_ITEM ||
+                drop_target_region_ == NEAR_ITEM) &&
+               !folder_delegate_) {
+      folder_dropping_timer_.Stop();
+
+      // If the drag changes regions from |BETWEEN_ITEMS| to |NEAR_ITEM| the
+      // timer should reset, so that we gain the extra time from hovering near
+      // the item
+      if (last_drop_target_region == BETWEEN_ITEMS)
+        reorder_timer_.Stop();
+      reorder_timer_.Start(FROM_HERE,
+                           base::TimeDelta::FromMilliseconds(kReorderDelay * 5),
+                           this, &AppsGridView::OnReorderTimer);
+    } else if (drop_target_region_ != NO_TARGET) {
+      // If none of the above cases evaluated true, then all of the possible
+      // drop regions should result in a fast reorder.
+      folder_dropping_timer_.Stop();
+      reorder_timer_.Start(FROM_HERE,
+                           base::TimeDelta::FromMilliseconds(kReorderDelay),
+                           this, &AppsGridView::OnReorderTimer);
     }
 
     // Reset the previous drop target.
-    SetAsFolderDroppingTarget(last_folder_drop_target, false);
+    if (last_drop_target_region == ON_ITEM)
+      SetAsFolderDroppingTarget(last_drop_target, false);
   }
 }
 
@@ -675,14 +690,14 @@
 
     if (!cancel && dragging()) {
       // Regular drag ending path, ie, not for reparenting.
-      CalculateDropTarget();
-      if (EnableFolderDragDropUI() && drop_attempt_ == DROP_FOR_FOLDER &&
-          IsValidIndex(folder_drop_target_)) {
-        MoveItemToFolder(drag_view_, folder_drop_target_);
+      UpdateDropTargetRegion();
+      if (drop_target_region_ == ON_ITEM && DraggedItemCanEnterFolder() &&
+          DropTargetIsValidFolder()) {
+        MoveItemToFolder(drag_view_, drop_target_);
         folder_item_view =
-            GetViewDisplayedAtSlotOnCurrentPage(folder_drop_target_.slot);
-      } else if (IsValidReorderTargetIndex(reorder_drop_target_)) {
-        MoveItemInModel(drag_view_, reorder_drop_target_);
+            GetViewDisplayedAtSlotOnCurrentPage(drop_target_.slot);
+      } else if (IsValidReorderTargetIndex(drop_target_)) {
+        MoveItemInModel(drag_view_, drop_target_);
       }
     }
   }
@@ -696,7 +711,7 @@
       if (landed_in_drag_and_drop_host) {
         // Move the item directly to the target location, avoiding the
         // "zip back" animation if the user was pinning it to the shelf.
-        int i = reorder_drop_target_.slot;
+        int i = drop_target_.slot;
         gfx::Rect bounds = view_model_.ideal_bounds(i);
         drag_view_->SetBoundsRect(bounds);
       }
@@ -706,7 +721,7 @@
     }
   }
 
-  SetAsFolderDroppingTarget(folder_drop_target_, false);
+  SetAsFolderDroppingTarget(drop_target_, false);
   ClearDragState();
   UpdatePaging();
   AnimateToIdealBounds();
@@ -819,10 +834,9 @@
 }
 
 void AppsGridView::ClearDragState() {
-  drop_attempt_ = DROP_FOR_NONE;
+  drop_target_region_ = NO_TARGET;
   drag_pointer_ = NONE;
-  reorder_drop_target_ = GridIndex();
-  folder_drop_target_ = GridIndex();
+  drop_target_ = GridIndex();
   reorder_placeholder_ = GridIndex();
   drag_start_grid_view_ = gfx::Point();
   drag_start_page_ = -1;
@@ -1361,7 +1375,7 @@
   drag_point->set_x(GetMirroredXInView(drag_point->x()));
 }
 
-void AppsGridView::CalculateDropTarget() {
+void AppsGridView::UpdateDropTargetRegion() {
   DCHECK(drag_view_);
 
   gfx::Point point = drag_view_->GetIconBounds().CenterPoint();
@@ -1369,54 +1383,32 @@
   // Ensure that the drop target location is correct if RTL.
   point.set_x(GetMirroredXInView(point.x()));
   if (IsPointWithinDragBuffer(point)) {
-    if (EnableFolderDragDropUI() &&
-        CalculateFolderDropTarget(point, &folder_drop_target_)) {
-      drop_attempt_ = DROP_FOR_FOLDER;
+    if (DragPointIsOverItem(point)) {
+      drop_target_region_ = ON_ITEM;
+      drop_target_ = GetNearestTileIndexForPoint(point);
       return;
     }
 
-    if (CalculateReorderDropTarget(point, &reorder_drop_target_)) {
-      drop_attempt_ = DROP_FOR_REORDER;
-      return;
-    }
+    UpdateDropTargetForReorder(point);
+    drop_target_region_ = DragIsCloseToItem() ? NEAR_ITEM : BETWEEN_ITEMS;
+    return;
   }
 
   // Reset the reorder target to the original position if the cursor is outside
   // the drag buffer or an item is dragged to a full page either from a folder
   // or another page.
   if (IsDraggingForReparentInRootLevelGridView()) {
-    drop_attempt_ = DROP_FOR_NONE;
+    drop_target_region_ = NO_TARGET;
     return;
   }
 
-  reorder_drop_target_ = drag_view_init_index_;
-  drop_attempt_ = DROP_FOR_REORDER;
+  drop_target_ = drag_view_init_index_;
+  drop_target_region_ = DragIsCloseToItem() ? NEAR_ITEM : BETWEEN_ITEMS;
 }
 
-bool AppsGridView::CalculateFolderDropTarget(const gfx::Point& point,
-                                             GridIndex* drop_target) const {
-  // Folders can't be dropped into other folders.
-  if (IsFolderItem(drag_view_->item()))
-    return false;
-
-  // A folder drop shouldn't happen on the reorder placeholder since that would
-  // be merging an item with itself.
-  GridIndex nearest_tile_index(GetNearestTileIndexForPoint(point));
-  if (!IsValidIndex(nearest_tile_index) ||
-      nearest_tile_index == reorder_placeholder_) {
-    return false;
-  }
-
-  int distance_to_tile_center =
-      (point - GetExpectedTileBounds(nearest_tile_index).CenterPoint())
-          .Length();
-  if (distance_to_tile_center >
-      AppListConfig::instance().folder_dropping_circle_radius()) {
-    return false;
-  }
-
+bool AppsGridView::DropTargetIsValidFolder() {
   AppListItemView* target_view =
-      GetViewDisplayedAtSlotOnCurrentPage(nearest_tile_index.slot);
+      GetViewDisplayedAtSlotOnCurrentPage(drop_target_.slot);
   if (!target_view)
     return false;
 
@@ -1431,53 +1423,112 @@
     return false;
   }
 
-  *drop_target = nearest_tile_index;
-  DCHECK(IsValidIndex(*drop_target));
+  if (!IsValidIndex(drop_target_))
+    return false;
+
   return true;
 }
 
-bool AppsGridView::CalculateReorderDropTarget(const gfx::Point& point,
-                                              GridIndex* drop_target) const {
+bool AppsGridView::DragPointIsOverItem(const gfx::Point& point) {
+  // The reorder placeholder shouldn't count as a unique item
+  GridIndex nearest_tile_index(GetNearestTileIndexForPoint(point));
+  if (!IsValidIndex(nearest_tile_index) ||
+      nearest_tile_index == reorder_placeholder_) {
+    return false;
+  }
+
+  int distance_to_tile_center =
+      (point - GetExpectedTileBounds(nearest_tile_index).CenterPoint())
+          .Length();
+  if (distance_to_tile_center >
+      AppListConfig::instance().folder_dropping_circle_radius()) {
+    return false;
+  }
+
+  return true;
+}
+
+bool AppsGridView::DraggedItemCanEnterFolder() {
+  if (!IsFolderItem(drag_view_->item()) && !folder_delegate_)
+    return true;
+  return false;
+}
+
+void AppsGridView::UpdateDropTargetForReorder(const gfx::Point& point) {
   gfx::Rect bounds = GetContentsBounds();
   bounds.Inset(GetTilePadding());
-  GridIndex grid_index = GetNearestTileIndexForPoint(point);
+  GridIndex nearest_tile_index = GetNearestTileIndexForPoint(point);
   gfx::Point reorder_placeholder_center =
       GetExpectedTileBounds(reorder_placeholder_).CenterPoint();
 
   int x_offset_direction = 0;
-  if (grid_index == reorder_placeholder_) {
+  if (nearest_tile_index == reorder_placeholder_) {
     x_offset_direction = reorder_placeholder_center.x() <= point.x() ? -1 : 1;
   } else {
-    x_offset_direction = reorder_placeholder_ < grid_index ? -1 : 1;
+    x_offset_direction = reorder_placeholder_ < nearest_tile_index ? -1 : 1;
   }
 
   const gfx::Size total_tile_size = GetTotalTileSize();
-  int row = grid_index.slot / cols_;
+  int row = nearest_tile_index.slot / cols_;
 
   // Offset the target column based on the direction of the target. This will
   // result in earlier targets getting their reorder zone shifted backwards
   // and later targets getting their reorder zones shifted forwards.
   //
-  // This makes eordering feel like the user is slotting items into the spaces
+  // This makes reordering feel like the user is slotting items into the spaces
   // between apps.
   int x_offset = x_offset_direction *
                  (total_tile_size.width() / 2 -
                   AppListConfig::instance().folder_dropping_circle_radius());
   int col = (point.x() - bounds.x() + x_offset) / total_tile_size.width();
   col = base::ClampToRange(col, 0, cols_ - 1);
-  *drop_target =
+  drop_target_ =
       std::min(GridIndex(pagination_model_.selected_page(), row * cols_ + col),
                GetLastTargetIndexOfPage(pagination_model_.selected_page()));
 
-  DCHECK(IsValidReorderTargetIndex(*drop_target));
-  return true;
+  DCHECK(IsValidReorderTargetIndex(drop_target_));
+}
+
+bool AppsGridView::DragIsCloseToItem() {
+  DCHECK(drag_view_);
+
+  gfx::Point point = drag_view_->GetIconBounds().CenterPoint();
+  views::View::ConvertPointToTarget(drag_view_, this, &point);
+  // Ensure that the drop target location is correct if RTL.
+  point.set_x(GetMirroredXInView(point.x()));
+
+  GridIndex nearest_tile_index = GetNearestTileIndexForPoint(point);
+
+  if (nearest_tile_index == reorder_placeholder_)
+    return false;
+
+  const int distance_to_tile_center =
+      (point - GetExpectedTileBounds(nearest_tile_index).CenterPoint())
+          .Length();
+
+  // The minimum of |forty_percent_icon_spacing| and |double_icon_radius| is
+  // chosen to give an acceptable spacing on displays of any resolution: when
+  // items are very close together, using |forty_percent_icon_spacing| will
+  // prevent overlap and leave a reasonable gap, whereas when icons are very far
+  // apart, using |double_icon_radius| will prevent us from juding an overly
+  // large region as 'nearby'
+  const int forty_percent_icon_spacing =
+      (AppListConfig::instance().grid_tile_width() +
+       horizontal_tile_padding_ * 2) *
+      0.4;
+  const int double_icon_radius =
+      AppListConfig::instance().folder_dropping_circle_radius() * 2;
+  const int minimum_drag_distance_for_reorder =
+      std::min(forty_percent_icon_spacing, double_icon_radius);
+
+  if (distance_to_tile_center < minimum_drag_distance_for_reorder)
+    return true;
+  return false;
 }
 
 void AppsGridView::OnReorderTimer() {
-  if (drop_attempt_ == DROP_FOR_REORDER) {
-    reorder_placeholder_ = reorder_drop_target_;
-    AnimateToIdealBounds();
-  }
+  reorder_placeholder_ = drop_target_;
+  AnimateToIdealBounds();
 }
 
 void AppsGridView::OnFolderItemReparentTimer() {
@@ -1497,8 +1548,7 @@
 }
 
 void AppsGridView::OnFolderDroppingTimer() {
-  if (drop_attempt_ == DROP_FOR_FOLDER)
-    SetAsFolderDroppingTarget(folder_drop_target_, true);
+  SetAsFolderDroppingTarget(drop_target_, true);
 }
 
 void AppsGridView::UpdateDragStateInsideFolder(Pointer pointer,
@@ -1745,7 +1795,7 @@
       ->NotifyOfDraggedItem(nullptr);
 
   DCHECK(IsDraggingForReparentInRootLevelGridView());
-  bool cancel_reparent = cancel_drag || drop_attempt_ == DROP_FOR_NONE;
+  bool cancel_reparent = cancel_drag || drop_target_region_ == NO_TARGET;
 
   // This is the folder view to drop an item into. Cache the |drag_view_|'s item
   // and its bounds for later use in folder dropping animation.
@@ -1754,25 +1804,24 @@
   const gfx::Rect drag_source_bounds(drag_view_->bounds());
 
   if (!events_forwarded_to_drag_drop_host && !cancel_reparent) {
-    CalculateDropTarget();
-    if (drop_attempt_ == DROP_FOR_REORDER &&
-        IsValidReorderTargetIndex(reorder_drop_target_)) {
-      ReparentItemForReorder(drag_view_, reorder_drop_target_);
-    } else if (drop_attempt_ == DROP_FOR_FOLDER &&
-               IsValidIndex(folder_drop_target_)) {
-      cancel_reparent =
-          !ReparentItemToAnotherFolder(drag_view_, folder_drop_target_);
+    UpdateDropTargetRegion();
+    if (drop_target_region_ == ON_ITEM && DropTargetIsValidFolder() &&
+        DraggedItemCanEnterFolder()) {
+      cancel_reparent = !ReparentItemToAnotherFolder(drag_view_, drop_target_);
       if (!cancel_reparent) {
         folder_item_view =
-            GetViewDisplayedAtSlotOnCurrentPage(folder_drop_target_.slot);
+            GetViewDisplayedAtSlotOnCurrentPage(drop_target_.slot);
       }
+    } else if (drop_target_region_ != NO_TARGET &&
+               IsValidReorderTargetIndex(drop_target_)) {
+      ReparentItemForReorder(drag_view_, drop_target_);
     } else {
       NOTREACHED();
     }
     SetViewHidden(drag_view_, false /* show */, true /* no animate */);
   }
 
-  SetAsFolderDroppingTarget(folder_drop_target_, false);
+  SetAsFolderDroppingTarget(drop_target_, false);
   if (!cancel_reparent) {
     // By setting |drag_view_| to NULL here, we prevent ClearDragState() from
     // cleaning up the newly created AppListItemView, effectively claiming
@@ -1805,7 +1854,7 @@
     drag_and_drop_host_->DestroyDragIconProxy();
   }
 
-  SetAsFolderDroppingTarget(folder_drop_target_, false);
+  SetAsFolderDroppingTarget(drop_target_, false);
   ClearDragState();
 }
 
@@ -2537,7 +2586,7 @@
 
 void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) {
   if (dragging()) {
-    CalculateDropTarget();
+    UpdateDropTargetRegion();
     Layout();
     MaybeStartPageFlipTimer(last_drag_point_);
   } else {
@@ -2600,11 +2649,6 @@
     SetVisible(false);
 }
 
-bool AppsGridView::EnableFolderDragDropUI() {
-  // Enable drag and drop folder UI only if it is at the app list root level.
-  return !folder_delegate_;
-}
-
 GridIndex AppsGridView::GetNearestTileIndexForPoint(
     const gfx::Point& point) const {
   gfx::Rect bounds = GetContentsBounds();
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h
index f4f2d36..e1ed6fc 100644
--- a/ash/app_list/views/apps_grid_view.h
+++ b/ash/app_list/views/apps_grid_view.h
@@ -299,10 +299,11 @@
   friend class test::AppsGridViewTestApi;
   friend class PagedViewStructure;
 
-  enum DropAttempt {
-    DROP_FOR_NONE,
-    DROP_FOR_REORDER,
-    DROP_FOR_FOLDER,
+  enum DropTargetRegion {
+    NO_TARGET,
+    ON_ITEM,
+    NEAR_ITEM,
+    BETWEEN_ITEMS,
   };
 
   // Updates suggestions from app list model.
@@ -359,20 +360,21 @@
   void ExtractDragLocation(const gfx::Point& root_location,
                            gfx::Point* drag_point);
 
-  // Updates |reorder_drop_target_|, |folder_drop_target_| and |drop_attempt_|
+  // Updates |drop_target_| and |drop_target_region_|
   // based on |drag_view_|'s position.
-  void CalculateDropTarget();
+  void UpdateDropTargetRegion();
 
-  // If |point| is a valid folder drop target, returns true and sets
-  // |drop_target| to the index of the view to do a folder drop for.
-  bool CalculateFolderDropTarget(const gfx::Point& point,
-                                 GridIndex* drop_target) const;
+  bool DropTargetIsValidFolder();
 
-  // Calculates the reorder target |point| and sets |drop_target| to the index
-  // of the view to reorder. Returns true if |drop_target| is calculated
-  // successfully.
-  bool CalculateReorderDropTarget(const gfx::Point& point,
-                                  GridIndex* drop_target) const;
+  // Updates |drop_target_| as a location for potential reordering after the
+  // currently dragged item is released.
+  void UpdateDropTargetForReorder(const gfx::Point& point);
+
+  // Returns true if the current drag is occurring within a certain range of the
+  // nearest item.
+  bool DragIsCloseToItem();
+
+  bool DragPointIsOverItem(const gfx::Point& point);
 
   // Prepares |drag_and_drop_host_| for dragging. |grid_location| contains
   // the drag point in this grid view's coordinates.
@@ -466,8 +468,9 @@
   // If |hide| is set the view will get hidden, otherwise it gets shown.
   void SetViewHidden(AppListItemView* view, bool hide, bool immediate);
 
-  // Whether the folder drag-and-drop UI should be enabled.
-  bool EnableFolderDragDropUI();
+  // Returns true if the dragged item isn't a folder, the drag is not
+  // occurring inside a folder, and |drop_target_| is a valid index.
+  bool DraggedItemCanEnterFolder();
 
   // Returns the size of the entire tile grid.
   gfx::Size GetTileGridSize() const;
@@ -663,7 +666,7 @@
   Pointer drag_pointer_ = NONE;
 
   // The most recent reorder drop target.
-  GridIndex reorder_drop_target_;
+  GridIndex drop_target_;
 
   // The most recent folder drop target.
   GridIndex folder_drop_target_;
@@ -673,12 +676,12 @@
   GridIndex reorder_placeholder_;
 
   // The current action that ending a drag will perform.
-  DropAttempt drop_attempt_ = DROP_FOR_NONE;
+  DropTargetRegion drop_target_region_ = NO_TARGET;
 
-  // Timer for re-ordering the |drop_target_| and |drag_view_|.
+  // Timer for re-ordering the |drop_target_region_| and |drag_view_|.
   base::OneShotTimer reorder_timer_;
 
-  // Timer for dropping |drag_view_| into the folder containing
+  // Timer for dropping |drag_view_| into the folder represented by
   // the |drop_target_|.
   base::OneShotTimer folder_dropping_timer_;
 
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc
index a4017ee..a70d5c0 100644
--- a/ash/assistant/assistant_interaction_controller.cc
+++ b/ash/assistant/assistant_interaction_controller.cc
@@ -162,13 +162,7 @@
       model_.SetInputModality(InputModality::kKeyboard);
       break;
     case AssistantVisibility::kVisible:
-      if (source == AssistantSource::kLauncherSearchBox ||
-          source == AssistantSource::kLongPressLauncher) {
-        if (IsTabletMode())
-          StartVoiceInteraction();
-      } else if (source == AssistantSource::kStylus) {
-        model_.SetInputModality(InputModality::kStylus);
-      }
+      OnUiVisible(source);
       break;
   }
 }
@@ -278,22 +272,43 @@
   // device hotword loss, for example, but can also occur if the interaction
   // errors out. In these cases we still need to commit the pending query as
   // this is a prerequisite step to being able to finalize the pending response.
-  if (model_.pending_query().type() != AssistantQueryType::kNull) {
+  if (model_.pending_query().type() != AssistantQueryType::kNull)
     model_.CommitPendingQuery();
+
+  // It's possible that the pending response has already been finalized. This
+  // occurs if the response contained TTS, as we flush the response to the UI
+  // when TTS is started to reduce latency.
+  if (!model_.pending_response())
+    return;
+
+  // Some interaction resolutions require special handling.
+  switch (resolution) {
+    case AssistantInteractionResolution::kError:
+      // In the case of error, we show an appropriate message to the user.
+      model_.pending_response()->AddUiElement(
+          std::make_unique<AssistantTextElement>(
+              l10n_util::GetStringUTF8(IDS_ASH_ASSISTANT_ERROR_GENERIC)));
+      break;
+    case AssistantInteractionResolution::kMultiDeviceHotwordLoss:
+      // In the case of hotword loss to another device, we show an appropriate
+      // message to the user.
+      model_.pending_response()->AddUiElement(
+          std::make_unique<AssistantTextElement>(l10n_util::GetStringUTF8(
+              IDS_ASH_ASSISTANT_MULTI_DEVICE_HOTWORD_LOSS)));
+      break;
+    case AssistantInteractionResolution::kMicTimeout:
+      // Interactions resolving due to mic timeout are already handled above
+      // outside the switch.
+      NOTREACHED();
+      break;
+    case AssistantInteractionResolution::kInterruption:  // fallthrough
+    case AssistantInteractionResolution::kNormal:
+      // No special handling required.
+      break;
   }
 
-  // If the interaction was finished due to multi-device hotword loss, we want
-  // to show an appropriate message to the user.
-  if (resolution == AssistantInteractionResolution::kMultiDeviceHotwordLoss) {
-    model_.pending_response()->AddUiElement(
-        std::make_unique<AssistantTextElement>(l10n_util::GetStringUTF8(
-            IDS_ASH_ASSISTANT_MULTI_DEVICE_HOTWORD_LOSS)));
-  }
-
-  // The interaction has finished, so we finalize the pending response if it
-  // hasn't already been finalized.
-  if (model_.pending_response())
-    model_.FinalizePendingResponse();
+  // Finalize the pending response to flush it to the UI.
+  model_.FinalizePendingResponse();
 }
 
 void AssistantInteractionController::OnHtmlResponse(
@@ -451,6 +466,34 @@
   StartTextInteraction(text);
 }
 
+void AssistantInteractionController::OnUiVisible(AssistantSource source) {
+  DCHECK_EQ(AssistantVisibility::kVisible,
+            assistant_controller_->ui_controller()->model()->visibility());
+
+  switch (source) {
+    case AssistantSource::kHotkey:
+    case AssistantSource::kLauncherSearchBox:
+    case AssistantSource::kLongPressLauncher: {
+      // When the user prefers it or when we are in tablet mode, launching
+      // Assistant UI will immediately start a voice interaction.
+      const bool launch_with_mic_open =
+          Shell::Get()->voice_interaction_controller()->launch_with_mic_open();
+      if (launch_with_mic_open || IsTabletMode())
+        StartVoiceInteraction();
+      break;
+    }
+    case AssistantSource::kStylus:
+      model_.SetInputModality(InputModality::kStylus);
+      break;
+    case AssistantSource::kUnspecified:
+    case AssistantSource::kDeepLink:
+    case AssistantSource::kHotword:
+    case AssistantSource::kSetup:
+      // No action necessary.
+      break;
+  }
+}
+
 void AssistantInteractionController::StartMetalayerInteraction(
     const gfx::Rect& region) {
   StopActiveInteraction(false);
diff --git a/ash/assistant/assistant_interaction_controller.h b/ash/assistant/assistant_interaction_controller.h
index f2fb1cd4..4e96de48 100644
--- a/ash/assistant/assistant_interaction_controller.h
+++ b/ash/assistant/assistant_interaction_controller.h
@@ -99,6 +99,8 @@
   void OnSuggestionChipPressed(const AssistantSuggestion* suggestion);
 
  private:
+  void OnUiVisible(AssistantSource source);
+
   void StartMetalayerInteraction(const gfx::Rect& region);
   void StartScreenContextInteraction();
   void StartTextInteraction(const std::string text);
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index 1538837a..5c2068a 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -340,7 +340,7 @@
   const gfx::ImageSkiaRep& image_rep = resized.GetRepresentation(cursor_scale);
   delegate_->SetCursorImage(
       resized.size(),
-      gfx::ImageSkia(gfx::ImageSkiaRep(image_rep.sk_bitmap(), cursor_scale)));
+      gfx::ImageSkia(gfx::ImageSkiaRep(image_rep.GetBitmap(), cursor_scale)));
   hot_point_ = gfx::ConvertPointToDIP(cursor_scale, hot_point_);
 
   if (cursor_view_) {
diff --git a/ash/drag_drop/drag_image_view.cc b/ash/drag_drop/drag_image_view.cc
index 910d0db..8ed7d4b04 100644
--- a/ash/drag_drop/drag_image_view.cc
+++ b/ash/drag_drop/drag_image_view.cc
@@ -135,7 +135,7 @@
     if (image_rep.is_null())
       return;
     SkBitmap scaled = skia::ImageOperations::Resize(
-        image_rep.sk_bitmap(), skia::ImageOperations::RESIZE_LANCZOS3,
+        image_rep.GetBitmap(), skia::ImageOperations::RESIZE_LANCZOS3,
         drag_image_size_pixels.width(), drag_image_size_pixels.height());
     gfx::ImageSkia image_skia(gfx::ImageSkiaRep(scaled, device_scale));
     canvas->DrawImageInt(image_skia, 0, 0);
diff --git a/ash/login/ui/horizontal_image_sequence_animation_decoder.cc b/ash/login/ui/horizontal_image_sequence_animation_decoder.cc
index 9d82994..b1a8a95 100644
--- a/ash/login/ui/horizontal_image_sequence_animation_decoder.cc
+++ b/ash/login/ui/horizontal_image_sequence_animation_decoder.cc
@@ -17,7 +17,7 @@
 
 AnimationFrames HorizontalImageSequenceAnimationDecoder::Decode(
     float image_scale) {
-  SkBitmap bitmap = image_.GetRepresentation(image_scale).sk_bitmap();
+  SkBitmap bitmap = image_.GetRepresentation(image_scale).GetBitmap();
 
   float frame_width = static_cast<float>(bitmap.width()) / num_frames_;
   base::TimeDelta frame_duration = duration_ / num_frames_;
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc
index 3b1202c..e188252 100644
--- a/ash/system/palette/palette_tray.cc
+++ b/ash/system/palette/palette_tray.cc
@@ -138,12 +138,35 @@
   DISALLOW_COPY_AND_ASSIGN(TitleView);
 };
 
+// Used as a Shell pre-target handler to notify PaletteTray of stylus events.
+class StylusEventHandler : public ui::EventHandler {
+ public:
+  explicit StylusEventHandler(PaletteTray* tray) : palette_tray_(tray) {
+    Shell::Get()->AddPreTargetHandler(this);
+  }
+
+  ~StylusEventHandler() override { Shell::Get()->RemovePreTargetHandler(this); }
+
+  // ui::EventHandler:
+  void OnTouchEvent(ui::TouchEvent* event) override {
+    if (event->pointer_details().pointer_type ==
+        ui::EventPointerType::POINTER_TYPE_PEN) {
+      palette_tray_->OnStylusEvent(*event);
+    }
+  }
+
+ private:
+  PaletteTray* palette_tray_;
+  DISALLOW_COPY_AND_ASSIGN(StylusEventHandler);
+};
+
 }  // namespace
 
 PaletteTray::PaletteTray(Shelf* shelf)
     : TrayBackgroundView(shelf),
-      palette_tool_manager_(new PaletteToolManager(this)),
+      palette_tool_manager_(std::make_unique<PaletteToolManager>(this)),
       welcome_bubble_(std::make_unique<PaletteWelcomeBubble>(this)),
+      stylus_event_handler_(std::make_unique<StylusEventHandler>(this)),
       scoped_session_observer_(this),
       weak_factory_(this) {
   PaletteTool::RegisterToolInstances(palette_tool_manager_.get());
@@ -158,7 +181,6 @@
   tray_container()->AddChildView(icon_);
 
   Shell::Get()->AddShellObserver(this);
-  Shell::Get()->AddPointerWatcher(this, views::PointerWatcherEventTypes::BASIC);
 }
 
 PaletteTray::~PaletteTray() {
@@ -167,7 +189,6 @@
 
   ui::InputDeviceManager::GetInstance()->RemoveObserver(this);
   Shell::Get()->RemoveShellObserver(this);
-  Shell::Get()->RemovePointerWatcher(this);
 }
 
 // static
@@ -199,6 +220,24 @@
           stylus_utils::IsPaletteEnabledOnEveryDisplay());
 }
 
+void PaletteTray::OnStylusEvent(const ui::TouchEvent& event) {
+  if (!HasSeenStylus() && local_state_pref_service_)
+    local_state_pref_service_->SetBoolean(prefs::kHasSeenStylus, true);
+
+  // Attempt to show the welcome bubble.
+  if (!welcome_bubble_->HasBeenShown() && active_user_pref_service_) {
+    // If a stylus event is detected on the palette tray, the user already knows
+    // about the tray and there is no need to show them the welcome bubble.
+    if (!GetBoundsInScreen().Contains(event.target()->GetScreenLocation(event)))
+      welcome_bubble_->ShowIfNeeded();
+    else
+      welcome_bubble_->MarkAsShown();
+  }
+
+  if (HasSeenStylus() && welcome_bubble_->HasBeenShown())
+    stylus_event_handler_.reset();
+}
+
 void PaletteTray::OnActiveUserPrefServiceChanged(PrefService* pref_service) {
   active_user_pref_service_ = pref_service;
   pref_change_registrar_user_ = std::make_unique<PrefChangeRegistrar>();
@@ -216,13 +255,13 @@
   // showing the bubble if the device has never and may never be used with
   // stylus).
   if (HasSeenStylus() && !stylus_utils::HasInternalStylus())
-    welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
+    welcome_bubble_->ShowIfNeeded();
 }
 
 void PaletteTray::OnSessionStateChanged(session_manager::SessionState state) {
   UpdateIconVisibility();
   if (HasSeenStylus() && !stylus_utils::HasInternalStylus())
-    welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
+    welcome_bubble_->ShowIfNeeded();
 }
 
 void PaletteTray::OnLockStateChanged(bool locked) {
@@ -302,7 +341,7 @@
     // Show the palette welcome bubble if the auto open palette setting is not
     // turned on, if the bubble has not been shown before (|welcome_bubble_|
     // will be nullptr if the bubble has been shown before).
-    welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
+    welcome_bubble_->ShowIfNeeded();
   }
 
   // Disable any active modes if the stylus has been inserted.
@@ -390,29 +429,6 @@
   return shelf()->GetWindow();
 }
 
-void PaletteTray::OnPointerEventObserved(const ui::PointerEvent& event,
-                                         const gfx::Point& location_in_screen,
-                                         gfx::NativeView target) {
-  if (event.pointer_details().pointer_type !=
-      ui::EventPointerType::POINTER_TYPE_PEN) {
-    return;
-  }
-
-  // If a stylus has never been seen before and a stylus event is received, mark
-  // the |kHasSeenStylus| pref as true and attempt to show the welcome bubble.
-  if (!HasSeenStylus()) {
-    if (local_state_pref_service_)
-      local_state_pref_service_->SetBoolean(prefs::kHasSeenStylus, true);
-
-    if (active_user_pref_service_)
-      welcome_bubble_->ShowIfNeeded(true /* shown_by_stylus */);
-  } else if (GetBoundsInScreen().Contains(location_in_screen)) {
-    // If a stylus event is detected on the palette tray, the user already knows
-    // about the tray and there is no need to show them the welcome bubble.
-    welcome_bubble_->MarkAsShown();
-  }
-}
-
 void PaletteTray::AnchorUpdated() {
   if (bubble_) {
     UpdateClippingWindowBounds();
diff --git a/ash/system/palette/palette_tray.h b/ash/system/palette/palette_tray.h
index 18afe6c..ac90a87 100644
--- a/ash/system/palette/palette_tray.h
+++ b/ash/system/palette/palette_tray.h
@@ -15,7 +15,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/events/devices/input_device_event_observer.h"
-#include "ui/views/pointer_watcher.h"
 
 class PrefChangeRegistrar;
 class PrefRegistrySimple;
@@ -44,8 +43,7 @@
                                public SessionObserver,
                                public ShellObserver,
                                public PaletteToolManager::Delegate,
-                               public ui::InputDeviceEventObserver,
-                               public views::PointerWatcher {
+                               public ui::InputDeviceEventObserver {
  public:
   explicit PaletteTray(Shelf* shelf);
   ~PaletteTray() override;
@@ -62,6 +60,9 @@
   // disabled it in settings. This can be overridden by passing switches.
   bool ShouldShowPalette() const;
 
+  // Handles stylus events to show the welcome bubble on first usage.
+  void OnStylusEvent(const ui::TouchEvent& event);
+
   // SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
   void OnSessionStateChanged(session_manager::SessionState state) override;
@@ -105,11 +106,6 @@
   void OnActiveToolChanged() override;
   aura::Window* GetWindow() override;
 
-  // views::PointerWatcher:
-  void OnPointerEventObserved(const ui::PointerEvent& event,
-                              const gfx::Point& location_in_screen,
-                              gfx::NativeView target) override;
-
   // Updates the tray icon from the palette tool manager.
   void UpdateTrayIcon();
 
@@ -133,6 +129,9 @@
   std::unique_ptr<PaletteWelcomeBubble> welcome_bubble_;
   std::unique_ptr<TrayBubbleWrapper> bubble_;
 
+  // A Shell pre-target handler that notifies PaletteTray of stylus events.
+  std::unique_ptr<ui::EventHandler> stylus_event_handler_;
+
   PrefService* local_state_pref_service_ = nullptr;  // Not owned.
   PrefService* active_user_pref_service_ = nullptr;  // Not owned.
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_local_;
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index 6c6a25978..8cb7d3da 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -213,21 +213,21 @@
 TEST_F(PaletteTrayTest, WelcomeBubbleVisibility) {
   ASSERT_FALSE(active_user_pref_service()->GetBoolean(
       prefs::kShownPaletteWelcomeBubble));
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   // Verify that the welcome bubble does not shown up after tapping the screen
   // with a finger.
   ui::test::EventGenerator* generator = GetEventGenerator();
   generator->PressTouch();
   generator->ReleaseTouch();
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   // Verify that the welcome bubble shows up after tapping the screen with a
   // stylus for the first time.
   generator->EnterPenPointerMode();
   generator->PressTouch();
   generator->ReleaseTouch();
-  EXPECT_TRUE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_TRUE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 }
 
 // Base class for tests that rely on voice interaction enabled.
@@ -590,10 +590,10 @@
                                          false);
   ASSERT_FALSE(active_user_pref_service()->GetBoolean(
       prefs::kShownPaletteWelcomeBubble));
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   EjectStylus();
-  EXPECT_TRUE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_TRUE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 }
 
 // Verify if the pref which tracks if the welcome bubble has been shown before
@@ -603,10 +603,10 @@
                                          false);
   active_user_pref_service()->SetBoolean(prefs::kShownPaletteWelcomeBubble,
                                          true);
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   EjectStylus();
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 }
 
 // Verify that the bubble does not get shown if the auto open palette setting is
@@ -617,10 +617,10 @@
       prefs::kLaunchPaletteOnEjectEvent));
   active_user_pref_service()->SetBoolean(prefs::kShownPaletteWelcomeBubble,
                                          false);
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   EjectStylus();
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 }
 
 // Verify that the bubble does not get shown if a stylus event has been seen by
@@ -629,7 +629,7 @@
        WelcomeBubbleNotShownIfStylusTouchTray) {
   ASSERT_FALSE(active_user_pref_service()->GetBoolean(
       prefs::kShownPaletteWelcomeBubble));
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 
   ui::test::EventGenerator* generator = GetEventGenerator();
   generator->EnterPenPointerMode();
@@ -641,7 +641,7 @@
   EXPECT_TRUE(active_user_pref_service()->GetBoolean(
       prefs::kShownPaletteWelcomeBubble));
   EjectStylus();
-  EXPECT_FALSE(test_api_->welcome_bubble()->bubble_shown());
+  EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting());
 }
 
 // Verify that palette bubble is shown/hidden on stylus eject/insert iff the
diff --git a/ash/system/palette/palette_welcome_bubble.cc b/ash/system/palette/palette_welcome_bubble.cc
index febe3fa..3971a327 100644
--- a/ash/system/palette/palette_welcome_bubble.cc
+++ b/ash/system/palette/palette_welcome_bubble.cc
@@ -79,7 +79,7 @@
 PaletteWelcomeBubble::~PaletteWelcomeBubble() {
   if (bubble_view_) {
     bubble_view_->GetWidget()->RemoveObserver(this);
-    Shell::Get()->RemovePointerWatcher(this);
+    Shell::Get()->RemovePreTargetHandler(this);
   }
   Shell::Get()->session_controller()->RemoveObserver(this);
 }
@@ -92,7 +92,7 @@
 void PaletteWelcomeBubble::OnWidgetClosing(views::Widget* widget) {
   widget->RemoveObserver(this);
   bubble_view_ = nullptr;
-  Shell::Get()->RemovePointerWatcher(this);
+  Shell::Get()->RemovePreTargetHandler(this);
 }
 
 void PaletteWelcomeBubble::OnActiveUserPrefServiceChanged(
@@ -100,7 +100,7 @@
   active_user_pref_service_ = pref_service;
 }
 
-void PaletteWelcomeBubble::ShowIfNeeded(bool shown_by_stylus) {
+void PaletteWelcomeBubble::ShowIfNeeded() {
   if (!active_user_pref_service_)
     return;
 
@@ -114,11 +114,13 @@
   if (user_type && *user_type == user_manager::USER_TYPE_GUEST)
     return;
 
-  if (!active_user_pref_service_->GetBoolean(
-          prefs::kShownPaletteWelcomeBubble) &&
-      !bubble_shown()) {
-    Show(shown_by_stylus);
-  }
+  if (!HasBeenShown())
+    Show();
+}
+
+bool PaletteWelcomeBubble::HasBeenShown() const {
+  return active_user_pref_service_ && active_user_pref_service_->GetBoolean(
+                                          prefs::kShownPaletteWelcomeBubble);
 }
 
 void PaletteWelcomeBubble::MarkAsShown() {
@@ -127,30 +129,20 @@
                                         true);
 }
 
-base::Optional<gfx::Rect> PaletteWelcomeBubble::GetBubbleBoundsForTest() {
-  if (bubble_view_)
-    return base::make_optional(bubble_view_->GetBoundsInScreen());
-
-  return base::nullopt;
+views::View* PaletteWelcomeBubble::GetBubbleViewForTesting() {
+  return bubble_view_;
 }
 
-void PaletteWelcomeBubble::Show(bool shown_by_stylus) {
+void PaletteWelcomeBubble::Show() {
   if (!bubble_view_) {
     DCHECK(tray_);
     bubble_view_ =
         new WelcomeBubbleView(tray_, views::BubbleBorder::BOTTOM_RIGHT);
   }
-  active_user_pref_service_->SetBoolean(prefs::kShownPaletteWelcomeBubble,
-                                        true);
+  MarkAsShown();
   bubble_view_->GetWidget()->Show();
   bubble_view_->GetWidget()->AddObserver(this);
-  Shell::Get()->AddPointerWatcher(this, views::PointerWatcherEventTypes::BASIC);
-
-  // If the bubble is shown after the device first reads a stylus, ignore the
-  // first up event so the event responsible for showing the bubble does not
-  // also cause the bubble to close.
-  if (shown_by_stylus)
-    ignore_stylus_event_ = true;
+  Shell::Get()->AddPreTargetHandler(this);
 }
 
 void PaletteWelcomeBubble::Hide() {
@@ -158,30 +150,18 @@
     bubble_view_->GetWidget()->Close();
 }
 
-void PaletteWelcomeBubble::OnPointerEventObserved(
-    const ui::PointerEvent& event,
-    const gfx::Point& location_in_screen,
-    gfx::NativeView target) {
-  if (!bubble_view_)
-    return;
-
-  // For devices with external stylus, the bubble is activated after it receives
-  // a pen pointer event. However, on attaching |this| as a pointer watcher, it
-  // receives the same set of events which activated the bubble in the first
-  // place (ET_POINTER_DOWN, ET_POINTER_UP, ET_POINTER_CAPTURE_CHANGED). By only
-  // looking at ET_POINTER_UP events and skipping the first up event if the
-  // bubble is shown because of a stylus event, we ensure the same event that
-  // opened the bubble does not close it as well.
-  if (event.type() != ui::ET_POINTER_UP)
-    return;
-
-  if (ignore_stylus_event_) {
-    ignore_stylus_event_ = false;
-    return;
-  }
-
-  if (!bubble_view_->GetBoundsInScreen().Contains(location_in_screen))
+void PaletteWelcomeBubble::OnMouseEvent(ui::MouseEvent* event) {
+  if (bubble_view_ && event->type() == ui::ET_MOUSE_PRESSED &&
+      event->target() != bubble_view_->GetWidget()->GetNativeView()) {
     bubble_view_->GetWidget()->Close();
+  }
+}
+
+void PaletteWelcomeBubble::OnTouchEvent(ui::TouchEvent* event) {
+  if (bubble_view_ && event->type() == ui::ET_TOUCH_PRESSED &&
+      event->target() != bubble_view_->GetWidget()->GetNativeView()) {
+    bubble_view_->GetWidget()->Close();
+  }
 }
 
 }  // namespace ash
diff --git a/ash/system/palette/palette_welcome_bubble.h b/ash/system/palette/palette_welcome_bubble.h
index d34024e5..318121c4 100644
--- a/ash/system/palette/palette_welcome_bubble.h
+++ b/ash/system/palette/palette_welcome_bubble.h
@@ -8,16 +8,15 @@
 #include "ash/ash_export.h"
 #include "ash/session/session_observer.h"
 #include "base/macros.h"
-#include "base/optional.h"
-#include "ui/views/pointer_watcher.h"
+#include "ui/events/event_handler.h"
 #include "ui/views/widget/widget_observer.h"
 
 class PrefRegistrySimple;
 class PrefService;
 
 namespace views {
-class Widget;
-}  // namespace views
+class View;
+}
 
 namespace ash {
 class PaletteTray;
@@ -28,51 +27,43 @@
 // bubble.
 class ASH_EXPORT PaletteWelcomeBubble : public SessionObserver,
                                         public views::WidgetObserver,
-                                        public views::PointerWatcher {
+                                        public ui::EventHandler {
  public:
   explicit PaletteWelcomeBubble(PaletteTray* tray);
   ~PaletteWelcomeBubble() override;
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
-  // Show the welcome bubble iff it has not been shown before. |shown_by_stylus|
-  // is true if the call is generated by a stylus-down event.
-  void ShowIfNeeded(bool shown_by_stylus);
+  // Show the welcome bubble iff it has not been shown before.
+  void ShowIfNeeded();
+
+  // Get the pref which stores whether the bubble has been shown before.
+  bool HasBeenShown() const;
 
   // Set the pref which stores whether the bubble has been shown before as true.
   // The bubble will not be shown after this is called.
   void MarkAsShown();
 
-  bool bubble_shown() { return bubble_view_ != nullptr; }
-
   // SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
 
   // views::WidgetObserver:
   void OnWidgetClosing(views::Widget* widget) override;
 
-  // Returns the bounds of the bubble view if it exists.
-  base::Optional<gfx::Rect> GetBubbleBoundsForTest();
+  // Returns the bubble view for tests, or null when the bubble is not showing.
+  views::View* GetBubbleViewForTesting();
 
  private:
   friend class PaletteWelcomeBubbleTest;
   class WelcomeBubbleView;
 
-  void Show(bool shown_by_stylus);
-
-  // Hides the welcome bubble.
+  // Shows or hides the welcome bubble.
+  void Show();
   void Hide();
 
-  // views::PointerWatcher:
-  void OnPointerEventObserved(const ui::PointerEvent& event,
-                              const gfx::Point& location_in_screen,
-                              gfx::NativeView target) override;
-
-  // Flag which determines whether a pointer event should be ignored. This is
-  // set when this is first registered as a pointer watcher, so the same event
-  // which caused the bubble to show does not also cause the bubble to be
-  // hidden.
-  bool ignore_stylus_event_ = false;
+  // ui::EventHandler:
+  void OnMouseEvent(ui::MouseEvent* event) override;
+  void OnTouchEvent(ui::TouchEvent* event) override;
 
   // The PaletteTray this bubble is associated with. Serves as the anchor for
   // the bubble. Not owned.
diff --git a/ash/system/palette/palette_welcome_bubble_unittest.cc b/ash/system/palette/palette_welcome_bubble_unittest.cc
index 26318dc..8ac41f6 100644
--- a/ash/system/palette/palette_welcome_bubble_unittest.cc
+++ b/ash/system/palette/palette_welcome_bubble_unittest.cc
@@ -43,7 +43,7 @@
         AccountId::FromUserEmail(kUser2Email));
   }
 
-  void ShowBubble() { welcome_bubble_->Show(false /* shown_by_stylus */); }
+  void ShowBubble() { welcome_bubble_->Show(); }
   void HideBubble() { welcome_bubble_->Hide(); }
 
   // AshTestBase:
@@ -72,13 +72,13 @@
 
 // Test the basic Show/Hide functions work.
 TEST_F(PaletteWelcomeBubbleTest, Basic) {
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
+  EXPECT_FALSE(welcome_bubble_->GetBubbleViewForTesting());
 
   ShowBubble();
-  EXPECT_TRUE(welcome_bubble_->bubble_shown());
+  EXPECT_TRUE(welcome_bubble_->GetBubbleViewForTesting());
 
   HideBubble();
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
+  EXPECT_FALSE(welcome_bubble_->GetBubbleViewForTesting());
 
   // Verify that the pref changes after the bubble is hidden.
   EXPECT_TRUE(
@@ -89,32 +89,28 @@
 TEST_F(PaletteWelcomeBubbleTest, ShowIfNeeded) {
   user1_pref_service()->SetBoolean(prefs::kShownPaletteWelcomeBubble, true);
 
-  welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
-
-  welcome_bubble_->ShowIfNeeded(true /* shown_by_stylus */);
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
+  welcome_bubble_->ShowIfNeeded();
+  EXPECT_FALSE(welcome_bubble_->GetBubbleViewForTesting());
 }
 
 // Verify that tapping on the screen outside of the welcome bubble closes the
 // bubble.
 TEST_F(PaletteWelcomeBubbleTest, TapOutsideOfBubble) {
   ShowBubble();
-  ASSERT_TRUE(welcome_bubble_->bubble_shown());
-  ASSERT_TRUE(welcome_bubble_->GetBubbleBoundsForTest().has_value());
+  ASSERT_TRUE(welcome_bubble_->GetBubbleViewForTesting());
+  auto bounds = welcome_bubble_->GetBubbleViewForTesting()->GetBoundsInScreen();
+  ASSERT_FALSE(bounds.IsEmpty());
 
   // The bubble remains open if a tap occurs on the bubble.
-  GetEventGenerator()->set_current_location(
-      welcome_bubble_->GetBubbleBoundsForTest()->CenterPoint());
+  GetEventGenerator()->set_current_location(bounds.CenterPoint());
   GetEventGenerator()->ClickLeftButton();
-  EXPECT_TRUE(welcome_bubble_->bubble_shown());
+  EXPECT_TRUE(welcome_bubble_->GetBubbleViewForTesting());
 
   // Tap anywhere outside the bubble.
-  ASSERT_FALSE(
-      welcome_bubble_->GetBubbleBoundsForTest()->Contains(gfx::Point()));
+  ASSERT_FALSE(bounds.Contains(gfx::Point()));
   GetEventGenerator()->set_current_location(gfx::Point());
   GetEventGenerator()->ClickLeftButton();
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
+  EXPECT_FALSE(welcome_bubble_->GetBubbleViewForTesting());
 }
 
 // Verify that a second user sees the bubble even after a first user has seen it
@@ -123,7 +119,7 @@
   // Show the bubble for the first user, and verify that the pref is set when
   // the bubble is hidden.
   ShowBubble();
-  EXPECT_TRUE(welcome_bubble_->bubble_shown());
+  EXPECT_TRUE(welcome_bubble_->GetBubbleViewForTesting());
   HideBubble();
   ASSERT_TRUE(
       user1_pref_service()->GetBoolean(prefs::kShownPaletteWelcomeBubble));
@@ -133,15 +129,15 @@
       AccountId::FromUserEmail(kUser2Email));
   EXPECT_FALSE(
       user2_pref_service()->GetBoolean(prefs::kShownPaletteWelcomeBubble));
-  welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
-  EXPECT_TRUE(welcome_bubble_->bubble_shown());
+  welcome_bubble_->ShowIfNeeded();
+  EXPECT_TRUE(welcome_bubble_->GetBubbleViewForTesting());
 }
 
 TEST_F(PaletteWelcomeBubbleTest, BubbleNotShownInactiveSession) {
   GetSessionControllerClient()->SetSessionState(
       session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
-  welcome_bubble_->ShowIfNeeded(false /* shown_by_stylus */);
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
+  welcome_bubble_->ShowIfNeeded();
+  EXPECT_FALSE(welcome_bubble_->GetBubbleViewForTesting());
 }
 
 class PaletteWelcomeBubbleGuestModeTest : public AshTestBase {
@@ -163,8 +159,8 @@
 TEST_F(PaletteWelcomeBubbleGuestModeTest, BubbleNotShownForGuest) {
   auto welcome_bubble = std::make_unique<PaletteWelcomeBubble>(
       StatusAreaWidgetTestHelper::GetStatusAreaWidget()->palette_tray());
-  welcome_bubble->ShowIfNeeded(false /* shown_by_stylus */);
-  EXPECT_FALSE(welcome_bubble->bubble_shown());
+  welcome_bubble->ShowIfNeeded();
+  EXPECT_FALSE(welcome_bubble->GetBubbleViewForTesting());
 }
 
 }  // namespace ash
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index a47be4e..3ee8d940 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -13,6 +13,7 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/unified/unified_system_tray.h"
+#include "ash/system/unified/unified_system_tray_bubble.h"
 #include "ash/system/unified/unified_system_tray_view.h"
 
 using chromeos::CrasAudioHandler;
@@ -176,7 +177,7 @@
   bubble_view_->set_color(SK_ColorTRANSPARENT);
   bubble_view_->layer()->SetFillsBoundsOpaquely(false);
   bubble_view_->set_anchor_view_insets(
-      tray_->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets());
+      UnifiedSystemTrayBubble::GetAdjustedAnchorInsets(tray_, bubble_view_));
 
   bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
 
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc
index 31554699..1b6fe33 100644
--- a/ash/system/unified/unified_system_tray_bubble.cc
+++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -60,6 +60,24 @@
 
 }  // namespace
 
+// static
+gfx::Insets UnifiedSystemTrayBubble::GetAdjustedAnchorInsets(
+    UnifiedSystemTray* tray,
+    TrayBubbleView* bubble_view) {
+  gfx::Insets anchor_insets =
+      tray->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets();
+  gfx::Insets bubble_insets = bubble_view->GetBorderInsets();
+  if (tray->shelf()->IsHorizontalAlignment()) {
+    anchor_insets -=
+        gfx::Insets(kUnifiedMenuVerticalPadding - bubble_insets.bottom(), 0, 0,
+                    bubble_insets.right() + anchor_insets.right());
+  } else {
+    anchor_insets -=
+        gfx::Insets(0, 0, bubble_insets.bottom() + anchor_insets.bottom(), 0);
+  }
+  return anchor_insets;
+}
+
 UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray,
                                                  bool show_by_click)
     : controller_(
@@ -93,19 +111,8 @@
   bubble_view_->SetMaxHeight(max_height);
   bubble_view_->AddChildView(new ContainerView(unified_view_));
 
-  gfx::Insets anchor_insets =
-      tray->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets();
-  gfx::Insets bubble_insets = bubble_view_->GetBorderInsets();
-  if (tray_->shelf()->IsHorizontalAlignment()) {
-    anchor_insets -=
-        gfx::Insets(kUnifiedMenuVerticalPadding - bubble_insets.bottom(), 0, 0,
-                    bubble_insets.right() + anchor_insets.right());
-  } else {
-    anchor_insets -=
-        gfx::Insets(0, 0, bubble_insets.bottom() + anchor_insets.bottom(), 0);
-  }
-
-  bubble_view_->set_anchor_view_insets(anchor_insets);
+  bubble_view_->set_anchor_view_insets(
+      GetAdjustedAnchorInsets(tray, bubble_view_));
   bubble_view_->set_color(SK_ColorTRANSPARENT);
   bubble_view_->layer()->SetFillsBoundsOpaquely(false);
 
diff --git a/ash/system/unified/unified_system_tray_bubble.h b/ash/system/unified/unified_system_tray_bubble.h
index 33796347..9517c45 100644
--- a/ash/system/unified/unified_system_tray_bubble.h
+++ b/ash/system/unified/unified_system_tray_bubble.h
@@ -42,6 +42,11 @@
                                 public TimeToClickRecorder::Delegate,
                                 public TabletModeObserver {
  public:
+  // Return adjusted anchor insets that take into account shelf alignment and
+  // bubble insets.
+  static gfx::Insets GetAdjustedAnchorInsets(UnifiedSystemTray* tray,
+                                             TrayBubbleView* bubble_view);
+
   explicit UnifiedSystemTrayBubble(UnifiedSystemTray* tray, bool show_by_click);
   ~UnifiedSystemTrayBubble() override;
 
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 0986dfe..941b5e9 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -501,7 +501,7 @@
   SkColor GetWallpaperColor() {
     const gfx::ImageSkiaRep& representation =
         controller_->GetWallpaper().GetRepresentation(1.0f);
-    return representation.sk_bitmap().getColor(0, 0);
+    return representation.GetBitmap().getColor(0, 0);
   }
 
   // Wrapper for private ShouldCalculateColors().
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
index 85394d0d..49846e7 100644
--- a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
@@ -100,7 +100,7 @@
 // static
 uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) {
   const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f);
-  return image_rep.is_null() ? 0 : image_rep.sk_bitmap().getGenerationID();
+  return image_rep.is_null() ? 0 : image_rep.GetBitmap().getGenerationID();
 }
 
 WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
diff --git a/ash/ws/window_service_owner.cc b/ash/ws/window_service_owner.cc
index 9252c3c..e3cac53e 100644
--- a/ash/ws/window_service_owner.cc
+++ b/ash/ws/window_service_owner.cc
@@ -4,11 +4,15 @@
 
 #include "ash/ws/window_service_owner.h"
 
+#include <cstdint>
+
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/wm/non_client_frame_controller.h"
 #include "ash/ws/window_service_delegate_impl.h"
 #include "base/lazy_instance.h"
+#include "base/unguessable_token.h"
+#include "services/content/public/cpp/buildflags.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/ws/public/cpp/host/gpu_interface_provider.h"
 #include "services/ws/window_service.h"
@@ -17,8 +21,31 @@
 #include "ui/display/screen.h"
 #include "ui/wm/core/focus_controller.h"
 
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+#include "services/content/public/cpp/navigable_contents_view.h"
+#include "services/ws/remote_view_host/server_remote_view_host.h"
+#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
 namespace ash {
 
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
+namespace {
+
+std::unique_ptr<views::NativeViewHost> CreateRemoteNavigableContentsView(
+    ws::WindowService* window_service,
+    const base::UnguessableToken& embed_token) {
+  constexpr uint32_t kEmbedFlags =
+      ws::mojom::kEmbedFlagEmbedderControlsVisibility;
+  auto remote_view = std::make_unique<ws::ServerRemoteViewHost>(window_service);
+  remote_view->EmbedUsingToken(embed_token, kEmbedFlags, base::DoNothing());
+  return remote_view;
+}
+
+}  // namespace
+
+#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
 WindowServiceOwner::WindowServiceOwner(
     std::unique_ptr<ws::GpuInterfaceProvider> gpu_interface_provider)
     : window_service_delegate_(std::make_unique<WindowServiceDelegateImpl>()),
@@ -35,6 +62,11 @@
   window_service_->SetDisplayForNewWindows(
       display::Screen::GetScreen()->GetDisplayForNewWindows().id());
   RegisterWindowProperties(window_service_->property_converter());
+
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+  content::NavigableContentsView::SetRemoteViewFactory(
+      base::BindRepeating(&CreateRemoteNavigableContentsView, window_service_));
+#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
 }
 
 WindowServiceOwner::~WindowServiceOwner() = default;
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 3076ed8..c75a7db 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2201,7 +2201,6 @@
 if (is_fuchsia) {
   fidl_library("testfidl") {
     namespace = "base.fuchsia"
-    namespace_path = "base/fuchsia"
 
     sources = [
       "fuchsia/test.fidl",
@@ -2812,14 +2811,9 @@
       "strings/string16_unittest.nc",
       "task/task_traits_extension_unittest.nc",
       "task/task_traits_unittest.nc",
+      "thread_annotations_unittest.nc",
     ]
 
-    # TODO(lukasza): https://crbug.com/881875#c9: Enable lock annotations on Mac
-    # after the clang bug is fixed: https://bugs.llvm.org/show_bug.cgi?id=38896
-    if (!is_mac && !is_ios) {
-      sources += [ "thread_annotations_unittest.nc" ]
-    }
-
     deps = [
       ":base",
       ":base_unittests_tasktraits",
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index ba5d8755..f835953 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -478,7 +478,11 @@
       PartitionExcessiveAllocationSize();
     }
     new_page = PartitionDirectMap(root, flags, size);
+#if !defined(OS_MACOSX)
+    // TODO(https://crbug.com/890752): Remove this when we figure out and fix
+    // whatever is breaking on macOS.
     *is_already_zeroed = true;
+#endif
   } else if (LIKELY(this->SetNewActivePage())) {
     // First, did we find an active page in the active pages list?
     new_page = this->active_pages_head;
@@ -510,7 +514,11 @@
       void* addr = PartitionPage::ToPointer(new_page);
       root->RecommitSystemPages(addr, new_page->bucket->get_bytes_per_span());
       new_page->Reset();
+#if !defined(OS_MACOSX)
+      // TODO(https://crbug.com/890752): Remove this when we figure out and fix
+      // whatever is breaking on macOS.
       *is_already_zeroed = true;
+#endif
     }
     DCHECK(new_page);
   } else {
@@ -520,7 +528,11 @@
     if (LIKELY(raw_pages != nullptr)) {
       new_page = PartitionPage::FromPointerNoAlignmentCheck(raw_pages);
       InitializeSlotSpan(new_page);
+#if !defined(OS_MACOSX)
+      // TODO(https://crbug.com/890752): Remove this when we figure out and fix
+      // whatever is breaking on macOS.
       *is_already_zeroed = true;
+#endif
     }
   }
 
diff --git a/base/allocator/partition_allocator/partition_root_base.h b/base/allocator/partition_allocator/partition_root_base.h
index 0d22c09..e1392d0 100644
--- a/base/allocator/partition_allocator/partition_root_base.h
+++ b/base/allocator/partition_allocator/partition_root_base.h
@@ -10,6 +10,7 @@
 #include "base/allocator/partition_allocator/partition_bucket.h"
 #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
 #include "base/allocator/partition_allocator/partition_page.h"
+#include "build/build_config.h"
 
 namespace base {
 namespace internal {
@@ -141,6 +142,11 @@
   }
   PartitionCookieWriteValue(char_ret + kCookieSize + no_cookie_size);
 #else
+#if defined(OS_MACOSX)
+  // TODO(https://crbug.com/890752): Remove this when we figure out and fix
+  // whatever is breaking on macOS.
+  is_already_zeroed = false;
+#endif
   if (ret && zero_fill && !is_already_zeroed) {
     memset(ret, 0, size);
   }
diff --git a/base/thread_annotations.h b/base/thread_annotations.h
index d9bf6d4..bba3ed7 100644
--- a/base/thread_annotations.h
+++ b/base/thread_annotations.h
@@ -34,9 +34,7 @@
 
 #include "build/build_config.h"
 
-// TODO(lukasza): https://crbug.com/881875#c9: Enable lock annotations on Mac
-// after the clang bug is fixed: https://bugs.llvm.org/show_bug.cgi?id=38896
-#if defined(__clang__) && !defined(OS_MACOSX)
+#if defined(__clang__)
 #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
 #else
 #define THREAD_ANNOTATION_ATTRIBUTE__(x)  // no-op
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index 3a611b4..13eb7b1d 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -307,7 +307,8 @@
           changed_paths.update(os.path.join(generated_java_dir, f)
                                for f in changes.IterChangedSubpaths(srcjar))
         extracted_files = build_utils.ExtractAll(
-            srcjar, path=generated_java_dir, pattern='*.java')
+            srcjar, no_clobber=not incremental, path=generated_java_dir,
+            pattern='*.java')
         for path in extracted_files:
           # We want the path inside the srcjar so the viewer can have a tree
           # structure.
diff --git a/build/config/fuchsia/fidl_library.gni b/build/config/fuchsia/fidl_library.gni
index 6259640..6fbb28b6 100644
--- a/build/config/fuchsia/fidl_library.gni
+++ b/build/config/fuchsia/fidl_library.gni
@@ -12,13 +12,6 @@
 #   library_name   - (optional) Name of the library. target_name is used if name
 #                    is not specified explicitly.
 #   namespace      - (optional) Namespace for the library.
-#   namespace_path - (optional) namespace with '.' are replaced with '/', e.g.
-#                    if namespace is "fuchsia.foo", then namespace_path must be
-#                    set to "fuchsia/foo". This parameter must be specified when
-#                    namespace is specified.
-#                    TODO(sergeyu): In theory namespace_path can be generated
-#                    from name, but GN doesn't provide any tools to perform this
-#                    conversion without invoking a python script.
 #   deps           - (optional) List of other fidl_library() targets that this
 #                    FIDL library depends on.
 #
@@ -26,11 +19,7 @@
 # files.
 
 template("fidl_library") {
-  forward_variables_from(invoker,
-                         [
-                           "namespace",
-                           "namespace_path",
-                         ])
+  forward_variables_from(invoker, [ "namespace" ])
 
   _library_basename = target_name
   if (defined(invoker.library_name)) {
@@ -38,10 +27,9 @@
   }
 
   if (defined(namespace)) {
-    assert(defined(namespace_path),
-           "FIDL libraries with namespace must specify namespace_path")
     _library_name = "${namespace}.${_library_basename}"
-    _library_path = "${namespace_path}/${_library_basename}"
+    _namespace_path = string_replace(namespace, ".", "/")
+    _library_path = "${_namespace_path}/${_library_basename}"
   } else {
     _library_name = _library_basename
     _library_path = _library_basename
diff --git a/build/config/fuchsia/testing_sandbox_policy b/build/config/fuchsia/testing_sandbox_policy
index 401a6d9..b0ed870 100644
--- a/build/config/fuchsia/testing_sandbox_policy
+++ b/build/config/fuchsia/testing_sandbox_policy
@@ -8,6 +8,8 @@
       "fuchsia.net.LegacySocketProvider",
       "fuchsia.netstack.Netstack",
       "fuchsia.process.Launcher",
+      "fuchsia.ui.input.ImeService",
+      "fuchsia.ui.input.ImeVisibilityService",
       "fuchsia.ui.policy.Presenter",
       "fuchsia.ui.scenic.Scenic",
       "fuchsia.ui.viewsv1.ViewManager",
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index a6d0595e..45c07cf 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-065fd902445d69829dddf465c524700b375de112
\ No newline at end of file
+065fd902445d69829dddf465c524700b375de112
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index abc96619..c19eb73 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-4dfe28e996ad104738f8abdb1f27680b369dba9a
\ No newline at end of file
+4dfe28e996ad104738f8abdb1f27680b369dba9a
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py
index 8305064..4718aae 100755
--- a/build/fuchsia/update_sdk.py
+++ b/build/fuchsia/update_sdk.py
@@ -75,7 +75,8 @@
   # Previously SDK was unpacked in //third_party/fuchsia-sdk instead of
   # //third_party/fuchsia-sdk/sdk . Remove the old files if they are still
   # there.
-  Cleanup(os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk'))
+  sdk_root = os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk')
+  Cleanup(sdk_root)
 
   hash_file = GetSdkHashForPlatform()
   with open(hash_file, 'r') as f:
@@ -85,14 +86,15 @@
     print >>sys.stderr, 'No SHA1 found in %s' % hash_file
     return 1
 
-  output_dir = os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk',
-                            'sdk')
+  output_dir = os.path.join(sdk_root, 'sdk')
 
   hash_filename = os.path.join(output_dir, '.hash')
   if os.path.exists(hash_filename):
     with open(hash_filename, 'r') as f:
       if f.read().strip() == sdk_hash:
-        # Nothing to do.
+        # Nothing to do. Generate sdk/BUILD.gn anyways, in case the conversion
+        # script changed.
+        subprocess.check_call([os.path.join(sdk_root, 'gen_build_defs.py')])
         return 0
 
   print 'Downloading SDK %s...' % sdk_hash
@@ -113,6 +115,9 @@
   finally:
     os.remove(tmp)
 
+  # Generate sdk/BUILD.gn.
+  subprocess.check_call([os.path.join(sdk_root, 'gen_build_defs.py')])
+
   with open(hash_filename, 'w') as f:
     f.write(sdk_hash)
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index b95bb22..acabfb8 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1036,7 +1036,7 @@
     }
   }
 
-  if (should_bundle_widevine_cdm) {
+  if (bundle_widevine_cdm) {
     bundle_data("widevine_cdm_library_binaries") {
       sources = [
         "$root_out_dir/$widevine_cdm_path/libwidevinecdm.dylib",
@@ -1067,7 +1067,7 @@
   }
 
   group("widevine_cdm_library") {
-    if (should_bundle_widevine_cdm) {
+    if (bundle_widevine_cdm) {
       deps = [
         ":widevine_cdm_library_binaries",
         ":widevine_cdm_library_manifest",
diff --git a/chrome/VERSION b/chrome/VERSION
index f9d1cce..86eb119 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=71
 MINOR=0
-BUILD=3568
+BUILD=3569
 PATCH=0
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 7cc262c..9635c116 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -120,7 +120,6 @@
         private final Resources mResources;
         private final UiConfig mUiConfig;
         private final int mCornerRadius;
-        private final Drawable mCardBackground;
         private final int mCardMargin;
         private final int mCardWideMargin;
 
@@ -129,8 +128,6 @@
             mUiConfig = uiConfig;
             mCornerRadius = mResources.getDimensionPixelSize(
                     R.dimen.content_suggestions_card_modern_corner_radius);
-            mCardBackground = ApiCompatibilityUtils.getDrawable(
-                    mResources, R.drawable.content_card_modern_background);
             mCardMargin = mResources.getDimensionPixelSize(
                     R.dimen.content_suggestions_card_modern_margin);
             mCardWideMargin =
@@ -144,7 +141,8 @@
 
         @Override
         public Drawable getCardBackground() {
-            return mCardBackground;
+            return ApiCompatibilityUtils.getDrawable(
+                    mResources, R.drawable.content_card_modern_background);
         }
 
         @Override
diff --git a/chrome/android/java/res/layout-sw600dp/location_bar.xml b/chrome/android/java/res/layout-sw600dp/location_bar.xml
index 47d81308..5c2a4b7 100644
--- a/chrome/android/java/res/layout-sw600dp/location_bar.xml
+++ b/chrome/android/java/res/layout-sw600dp/location_bar.xml
@@ -20,7 +20,7 @@
             android:src="@drawable/ic_omnibox_page"
             android:scaleType="center"
             android:contentDescription="@string/accessibility_toolbar_btn_site_info"/>
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/security_button"
             style="@style/LocationBarButton"
             android:layout_width="match_parent"
@@ -29,7 +29,7 @@
             android:layout_gravity="center"
             android:alpha="0"
             android:visibility="invisible"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
     </FrameLayout>
 
     <include layout="@layout/location_bar_status" />
diff --git a/chrome/android/java/res/layout/accept_languages_item.xml b/chrome/android/java/res/layout/accept_languages_item.xml
index 48c794e..dd9fd20a 100644
--- a/chrome/android/java/res/layout/accept_languages_item.xml
+++ b/chrome/android/java/res/layout/accept_languages_item.xml
@@ -13,10 +13,10 @@
     android:paddingEnd="@dimen/pref_languages_padding"
     style="@style/ListItemContainer">
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/icon_view"
         style="@style/ListItemStartIcon"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 
     <LinearLayout
         android:layout_width="0dp"
@@ -48,6 +48,6 @@
         android:background="@null"
         android:src="@drawable/ic_more_vert_black_24dp"
         app:menuWidth="@dimen/pref_languages_item_popup_width"
-        app:tint="@color/dark_mode_tint"
+        app:chrometint="@color/dark_mode_tint"
         tools:ignore="ContentDescription" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/accessibility_tab_switcher.xml b/chrome/android/java/res/layout/accessibility_tab_switcher.xml
index 7b2057b..a8ba536d 100644
--- a/chrome/android/java/res/layout/accessibility_tab_switcher.xml
+++ b/chrome/android/java/res/layout/accessibility_tab_switcher.xml
@@ -54,14 +54,14 @@
         android:id="@+id/button_wrapper"
         android:visibility="gone">
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/standard_tabs_button"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:background="@drawable/btn_bg_holo_active"
             android:src="@drawable/btn_normal_tabs"
-            app:tint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             android:contentDescription="@string/accessibility_tab_switcher_standard_stack"
             style="?android:attr/borderlessButtonStyle" />
 
@@ -71,13 +71,13 @@
             android:layout_gravity="center_vertical"
             android:background="#292929" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/incognito_tabs_button"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:src="@drawable/btn_incognito_tabs"
-            app:tint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             android:background="@drawable/btn_bg_holo"
             android:contentDescription="@string/accessibility_tab_switcher_incognito_stack"
             style="?android:attr/borderlessButtonStyle" />
diff --git a/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml b/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
index 62e6b35..cf23a9b 100644
--- a/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
+++ b/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
@@ -9,6 +9,7 @@
 <org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelListItem
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/list_item_frame"
     android:layout_width="match_parent"
     android:layout_height="@dimen/accessibility_tab_height">
@@ -19,13 +20,13 @@
         <include layout="@layout/modern_list_item_view" />
 
         <!-- TODO(huayinz): Remove custom padding after https://crbug.com/746712 is fixed. -->
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/close_btn_modern"
             style="@style/ListItemEndIconSmall"
             android:paddingStart="23dp"
             android:paddingEnd="13dp"
             android:src="@drawable/btn_delete_24dp"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
     </LinearLayout>
 
     <LinearLayout
diff --git a/chrome/android/java/res/layout/bottom_toolbar.xml b/chrome/android/java/res/layout/bottom_toolbar.xml
index f69fdcfa..c84fd09 100644
--- a/chrome/android/java/res/layout/bottom_toolbar.xml
+++ b/chrome/android/java/res/layout/bottom_toolbar.xml
@@ -5,11 +5,12 @@
 
 <org.chromium.chrome.browser.toolbar.ScrollingBottomViewResourceFrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/bottom_toolbar_control_container"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/bottom_toolbar_height">
+    android:minHeight="@dimen/bottom_toolbar_height" >
 
     <ImageView
         android:id="@+id/bottom_toolbar_top_shadow"
@@ -39,7 +40,7 @@
                 android:layout_height="1dp"
                 android:layout_weight="1" />
 
-            <android.support.v7.widget.AppCompatImageButton
+            <org.chromium.chrome.browser.widget.TintedImageButton
                 android:id="@+id/first_button"
                 style="@style/ToolbarButton"
                 android:layout_gravity="center" />
@@ -49,7 +50,7 @@
                 android:layout_height="1dp"
                 android:layout_weight="1" />
 
-            <android.support.v7.widget.AppCompatImageButton
+            <org.chromium.chrome.browser.widget.TintedImageButton
                 android:id="@+id/second_button"
                 style="@style/ToolbarButton"
                 android:layout_gravity="center" />
diff --git a/chrome/android/java/res/layout/chip.xml b/chrome/android/java/res/layout/chip.xml
index d158383..2bcb5390 100644
--- a/chrome/android/java/res/layout/chip.xml
+++ b/chrome/android/java/res/layout/chip.xml
@@ -13,14 +13,14 @@
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:background="@drawable/chip_bg">
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/icon"
         android:layout_width="20dp"
         android:layout_height="20dp"
         android:layout_marginStart="8dp"
         android:gravity="center"
         android:scaleType="fitCenter"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
     <TextView
         android:id="@+id/text"
         android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/clear_storage.xml b/chrome/android/java/res/layout/clear_storage.xml
index 671db1d9..de067072 100644
--- a/chrome/android/java/res/layout/clear_storage.xml
+++ b/chrome/android/java/res/layout/clear_storage.xml
@@ -3,11 +3,11 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<android.support.v7.widget.AppCompatImageView
+<org.chromium.chrome.browser.widget.TintedImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:contentDescription="@string/webstorage_clear_data_dialog_title"
     android:src="@drawable/ic_delete_white_24dp"
-    app:tint="@color/blue_mode_tint"/>
+    app:chrometint="@color/blue_mode_tint"/>
diff --git a/chrome/android/java/res/layout/content_suggestions_card_modern_reversed.xml b/chrome/android/java/res/layout/content_suggestions_card_modern_reversed.xml
index a330626..7d81b4b 100644
--- a/chrome/android/java/res/layout/content_suggestions_card_modern_reversed.xml
+++ b/chrome/android/java/res/layout/content_suggestions_card_modern_reversed.xml
@@ -100,7 +100,7 @@
             </LinearLayout>
         </LinearLayout>
 
-        <android.support.v7.widget.AppCompatImageView
+        <org.chromium.chrome.browser.widget.TintedImageView
             android:id="@+id/article_thumbnail"
             android:layout_width="@dimen/snippets_thumbnail_size"
             android:layout_height="@dimen/snippets_thumbnail_size"
diff --git a/chrome/android/java/res/layout/contextual_suggestions_card_modern.xml b/chrome/android/java/res/layout/contextual_suggestions_card_modern.xml
index a5f55d9..e8baf25 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_card_modern.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_card_modern.xml
@@ -99,6 +99,7 @@
                 android:layout_marginStart="6dp"
                 android:contentDescription="@string/accessibility_ntp_offline_badge"
                 android:visibility="gone"
-                android:src="@drawable/offline_pin_round" />
+                android:src="@drawable/offline_pin_round"
+                app:chrometint="@color/default_icon_color" />
         </LinearLayout>
 </RelativeLayout>
diff --git a/chrome/android/java/res/layout/contextual_suggestions_card_modern_alternate.xml b/chrome/android/java/res/layout/contextual_suggestions_card_modern_alternate.xml
index 22d1da9..3dbfc54 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_card_modern_alternate.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_card_modern_alternate.xml
@@ -67,7 +67,8 @@
             android:layout_marginStart="6dp"
             android:contentDescription="@string/accessibility_ntp_offline_badge"
             android:visibility="gone"
-            android:src="@drawable/offline_pin_round" />
+            android:src="@drawable/offline_pin_round"
+            app:chrometint="@color/default_icon_color" />
     </LinearLayout>
 
     <LinearLayout
diff --git a/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
index 797e7def..928d7c4 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
@@ -45,10 +45,10 @@
             android:layout_height="match_parent"
             android:background="?attr/selectableItemBackground"
             android:src="@drawable/ic_more_vert_black_24dp"
-            app:tint="@color/dark_mode_tint"
+            app:chrometint="@color/dark_mode_tint"
             tools:ignore="ContentDescription" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/close_button"
             android:layout_height="match_parent"
             android:layout_width="@dimen/contextual_suggestions_toolbar_icon_size"
@@ -56,7 +56,7 @@
             android:src="@drawable/btn_close"
             android:scaleType="center"
             android:contentDescription="@string/contextual_suggestions_close_button_description"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
    </LinearLayout>
 
    <ImageView
diff --git a/chrome/android/java/res/layout/custom_tabs_toolbar.xml b/chrome/android/java/res/layout/custom_tabs_toolbar.xml
index efae5b1..981f544 100644
--- a/chrome/android/java/res/layout/custom_tabs_toolbar.xml
+++ b/chrome/android/java/res/layout/custom_tabs_toolbar.xml
@@ -19,7 +19,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical" >
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/security_button"
             style="@style/LocationBarButton"
             android:layout_width="@dimen/location_bar_icon_width"
@@ -27,7 +27,7 @@
             android:layout_gravity="center_vertical"
             android:scaleType="center"
             android:visibility="invisible"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
         <view
             class="org.chromium.chrome.browser.toolbar.CustomTabToolbar$InterceptTouchLayout"
             android:id="@+id/title_url_container"
@@ -96,7 +96,7 @@
         android:layout_gravity="center_vertical|end"
         android:gravity="center_vertical"
         android:orientation="horizontal" />
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/menu_button"
         style="@style/ToolbarButton"
         android:layout_gravity="center_vertical|end"
@@ -105,5 +105,5 @@
         android:src="@drawable/ic_more_vert_black_24dp"
         android:contentDescription="@string/accessibility_toolbar_btn_menu"
         android:background="@null"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 </org.chromium.chrome.browser.toolbar.CustomTabToolbar>
diff --git a/chrome/android/java/res/layout/empty_background_view_tablet.xml b/chrome/android/java/res/layout/empty_background_view_tablet.xml
index dd8806e6..212b92a 100644
--- a/chrome/android/java/res/layout/empty_background_view_tablet.xml
+++ b/chrome/android/java/res/layout/empty_background_view_tablet.xml
@@ -43,7 +43,7 @@
             android:background="?attr/selectableItemBackground"
             android:contentDescription="@string/accessibility_tabstrip_btn_incognito_toggle_standard"
             />
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/empty_menu_button"
             style="@style/ToolbarButton"
             android:layout_width="48dp"
@@ -52,7 +52,7 @@
             android:scaleType="center"
             android:contentDescription="@string/accessibility_toolbar_btn_menu"
             android:paddingStart="2dp"
-            app:tint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             />
     </LinearLayout>
 </org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewTablet>
diff --git a/chrome/android/java/res/layout/experimental_toolbar_button.xml b/chrome/android/java/res/layout/experimental_toolbar_button.xml
index 8c7f19b..1dbeb1f 100644
--- a/chrome/android/java/res/layout/experimental_toolbar_button.xml
+++ b/chrome/android/java/res/layout/experimental_toolbar_button.xml
@@ -3,10 +3,11 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<android.support.v7.widget.AppCompatImageButton
+<org.chromium.chrome.browser.widget.TintedImageButton
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     style="@style/ToolbarButton"
     android:layout_gravity="top"
     android:paddingStart="8dp"
-    tools:ignore="ContentDescription"/>
\ No newline at end of file
+    tools:ignore="ContentDescription" />
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/find_in_page.xml b/chrome/android/java/res/layout/find_in_page.xml
index caa4296..acde96ff 100644
--- a/chrome/android/java/res/layout/find_in_page.xml
+++ b/chrome/android/java/res/layout/find_in_page.xml
@@ -41,25 +41,25 @@
         android:layout_marginBottom="8dp"
         android:background="#000000"
         android:alpha="0.1" />
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/find_prev_button"
         style="@style/ToolbarButton"
         android:layout_height="match_parent"
         android:src="@drawable/ic_expand_less_black_24dp"
         android:contentDescription="@string/accessibility_find_toolbar_btn_prev"
-        app:tint="@color/dark_mode_tint" />
-    <android.support.v7.widget.AppCompatImageButton
+        app:chrometint="@color/dark_mode_tint" />
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/find_next_button"
         style="@style/ToolbarButton"
         android:layout_height="match_parent"
         android:src="@drawable/ic_expand_more_black_24dp"
         android:contentDescription="@string/accessibility_find_toolbar_btn_next"
-        app:tint="@color/dark_mode_tint" />
-    <android.support.v7.widget.AppCompatImageButton
+        app:chrometint="@color/dark_mode_tint" />
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/close_find_button"
         style="@style/ToolbarButton"
         android:layout_height="match_parent"
         android:src="@drawable/btn_close"
         android:contentDescription="@string/close"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/history_item_view.xml b/chrome/android/java/res/layout/history_item_view.xml
index b4b1c99..c2bd348 100644
--- a/chrome/android/java/res/layout/history_item_view.xml
+++ b/chrome/android/java/res/layout/history_item_view.xml
@@ -15,12 +15,12 @@
 
         <include layout="@layout/modern_list_item_view" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/remove"
             style="@style/ListItemEndIconSmall"
             android:contentDescription="@string/remove"
             android:src="@drawable/btn_delete_24dp"
-            app:tint="@color/light_icon_color" />
+            app:chrometint="@color/light_icon_color" />
     </LinearLayout>
 
 </org.chromium.chrome.browser.history.HistoryItemView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/icon_row_menu_footer.xml b/chrome/android/java/res/layout/icon_row_menu_footer.xml
index 9b18e375..02571a7 100644
--- a/chrome/android/java/res/layout/icon_row_menu_footer.xml
+++ b/chrome/android/java/res/layout/icon_row_menu_footer.xml
@@ -18,31 +18,31 @@
         android:orientation="horizontal"
         android:id="@+id/menu_items" >
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/forward_menu_id"
             style="@style/OverflowMenuButton"
             android:src="@drawable/btn_forward"
             android:contentDescription="@string/accessibility_menu_forward" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/bookmark_this_page_id"
             style="@style/OverflowMenuButton"
             android:src="@drawable/btn_star"
             android:contentDescription="@string/accessibility_menu_bookmark" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/offline_page_id"
             style="@style/OverflowMenuButton"
             android:src="@drawable/ic_file_download_white_24dp"
             android:contentDescription="@string/download_page" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/info_menu_id"
             style="@style/OverflowMenuButton"
             android:src="@drawable/btn_info"
             android:contentDescription="@string/accessibility_menu_info" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/reload_menu_id"
             style="@style/OverflowMenuButton"
             android:src="@drawable/btn_reload_stop"
diff --git a/chrome/android/java/res/layout/icon_row_menu_item.xml b/chrome/android/java/res/layout/icon_row_menu_item.xml
index 7da9b78..43442e6 100644
--- a/chrome/android/java/res/layout/icon_row_menu_item.xml
+++ b/chrome/android/java/res/layout/icon_row_menu_item.xml
@@ -6,28 +6,29 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeightSmall"
     android:layout_gravity="top|start"
     android:orientation="horizontal">
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button_one"
         style="@style/OverflowMenuButton" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button_two"
         style="@style/OverflowMenuButton" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button_three"
         style="@style/OverflowMenuButton" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button_four"
         style="@style/OverflowMenuButton" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button_five"
         style="@style/OverflowMenuButton" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/infobar_translate_compact_content.xml b/chrome/android/java/res/layout/infobar_translate_compact_content.xml
index 41f8e9bf..30967f37 100644
--- a/chrome/android/java/res/layout/infobar_translate_compact_content.xml
+++ b/chrome/android/java/res/layout/infobar_translate_compact_content.xml
@@ -23,7 +23,7 @@
         app:tabGravity="fill"
         app:tabMode="scrollable" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/translate_infobar_menu_button"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
@@ -33,5 +33,5 @@
         android:background="?attr/selectableItemBackground"
         android:contentDescription="@string/accessibility_toolbar_btn_menu"
         android:src="@drawable/ic_more_vert_black_24dp"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/list_menu_button.xml b/chrome/android/java/res/layout/list_menu_button.xml
index 8e6de6e..5672e8ca 100644
--- a/chrome/android/java/res/layout/list_menu_button.xml
+++ b/chrome/android/java/res/layout/list_menu_button.xml
@@ -16,5 +16,5 @@
     android:paddingEnd="@dimen/selectable_list_layout_row_padding"
     android:background="@null"
     android:src="@drawable/ic_more_vert_black_24dp"
-    app:tint="@color/dark_mode_tint"
+    app:chrometint="@color/dark_mode_tint"
     tools:ignore="ContentDescription" />
diff --git a/chrome/android/java/res/layout/list_selection_handle_view.xml b/chrome/android/java/res/layout/list_selection_handle_view.xml
index a3360a1..3367d7e8 100644
--- a/chrome/android/java/res/layout/list_selection_handle_view.xml
+++ b/chrome/android/java/res/layout/list_selection_handle_view.xml
@@ -9,18 +9,18 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools">
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/check"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:scaleType="center"
         android:background="@drawable/list_item_icon_modern_bg"
         android:visibility="gone"
-        app:tint="@color/white_mode_tint"
+        app:chrometint="@color/white_mode_tint"
         app:layout_gravity="center"
         tools:ignore="ContentDescription" />
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/circle"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -28,7 +28,7 @@
         android:background="@null"
         android:src="@drawable/download_circular_selector_transparent"
         android:visibility="gone"
-        app:tint="@null"
+        app:chrometint="@null"
         tools:ignore="ContentDescription"/>
 
 </merge>
diff --git a/chrome/android/java/res/layout/location_bar_base.xml b/chrome/android/java/res/layout/location_bar_base.xml
index 4970595..7d9bc9f 100644
--- a/chrome/android/java/res/layout/location_bar_base.xml
+++ b/chrome/android/java/res/layout/location_bar_base.xml
@@ -24,7 +24,7 @@
             android:scaleType="center"
             android:contentDescription="@string/accessibility_toolbar_btn_site_info" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/security_button"
             style="@style/LocationBarButton"
             android:layout_width="match_parent"
@@ -33,7 +33,7 @@
             android:layout_gravity="center"
             android:alpha="0"
             android:visibility="invisible"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
     </FrameLayout>
 
diff --git a/chrome/android/java/res/layout/menu_button.xml b/chrome/android/java/res/layout/menu_button.xml
index f4808b1..442f408 100644
--- a/chrome/android/java/res/layout/menu_button.xml
+++ b/chrome/android/java/res/layout/menu_button.xml
@@ -12,13 +12,13 @@
        android:layout_height="wrap_content"
        android:id="@+id/menu_button_wrapper">
 
-       <android.support.v7.widget.AppCompatImageButton
+       <org.chromium.chrome.browser.widget.TintedImageButton
            android:id="@+id/menu_button"
            style="@style/ToolbarMenuButtonPhone"
            android:src="@drawable/ic_more_vert_black_24dp"
            android:contentDescription="@string/accessibility_toolbar_btn_menu"
            android:layout_gravity="center"
-           app:tint="@color/dark_mode_tint" />
+           app:chrometint="@color/dark_mode_tint" />
 
        <ImageView
            android:id="@+id/menu_badge"
diff --git a/chrome/android/java/res/layout/modern_list_item_view.xml b/chrome/android/java/res/layout/modern_list_item_view.xml
index 0180c25..3616a79 100644
--- a/chrome/android/java/res/layout/modern_list_item_view.xml
+++ b/chrome/android/java/res/layout/modern_list_item_view.xml
@@ -6,7 +6,7 @@
 <merge
     xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/icon_view"
         style="@style/ListItemStartIcon" />
 
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml
index 722604e4..7c0158c 100644
--- a/chrome/android/java/res/layout/new_tab_page_layout.xml
+++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -54,13 +54,13 @@
             android:gravity="center_vertical"
             android:inputType="text"
             android:singleLine="true" />
-        <android.support.v7.widget.AppCompatImageView
+        <org.chromium.chrome.browser.widget.TintedImageView
             android:id="@+id/voice_search_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:contentDescription="@string/accessibility_toolbar_btn_mic"
             android:src="@drawable/btn_mic"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
     </view>
 
     <ViewStub
diff --git a/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml b/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml
index 5f6180b..73cea57 100644
--- a/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml
+++ b/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml
@@ -17,7 +17,7 @@
         android:layout_weight="1"
         android:textAppearance="@style/TextAppearance.PreferenceMediumText" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/password_entry_editor_copy"
         android:background="?attr/selectableItemBackground"
         android:layout_width="wrap_content"
@@ -25,7 +25,7 @@
         android:layout_gravity="end"
         android:layout_marginTop="15dp"
         android:layout_marginEnd="15dp"
-        app:tint="@color/dark_mode_tint"
+        app:chrometint="@color/dark_mode_tint"
         android:contentDescription="@string/password_entry_editor_copy_stored_username"
         style="?android:attr/buttonStyleSmall" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/password_entry_editor_interactive.xml b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
index efa7efb..97f3535c 100644
--- a/chrome/android/java/res/layout/password_entry_editor_interactive.xml
+++ b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
@@ -59,7 +59,7 @@
                     android:layout_weight="1"
                     android:textAppearance="@style/TextAppearance.PreferenceMediumText" />
 
-                <android.support.v7.widget.AppCompatImageButton
+                <org.chromium.chrome.browser.widget.TintedImageButton
                     android:id="@+id/password_entry_editor_view_password"
                     android:background="?attr/selectableItemBackground"
                     android:layout_width="wrap_content"
@@ -68,11 +68,11 @@
                     android:layout_marginTop="15dp"
                     android:layout_marginEnd="15dp"
                     app:srcCompat="@drawable/ic_visibility_black"
-                    app:tint="@color/dark_mode_tint"
+                    app:chrometint="@color/dark_mode_tint"
                     android:contentDescription="@string/password_entry_editor_view_stored_password"
                     style="?android:attr/buttonStyleSmall" />
 
-                <android.support.v7.widget.AppCompatImageButton
+                <org.chromium.chrome.browser.widget.TintedImageButton
                     android:id="@+id/password_entry_editor_copy_password"
                     android:background="?attr/selectableItemBackground"
                     android:layout_width="wrap_content"
@@ -80,7 +80,7 @@
                     android:layout_gravity="end"
                     android:layout_marginTop="15dp"
                     android:layout_marginEnd="15dp"
-                    app:tint="@color/dark_mode_tint"
+                    app:chrometint="@color/dark_mode_tint"
                     android:contentDescription="@string/password_entry_editor_copy_stored_password"
                     style="?android:attr/buttonStyleSmall" />
             </LinearLayout>
diff --git a/chrome/android/java/res/layout/search_toolbar.xml b/chrome/android/java/res/layout/search_toolbar.xml
index c2088a4a..92ab49a 100644
--- a/chrome/android/java/res/layout/search_toolbar.xml
+++ b/chrome/android/java/res/layout/search_toolbar.xml
@@ -24,7 +24,7 @@
         android:textAppearance="@style/BlackTitle1"
         android:textColorHint="@color/search_box_hint"/>
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/clear_text_button"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
@@ -35,5 +35,5 @@
         android:scaleType="center"
         android:contentDescription="@string/accessibility_toolbar_btn_delete_url"
         android:visibility="invisible"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/textbubble_text_with_image.xml b/chrome/android/java/res/layout/textbubble_text_with_image.xml
index 24332f9..2f12ec6 100644
--- a/chrome/android/java/res/layout/textbubble_text_with_image.xml
+++ b/chrome/android/java/res/layout/textbubble_text_with_image.xml
@@ -16,14 +16,14 @@
     android:padding="16dp"
     android:gravity="center" >
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/image"
         android:layout_width="20sp"
         android:layout_height="20sp"
         android:layout_marginEnd="12dp"
         tools:ignore="ContentDescription"
         android:scaleType="centerInside"
-        app:tint="@color/white_mode_tint" />
+        app:chrometint="@color/white_mode_tint" />
 
     <TextView
         android:id="@+id/message"
diff --git a/chrome/android/java/res/layout/title_button_menu_item.xml b/chrome/android/java/res/layout/title_button_menu_item.xml
index 7f91b77..423c0ba2 100644
--- a/chrome/android/java/res/layout/title_button_menu_item.xml
+++ b/chrome/android/java/res/layout/title_button_menu_item.xml
@@ -11,8 +11,9 @@
      * A text label with an icon
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="?android:attr/listPreferredItemHeightSmall">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/listPreferredItemHeightSmall">
     <TextView
         android:id="@+id/title"
         android:layout_width="0dp"
@@ -40,7 +41,7 @@
         android:src="?android:attr/listChoiceIndicatorMultiple" />
 
     <!-- Displays an icon. -->
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/button"
         android:layout_width="56dp"
         android:layout_height="match_parent"
diff --git a/chrome/android/java/res/layout/toolbar_phone.xml b/chrome/android/java/res/layout/toolbar_phone.xml
index 1751858c..47f6ec5 100644
--- a/chrome/android/java/res/layout/toolbar_phone.xml
+++ b/chrome/android/java/res/layout/toolbar_phone.xml
@@ -30,7 +30,7 @@
         android:src="@drawable/btn_toolbar_home"
         android:contentDescription="@string/accessibility_toolbar_btn_home"
         android:visibility="gone"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 
     <org.chromium.chrome.browser.omnibox.LocationBarPhone
         android:id="@+id/location_bar"
diff --git a/chrome/android/java/res/layout/toolbar_tablet.xml b/chrome/android/java/res/layout/toolbar_tablet.xml
index d9fbd76..42b2376 100644
--- a/chrome/android/java/res/layout/toolbar_tablet.xml
+++ b/chrome/android/java/res/layout/toolbar_tablet.xml
@@ -28,28 +28,28 @@
             android:src="@drawable/btn_toolbar_home"
             android:contentDescription="@string/accessibility_toolbar_btn_home"
             android:visibility="gone"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/back_button"
             style="@style/ToolbarButton"
             android:src="@drawable/btn_back"
             android:contentDescription="@string/accessibility_toolbar_btn_back"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/forward_button"
             style="@style/ToolbarButton"
             android:src="@drawable/btn_forward"
             android:contentDescription="@string/accessibility_toolbar_btn_forward"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/refresh_button"
             style="@style/ToolbarButton"
             android:src="@drawable/btn_reload_stop"
             android:contentDescription="@string/accessibility_btn_refresh"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
         <org.chromium.chrome.browser.omnibox.LocationBarTablet
             android:id="@+id/location_bar"
@@ -72,12 +72,12 @@
             android:layout_height="wrap_content"
             android:id="@+id/menu_button_wrapper" >
 
-            <android.support.v7.widget.AppCompatImageButton
+            <org.chromium.chrome.browser.widget.TintedImageButton
                 android:id="@+id/menu_button"
                 style="@style/ToolbarMenuButtonTablet"
                 android:src="@drawable/ic_more_vert_black_24dp"
                 android:contentDescription="@string/accessibility_toolbar_btn_menu"
-                app:tint="@color/dark_mode_tint" />
+                app:chrometint="@color/dark_mode_tint" />
 
             <ImageView
                 android:id="@+id/menu_badge"
diff --git a/chrome/android/java/res/layout/translate_menu_item_checked.xml b/chrome/android/java/res/layout/translate_menu_item_checked.xml
index 3115270..c5b1ea62 100644
--- a/chrome/android/java/res/layout/translate_menu_item_checked.xml
+++ b/chrome/android/java/res/layout/translate_menu_item_checked.xml
@@ -26,14 +26,14 @@
             android:paddingTop="13dp"
             android:paddingBottom="13dp"
             android:paddingEnd="16dp" />
-        <android.support.v7.widget.AppCompatImageView
+        <org.chromium.chrome.browser.widget.TintedImageView
             android:id="@+id/menu_item_icon"
             android:src="@drawable/ic_check_googblue_24dp"
             android:layout_width="24dp"
             android:layout_height="match_parent"
             android:layout_gravity="end"
             android:gravity="center_vertical"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
     </LinearLayout>
 
diff --git a/chrome/android/java/res/layout/update_menu_item.xml b/chrome/android/java/res/layout/update_menu_item.xml
index 98b05087..f2f8a1b 100644
--- a/chrome/android/java/res/layout/update_menu_item.xml
+++ b/chrome/android/java/res/layout/update_menu_item.xml
@@ -41,6 +41,6 @@
         android:layout_height="match_parent"
         android:layout_gravity="end"
         android:gravity="center_vertical"
-        app:tint="@null" />
+        app:chrometint="@null" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/url_action_container.xml b/chrome/android/java/res/layout/url_action_container.xml
index 5756cf2a..53dbc0e4 100644
--- a/chrome/android/java/res/layout/url_action_container.xml
+++ b/chrome/android/java/res/layout/url_action_container.xml
@@ -4,7 +4,8 @@
      found in the LICENSE file. -->
 
 <merge
-    xmlns:android="http://schemas.android.com/apk/res/android">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <LinearLayout android:id="@+id/url_action_container"
         android:layout_width="wrap_content"
@@ -12,27 +13,27 @@
         android:layout_gravity="end|center_vertical"
         android:orientation="horizontal" >
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/delete_button"
             style="@style/LocationBarActionButton"
             android:src="@drawable/btn_delete_24dp"
             android:visibility="invisible"
             android:contentDescription="@string/accessibility_toolbar_btn_delete_url" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/mic_button"
             style="@style/LocationBarActionButton"
             android:src="@drawable/btn_mic"
             android:visibility="invisible"
             android:contentDescription="@string/accessibility_toolbar_btn_mic" />
 
-        <android.support.v7.widget.AppCompatImageButton
+        <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/bookmark_button"
             style="@style/LocationBarActionButton"
             android:visibility="gone"
             android:contentDescription="@string/accessibility_menu_bookmark" />
 
-       <android.support.v7.widget.AppCompatImageButton
+       <org.chromium.chrome.browser.widget.TintedImageButton
             android:id="@+id/save_offline_button"
             style="@style/LocationBarActionButton"
             android:nextFocusForward="@+id/menu_button"
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 54ebed0a..3d946cde 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -298,7 +298,7 @@
         <item name="android:layout_weight">1</item>
         <item name="android:background">?attr/listChoiceBackgroundIndicator</item>
         <item name="android:scaleType">center</item>
-        <item name="tint">@color/dark_mode_tint</item>
+        <item name="chrometint">@color/dark_mode_tint</item>
     </style>
     <style name="OverflowMenuAnim">
         <item name="android:windowEnterAnimation">@anim/menu_enter</item>
@@ -560,7 +560,7 @@
         <item name="android:paddingStart">4dp</item>
         <item name="android:scaleType">center</item>
         <item name="android:layout_gravity">end</item>
-        <item name="tint">@color/dark_mode_tint</item>
+        <item name="chrometint">@color/dark_mode_tint</item>
     </style>
     <style name="ModernToolbar" parent="Widget.AppCompat.Toolbar">
         <item name="titleTextAppearance">@style/BlackHeadline1</item>
diff --git a/chrome/android/java/res/values/attrs.xml b/chrome/android/java/res/values/attrs.xml
index e0f3c30..fc71116 100644
--- a/chrome/android/java/res/values/attrs.xml
+++ b/chrome/android/java/res/values/attrs.xml
@@ -4,6 +4,10 @@
      found in the LICENSE file. -->
 
 <resources>
+    <declare-styleable name="TintedImage">
+        <attr name="chrometint" format="color" />
+    </declare-styleable>
+
     <declare-styleable name="HyperlinkPreference">
         <!-- The URL to load when the preference is clicked -->
         <attr name="url" format="string" />
diff --git a/chrome/android/java/res_download/layout/download_item_view.xml b/chrome/android/java/res_download/layout/download_item_view.xml
index e36dd3f..e396f2c 100644
--- a/chrome/android/java/res_download/layout/download_item_view.xml
+++ b/chrome/android/java/res_download/layout/download_item_view.xml
@@ -15,10 +15,10 @@
             android:id="@+id/layout_container"
             style="@style/ListItemContainer" >
 
-        <android.support.v7.widget.AppCompatImageView
+        <org.chromium.chrome.browser.widget.TintedImageView
             android:id="@+id/icon_view"
             style="@style/DownloadIconView"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
         <!-- Shown for completed downloads. -->
         <RelativeLayout
@@ -91,7 +91,7 @@
                     android:layout_below="@+id/download_progress_view"
                     android:textAlignment="viewEnd" />
 
-            <android.support.v7.widget.AppCompatImageButton
+            <org.chromium.chrome.browser.widget.TintedImageButton
                     android:id="@+id/pause_button"
                     android:layout_width="48dp"
                     android:layout_height="48dp"
@@ -102,9 +102,9 @@
                     android:background="?attr/selectableItemBackground"
                     android:contentDescription="@string/download_notification_pause_button"
                     android:src="@drawable/ic_pause_white_24dp"
-                    app:tint="@color/default_icon_color" />
+                    app:chrometint="@color/default_icon_color" />
 
-            <android.support.v7.widget.AppCompatImageButton
+            <org.chromium.chrome.browser.widget.TintedImageButton
                     android:id="@+id/cancel_button"
                     android:layout_width="48dp"
                     android:layout_height="48dp"
@@ -116,7 +116,7 @@
                     android:background="?attr/selectableItemBackground"
                     android:contentDescription="@string/download_notification_cancel_button"
                     android:src="@drawable/btn_close"
-                    app:tint="@color/default_icon_color" />
+                    app:chrometint="@color/default_icon_color" />
         </RelativeLayout>
     </LinearLayout>
 </view>
diff --git a/chrome/android/java/res_download/layout/download_location_dialog.xml b/chrome/android/java/res_download/layout/download_location_dialog.xml
index 4061a078..cb75a04 100644
--- a/chrome/android/java/res_download/layout/download_location_dialog.xml
+++ b/chrome/android/java/res_download/layout/download_location_dialog.xml
@@ -28,11 +28,11 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal">
 
-            <android.support.v7.widget.AppCompatImageView
+            <org.chromium.chrome.browser.widget.TintedImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 app:srcCompat="@drawable/ic_drive_file_24dp"
-                app:tint="@color/default_icon_color"
+                app:chrometint="@color/default_icon_color"
                 style="@style/ListItemStartIcon" />
 
             <org.chromium.chrome.browser.widget.AlertDialogEditText
@@ -49,11 +49,11 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal">
 
-            <android.support.v7.widget.AppCompatImageView
+            <org.chromium.chrome.browser.widget.TintedImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:src="@drawable/ic_folder_blue_24dp"
-                app:tint="@color/default_icon_color"
+                app:chrometint="@color/default_icon_color"
                 style="@style/ListItemStartIcon" />
 
             <Spinner
diff --git a/chrome/android/java/res_download/layout/download_manager_generic_item.xml b/chrome/android/java/res_download/layout/download_manager_generic_item.xml
index 581a439..ceaa410 100644
--- a/chrome/android/java/res_download/layout/download_manager_generic_item.xml
+++ b/chrome/android/java/res_download/layout/download_manager_generic_item.xml
@@ -16,7 +16,7 @@
     app:columnCount="3"
     app:rowCount="2">
 
-    <android.support.v7.widget.AppCompatImageView
+    <org.chromium.chrome.browser.widget.TintedImageView
         android:id="@+id/thumbnail"
         android:layout_width="@dimen/download_manager_generic_thumbnail_size"
         android:layout_height="@dimen/download_manager_generic_thumbnail_size"
@@ -27,7 +27,7 @@
         app:layout_row="0"
         app:layout_rowSpan="2"
         app:layout_gravity="center_vertical"
-        app:tint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 
     <org.chromium.chrome.browser.download.home.view.SelectionView
         android:id="@+id/selection"
diff --git a/chrome/android/java/res_download/layout/download_manager_in_progress_item.xml b/chrome/android/java/res_download/layout/download_manager_in_progress_item.xml
index 4762920e..b5304d6 100644
--- a/chrome/android/java/res_download/layout/download_manager_in_progress_item.xml
+++ b/chrome/android/java/res_download/layout/download_manager_in_progress_item.xml
@@ -43,7 +43,7 @@
         app:layout_row="1"
         app:layout_gravity="fill_horizontal" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/cancel_button"
         android:layout_width="48dp"
         android:layout_height="48dp"
@@ -54,6 +54,6 @@
         android:background="?attr/selectableItemBackground"
         android:contentDescription="@string/download_notification_cancel_button"
         android:src="@drawable/btn_close"
-        app:tint="@color/default_icon_color" />
+        app:chrometint="@color/default_icon_color" />
 
 </android.support.v7.widget.GridLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res_download/layout/download_manager_in_progress_video_item.xml b/chrome/android/java/res_download/layout/download_manager_in_progress_video_item.xml
index 116f9e8..8557e4a 100644
--- a/chrome/android/java/res_download/layout/download_manager_in_progress_video_item.xml
+++ b/chrome/android/java/res_download/layout/download_manager_in_progress_video_item.xml
@@ -60,7 +60,7 @@
         android:layout_marginStart="16dp"
         app:layout_gravity="fill_horizontal" />
 
-    <android.support.v7.widget.AppCompatImageButton
+    <org.chromium.chrome.browser.widget.TintedImageButton
         android:id="@+id/cancel_button"
         android:layout_width="48dp"
         android:layout_height="48dp"
@@ -71,6 +71,6 @@
         android:background="?attr/selectableItemBackground"
         android:contentDescription="@string/download_notification_cancel_button"
         android:src="@drawable/btn_close"
-        app:tint="@color/default_icon_color" />
+        app:chrometint="@color/default_icon_color" />
 
 </android.support.v7.widget.GridLayout>
diff --git a/chrome/android/java/res_download/layout/download_manager_video_item.xml b/chrome/android/java/res_download/layout/download_manager_video_item.xml
index f113ee7f..17b35b8 100644
--- a/chrome/android/java/res_download/layout/download_manager_video_item.xml
+++ b/chrome/android/java/res_download/layout/download_manager_video_item.xml
@@ -19,7 +19,7 @@
         android:id="@+id/thumbnail"
         android:layout_width="match_parent"
         android:layout_height="200dp"
-        android:scaleType="centerInside"
+        android:scaleType="centerCrop"
         android:adjustViewBounds="true"
         app:layout_column="0"
         app:layout_row="0"
diff --git a/chrome/android/java/res_download/layout/offline_download_header.xml b/chrome/android/java/res_download/layout/offline_download_header.xml
index 60cfc07d..74d9b36 100644
--- a/chrome/android/java/res_download/layout/offline_download_header.xml
+++ b/chrome/android/java/res_download/layout/offline_download_header.xml
@@ -16,11 +16,11 @@
         android:id="@+id/layout_container"
         style="@style/ListItemContainer" >
 
-        <android.support.v7.widget.AppCompatImageView
+        <org.chromium.chrome.browser.widget.TintedImageView
             android:id="@+id/icon_view"
             style="@style/DownloadIconView"
             android:src="@drawable/ic_chrome"
-            app:tint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
         <RelativeLayout
             android:id="@+id/completed_layout"
@@ -47,7 +47,7 @@
                     android:layout_weight="0"
                     android:visibility="gone" />
 
-                <android.support.v7.widget.AppCompatImageView
+                <org.chromium.chrome.browser.widget.TintedImageView
                     android:id="@+id/expand_icon"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -56,7 +56,7 @@
                     android:paddingEnd="16dp"
                     tools:ignore="ContentDescription"
                     android:src="@drawable/ic_expand_more_black_24dp"
-                    app:tint="@color/dark_mode_tint" />
+                    app:chrometint="@color/dark_mode_tint" />
             </LinearLayout>
 
             <TextView
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index e6d2716..6732fdd4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -10,9 +10,7 @@
 import android.animation.ObjectAnimator;
 import android.graphics.drawable.Drawable;
 import android.support.annotation.IntDef;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -25,6 +23,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.ViewHighlighter;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.interpolators.BakedBezierInterpolator;
@@ -228,7 +227,7 @@
                     holder = new TitleButtonMenuItemViewHolder();
                     holder.title = (TextView) convertView.findViewById(R.id.title);
                     holder.checkbox = (AppMenuItemIcon) convertView.findViewById(R.id.checkbox);
-                    holder.button = (AppCompatImageButton) convertView.findViewById(R.id.button);
+                    holder.button = (TintedImageButton) convertView.findViewById(R.id.button);
                     holder.button.setTag(
                             R.id.menu_item_original_background, holder.button.getBackground());
 
@@ -289,13 +288,13 @@
 
         // The checkbox must be tinted to make Android consistently style it across OS versions.
         // http://crbug.com/571445
-        ImageViewCompat.setImageTintList(button,
+        button.setTint(
                 AppCompatResources.getColorStateList(button.getContext(), R.color.checkbox_tint));
 
         setupMenuButton(button, item);
     }
 
-    private void setupImageButton(AppCompatImageButton button, final MenuItem item) {
+    private void setupImageButton(TintedImageButton button, final MenuItem item) {
         // Store and recover the level of image as button.setimageDrawable
         // resets drawable to default level.
         int currentLevel = item.getIcon().getLevel();
@@ -303,9 +302,8 @@
         item.getIcon().setLevel(currentLevel);
 
         if (item.isChecked()) {
-            ImageViewCompat.setImageTintList(button,
-                    AppCompatResources.getColorStateList(
-                            button.getContext(), R.color.blue_mode_tint));
+            button.setTint(AppCompatResources.getColorStateList(
+                    button.getContext(), R.color.blue_mode_tint));
         }
 
         setupMenuButton(button, item);
@@ -440,8 +438,8 @@
 
             // Save references to all the buttons.
             for (int i = 0; i < numItems; i++) {
-                AppCompatImageButton view =
-                        (AppCompatImageButton) convertView.findViewById(BUTTON_IDS[i]);
+                TintedImageButton view =
+                        (TintedImageButton) convertView.findViewById(BUTTON_IDS[i]);
                 holder.buttons[i] = view;
                 holder.buttons[i].setTag(
                         R.id.menu_item_original_background, holder.buttons[i].getBackground());
@@ -477,16 +475,16 @@
     }
 
     private static class RowItemViewHolder {
-        public AppCompatImageButton[] buttons;
+        public TintedImageButton[] buttons;
 
         RowItemViewHolder(int numButtons) {
-            buttons = new AppCompatImageButton[numButtons];
+            buttons = new TintedImageButton[numButtons];
         }
     }
 
     static class TitleButtonMenuItemViewHolder {
         public TextView title;
         public AppMenuItemIcon checkbox;
-        public AppCompatImageButton button;
+        public TintedImageButton button;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java
index 3a681f5..72be6c58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuIconRowFooter.java
@@ -5,9 +5,7 @@
 package org.chromium.chrome.browser.appmenu;
 
 import android.content.Context;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -17,6 +15,7 @@
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 
 /**
  * A {@link LinearLayout} that displays a horizontal row of icons for page actions.
@@ -25,11 +24,11 @@
     private ChromeActivity mActivity;
     private AppMenu mAppMenu;
 
-    private AppCompatImageButton mForwardButton;
-    private AppCompatImageButton mBookmarkButton;
-    private AppCompatImageButton mDownloadButton;
-    private AppCompatImageButton mPageInfoButton;
-    private AppCompatImageButton mReloadButton;
+    private TintedImageButton mForwardButton;
+    private TintedImageButton mBookmarkButton;
+    private TintedImageButton mDownloadButton;
+    private TintedImageButton mPageInfoButton;
+    private TintedImageButton mReloadButton;
 
     public AppMenuIconRowFooter(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -39,19 +38,19 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mForwardButton = (AppCompatImageButton) findViewById(R.id.forward_menu_id);
+        mForwardButton = (TintedImageButton) findViewById(R.id.forward_menu_id);
         mForwardButton.setOnClickListener(this);
 
-        mBookmarkButton = (AppCompatImageButton) findViewById(R.id.bookmark_this_page_id);
+        mBookmarkButton = (TintedImageButton) findViewById(R.id.bookmark_this_page_id);
         mBookmarkButton.setOnClickListener(this);
 
-        mDownloadButton = (AppCompatImageButton) findViewById(R.id.offline_page_id);
+        mDownloadButton = (TintedImageButton) findViewById(R.id.offline_page_id);
         mDownloadButton.setOnClickListener(this);
 
-        mPageInfoButton = (AppCompatImageButton) findViewById(R.id.info_menu_id);
+        mPageInfoButton = (TintedImageButton) findViewById(R.id.info_menu_id);
         mPageInfoButton.setOnClickListener(this);
 
-        mReloadButton = (AppCompatImageButton) findViewById(R.id.reload_menu_id);
+        mReloadButton = (TintedImageButton) findViewById(R.id.reload_menu_id);
         mReloadButton.setOnClickListener(this);
     }
 
@@ -103,7 +102,7 @@
         if (currentTab.getBookmarkId() != Tab.INVALID_BOOKMARK_ID) {
             mBookmarkButton.setImageResource(R.drawable.btn_star_filled);
             mBookmarkButton.setContentDescription(mActivity.getString(R.string.edit_bookmark));
-            ImageViewCompat.setImageTintList(mBookmarkButton,
+            mBookmarkButton.setTint(
                     AppCompatResources.getColorStateList(getContext(), R.color.blue_mode_tint));
         } else {
             mBookmarkButton.setImageResource(R.drawable.btn_star);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java
index 87113f8..47b3980 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java
@@ -5,14 +5,15 @@
 package org.chromium.chrome.browser.appmenu;
 
 import android.content.Context;
-import android.support.v7.widget.AppCompatImageView;
 import android.util.AttributeSet;
 import android.widget.Checkable;
 
+import org.chromium.chrome.browser.widget.TintedImageView;
+
 /**
- * An AppCompatImageView that supports the checkable state.
+ * A TintedImageView that supports the checkable state.
  */
-public class AppMenuItemIcon extends AppCompatImageView implements Checkable {
+public class AppMenuItemIcon extends TintedImageView implements Checkable {
     private static final int[] CHECKED_STATE_SET = new int[] {android.R.attr.state_checked};
     private boolean mCheckedState;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
index 289f6f3..116dbf49 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
@@ -11,7 +11,6 @@
 import android.support.graphics.drawable.VectorDrawableCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageView;
 import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -27,6 +26,7 @@
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.widget.TintedImageView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.components.bookmarks.BookmarkId;
 
@@ -359,7 +359,7 @@
          * i.e. New Folder, Normal and Selected.
          */
         private void setUpIcons(FolderListEntry entry, View view) {
-            AppCompatImageView startIcon = view.findViewById(R.id.icon_view);
+            TintedImageView startIcon = view.findViewById(R.id.icon_view);
 
             Drawable iconDrawable;
             if (entry.mType == FolderListEntry.TYPE_NORMAL) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
index 27205cdd7..142abf5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -10,7 +10,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.animation.CompositorAnimator.AnimatorUpdateListener;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
@@ -348,12 +347,7 @@
 
         mHeightAnimator = CompositorAnimator.ofFloat(
                 getAnimationHandler(), getHeight(), height, duration, null);
-        mHeightAnimator.addUpdateListener(new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                setPanelHeight(animator.getAnimatedValue());
-            }
-        });
+        mHeightAnimator.addUpdateListener(animator -> setPanelHeight(animator.getAnimatedValue()));
         mHeightAnimator.addListener(new CancelAwareAnimatorListener() {
             @Override
             public void onEnd(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarBannerControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarBannerControl.java
index 397687b..7ce78a6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarBannerControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarBannerControl.java
@@ -11,7 +11,6 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.animation.CompositorAnimator.AnimatorUpdateListener;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelInflater;
@@ -251,25 +250,21 @@
      * Animates the Bar Banner appearance.
      */
     public void animateAppearance() {
-        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                float percentage = animator.getAnimatedFraction();
-                mRippleWidthPx = Math.round(MathUtils.interpolate(
-                        mRippleMinimumWidthPx, mRippleMaximumWidthPx, percentage));
-
-                mRippleOpacity = MathUtils.interpolate(0.f, 1.f, percentage);
-
-                float textOpacityDelay = 0.5f;
-                float textOpacityPercentage =
-                        Math.max(0.f, percentage - textOpacityDelay) / (1.f - textOpacityDelay);
-                mTextOpacity = MathUtils.interpolate(0.f, 1.f, textOpacityPercentage);
-            }
-        };
-
         CompositorAnimator appearance =
                 CompositorAnimator.ofFloat(mOverlayPanel.getAnimationHandler(), 0.f, 1.f,
-                        OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, listener);
+                        OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
+        appearance.addUpdateListener(animator -> {
+            float percentage = animator.getAnimatedFraction();
+            mRippleWidthPx = Math.round(MathUtils.interpolate(
+                    mRippleMinimumWidthPx, mRippleMaximumWidthPx, percentage));
+
+            mRippleOpacity = MathUtils.interpolate(0.f, 1.f, percentage);
+
+            float textOpacityDelay = 0.5f;
+            float textOpacityPercentage =
+                    Math.max(0.f, percentage - textOpacityDelay) / (1.f - textOpacityDelay);
+            mTextOpacity = MathUtils.interpolate(0.f, 1.f, textOpacityPercentage);
+        });
         appearance.start();
     }
 
@@ -281,13 +276,10 @@
         CompositorAnimator disappearance =
                 CompositorAnimator.ofFloat(mOverlayPanel.getAnimationHandler(), 1.f, 0.f,
                         OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
-        disappearance.addUpdateListener(new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                if (isVisible()) {
-                    float percentage = animator.getAnimatedFraction();
-                    mHeightPx = MathUtils.interpolate(getPaddedHeightPx(), 0.f, percentage);
-                }
+        disappearance.addUpdateListener(animator -> {
+            if (isVisible()) {
+                float percentage = animator.getAnimatedFraction();
+                mHeightPx = MathUtils.interpolate(getPaddedHeightPx(), 0.f, percentage);
             }
         });
         disappearance.addListener(new AnimatorListenerAdapter() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
index 45f989b..d1599e3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
@@ -13,7 +13,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.animation.CompositorAnimator.AnimatorUpdateListener;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
@@ -430,15 +429,11 @@
         float endValue = visible ? FULL_OPACITY : TRANSPARENT_OPACITY;
         if (mDividerLineVisibilityPercentage == endValue) return;
         if (mDividerLineVisibilityAnimation != null) mDividerLineVisibilityAnimation.cancel();
-        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                mDividerLineVisibilityPercentage = animator.getAnimatedValue();
-            }
-        };
         mDividerLineVisibilityAnimation = CompositorAnimator.ofFloat(
                 mContextualSearchPanel.getAnimationHandler(), mDividerLineVisibilityPercentage,
-                endValue, OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, listener);
+                endValue, OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
+        mDividerLineVisibilityAnimation.addUpdateListener(
+                animator -> mDividerLineVisibilityPercentage = animator.getAnimatedValue());
         mDividerLineVisibilityAnimation.start();
     }
 
@@ -581,12 +576,8 @@
             mTextOpacityAnimation = CompositorAnimator.ofFloat(
                     mContextualSearchPanel.getAnimationHandler(), TRANSPARENT_OPACITY, FULL_OPACITY,
                     OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
-            mTextOpacityAnimation.addUpdateListener(new AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(CompositorAnimator animator) {
-                    updateSearchBarTextOpacity(animator.getAnimatedValue());
-                }
-            });
+            mTextOpacityAnimation.addUpdateListener(
+                    animator -> updateSearchBarTextOpacity(animator.getAnimatedValue()));
         }
         mTextOpacityAnimation.cancel();
         mTextOpacityAnimation.start();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java
index 9251a41..4541c6f04 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java
@@ -14,7 +14,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.animation.CompositorAnimator.AnimatorUpdateListener;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelTextViewInflater;
@@ -254,15 +253,11 @@
     // ============================================================================================
 
     private void animateTransitionIn() {
-        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                mAnimationPercentage = animator.getAnimatedValue();
-            }
-        };
         mTransitionAnimator = CompositorAnimator.ofFloat(mOverlayPanel.getAnimationHandler(),
                 ANIMATION_PERCENTAGE_ZERO, ANIMATION_PERCENTAGE_COMPLETE,
-                OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, listener);
+                OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
+        mTransitionAnimator.addUpdateListener(
+                animator -> mAnimationPercentage = animator.getAnimatedValue());
         mTransitionAnimator.setInterpolator(ANIMATION_INTERPOLATOR);
         mTransitionAnimator.start();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java
index 59144b5..bd01fbc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchImageControl.java
@@ -213,12 +213,9 @@
         mImageVisibilityAnimator.setDuration(OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS);
         mImageVisibilityAnimator.setInterpolator(mCustomImageVisibilityInterpolator);
         mImageVisibilityAnimator.setValues(mCustomImageVisibilityPercentage, visible ? 1.f : 0.f);
-        mImageVisibilityAnimator.addUpdateListener(new CompositorAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                if (mExpandedPercentage > 0.f) return;
-                mCustomImageVisibilityPercentage = animator.getAnimatedValue();
-            }
+        mImageVisibilityAnimator.addUpdateListener(animator -> {
+            if (mExpandedPercentage > 0.f) return;
+            mCustomImageVisibilityPercentage = animator.getAnimatedValue();
         });
         mImageVisibilityAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
index 9eb77b3..fada36b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
@@ -16,7 +16,6 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.animation.CompositorAnimator.AnimatorUpdateListener;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelInflater;
@@ -291,12 +290,7 @@
                 CompositorAnimator.ofFloat(mOverlayPanel.getAnimationHandler(), 1.f, 0.f,
                         OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
 
-        collapse.addUpdateListener(new AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(CompositorAnimator animator) {
-                updateAppearance(animator.getAnimatedValue());
-            }
-        });
+        collapse.addUpdateListener(animator -> updateAppearance(animator.getAnimatedValue()));
 
         collapse.addListener(new AnimatorListenerAdapter() {
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
index 5561dc6a..bd497c7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
@@ -246,12 +246,9 @@
         if (duration > 0) {
             CompositorAnimator offsetAnimation =
                     CompositorAnimator.ofFloat(getAnimationHandler(), start, end, duration, null);
-            offsetAnimation.addUpdateListener(new CompositorAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(CompositorAnimator animator) {
-                    mOffset = animator.getAnimatedValue();
-                    mOffsetTarget = mOffset;
-                }
+            offsetAnimation.addUpdateListener(animator -> {
+                mOffset = animator.getAnimatedValue();
+                mOffsetTarget = mOffset;
             });
             offsetAnimation.start();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java
index 0b05d952..b17e36d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMediaParserBridge.java
@@ -19,9 +19,9 @@
      * @param totalSize Total size of the media file.
      * @param callback Callback to get the result.
      */
-    public DownloadMediaParserBridge(String mimeType, String filePath, long totalSize,
-            Callback<DownloadMediaData> callback) {
-        mNativeDownloadMediaParserBridge = nativeInit(mimeType, filePath, totalSize, callback);
+    public DownloadMediaParserBridge(
+            String mimeType, String filePath, Callback<DownloadMediaData> callback) {
+        mNativeDownloadMediaParserBridge = nativeInit(mimeType, filePath, callback);
     }
 
     /**
@@ -43,7 +43,7 @@
     }
 
     private native long nativeInit(
-            String mimeType, String filePath, long totalSize, Callback<DownloadMediaData> callback);
+            String mimeType, String filePath, Callback<DownloadMediaData> callback);
     private native void nativeDestory(long nativeDownloadMediaParserBridge);
     private native void nativeStart(long nativeDownloadMediaParserBridge);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java
new file mode 100644
index 0000000..a7d4bd6
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download.home.filter;
+
+import org.chromium.components.offline_items_collection.OfflineItem;
+import org.chromium.components.offline_items_collection.OfflineItemState;
+
+/** A {@link OfflineItemFilter} responsible for pruning out items that do not have the right state
+ *  to show in the UI.
+ */
+public class InvalidStateOfflineItemFilter extends OfflineItemFilter {
+    /** Creates an instance of this filter and wraps {@code source}. */
+    public InvalidStateOfflineItemFilter(OfflineItemFilterSource source) {
+        super(source);
+        onFilterChanged();
+    }
+
+    // OfflineItemFilter implementation.
+    @Override
+    protected boolean isFilteredOut(OfflineItem item) {
+        switch (item.state) {
+            case OfflineItemState.CANCELLED:
+            case OfflineItemState.FAILED:
+                return true;
+            case OfflineItemState.INTERRUPTED:
+                return !item.isResumable;
+            default:
+                return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilter.java
index 36f22f2..edf7eb1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilter.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.download.home.filter;
 
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.ObserverList;
 import org.chromium.components.offline_items_collection.OfflineItem;
 
@@ -111,10 +112,20 @@
 
     @Override
     public void onItemUpdated(OfflineItem oldItem, OfflineItem item) {
-        if (!mItems.remove(oldItem)) return;
+        boolean oldInList = mItems.remove(oldItem);
+        boolean newInList = !isFilteredOut(item);
 
-        mItems.add(item);
-        for (OfflineItemFilterObserver obs : mObservers) obs.onItemUpdated(oldItem, item);
+        if (oldInList && newInList) {
+            mItems.add(item);
+            for (OfflineItemFilterObserver obs : mObservers) obs.onItemUpdated(oldItem, item);
+        } else if (!oldInList && newInList) {
+            mItems.add(item);
+            Collection<OfflineItem> newItems = CollectionUtil.newHashSet(item);
+            for (OfflineItemFilterObserver obs : mObservers) obs.onItemsAdded(newItems);
+        } else if (oldInList && !newInList) {
+            Collection<OfflineItem> oldItems = CollectionUtil.newHashSet(oldItem);
+            for (OfflineItemFilterObserver obs : mObservers) obs.onItemsRemoved(oldItems);
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/chips/ChipsViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/chips/ChipsViewHolder.java
index 029bcd6..66d3dd04 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/chips/ChipsViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/chips/ChipsViewHolder.java
@@ -5,31 +5,31 @@
 
 import android.content.res.ColorStateList;
 import android.support.v4.view.ViewCompat;
-import android.support.v4.widget.ImageViewCompat;
-import android.support.v7.widget.AppCompatImageView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import org.chromium.chrome.browser.widget.TintedImageView;
+
 /** The {@link ViewHolder} responsible for reflecting a {@link Chip} to a {@link View}. */
 public class ChipsViewHolder extends ViewHolder {
     private final int mTextStartPaddingWithIconPx;
     private final int mTextStartPaddingWithNoIconPx;
 
     private final TextView mText;
-    private final AppCompatImageView mImage;
+    private final TintedImageView mImage;
 
     /** Builds a ChipsViewHolder around a specific {@link View}. */
     private ChipsViewHolder(View itemView) {
         super(itemView);
 
         mText = itemView.findViewById(org.chromium.chrome.R.id.text);
-        mImage = (AppCompatImageView) itemView.findViewById(org.chromium.chrome.R.id.icon);
+        mImage = (TintedImageView) itemView.findViewById(org.chromium.chrome.R.id.icon);
 
         ColorStateList textColors = mText.getTextColors();
-        if (textColors != null) ImageViewCompat.setImageTintList(mImage, textColors);
+        if (textColors != null) mImage.setTint(textColors);
 
         mTextStartPaddingWithIconPx = mText.getResources().getDimensionPixelSize(
                 org.chromium.chrome.R.dimen.chip_icon_padding);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java
index a5ff269c..1bd48a9a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java
@@ -7,14 +7,17 @@
 import android.graphics.Bitmap;
 
 import org.chromium.base.Callback;
+import org.chromium.chrome.browser.widget.ThumbnailProvider;
 import org.chromium.chrome.browser.widget.ThumbnailProvider.ThumbnailRequest;
+import org.chromium.chrome.browser.widget.ThumbnailProviderImpl;
+import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemVisuals;
 import org.chromium.components.offline_items_collection.VisualsCallback;
 
 /**
  * Glue class responsible for connecting the current downloads and {@link OfflineContentProvider}
- * thumbnail work to the {@link ThumbnailProvider} via a custon {@link ThumbnailProviderImpl}.
+ * thumbnail work to the {@link ThumbnailProvider} via a custom {@link ThumbnailProviderImpl}.
  */
 public class ThumbnailRequestGlue implements ThumbnailRequest {
     private final OfflineContentProviderGlue mProvider;
@@ -40,6 +43,11 @@
     }
 
     @Override
+    public String getMimeType() {
+        return mItem.mimeType;
+    }
+
+    @Override
     public String getContentId() {
         return mItem.id.id;
     }
@@ -71,4 +79,4 @@
             }
         });
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
index f73fe33..b794adb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -16,6 +16,7 @@
 import org.chromium.chrome.browser.download.home.OfflineItemSource;
 import org.chromium.chrome.browser.download.home.filter.DeleteUndoOfflineItemFilter;
 import org.chromium.chrome.browser.download.home.filter.Filters.FilterType;
+import org.chromium.chrome.browser.download.home.filter.InvalidStateOfflineItemFilter;
 import org.chromium.chrome.browser.download.home.filter.OffTheRecordOfflineItemFilter;
 import org.chromium.chrome.browser.download.home.filter.OfflineItemFilter;
 import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterObserver;
@@ -69,6 +70,7 @@
     private final SelectionDelegate<ListItem> mSelectionDelegate;
 
     private final OffTheRecordOfflineItemFilter mOffTheRecordFilter;
+    private final InvalidStateOfflineItemFilter mInvalidStateFilter;
     private final DeleteUndoOfflineItemFilter mDeleteUndoFilter;
     private final TypeOfflineItemFilter mTypeFilter;
     private final SearchOfflineItemFilter mSearchFilter;
@@ -120,11 +122,12 @@
         // [OfflineContentProvider] ->
         //     [OfflineItemSource] ->
         //         [OffTheRecordOfflineItemFilter] ->
-        //             [DeleteUndoOfflineItemFilter] ->
-        //                 [TypeOfflineItemFilter] ->
-        //                     [SearchOfflineItemFitler] ->
-        //                         [DateOrderedListMutator] ->
-        //                             [ListItemModel]
+        //             [InvalidStateOfflineItemFilter] ->
+        //                 [DeleteUndoOfflineItemFilter] ->
+        //                     [TypeOfflineItemFilter] ->
+        //                         [SearchOfflineItemFitler] ->
+        //                             [DateOrderedListMutator] ->
+        //                                 [ListItemModel]
 
         mProvider = new OfflineContentProviderGlue(provider, offTheRecord);
         mShareController = shareController;
@@ -134,7 +137,8 @@
 
         mSource = new OfflineItemSource(mProvider);
         mOffTheRecordFilter = new OffTheRecordOfflineItemFilter(offTheRecord, mSource);
-        mDeleteUndoFilter = new DeleteUndoOfflineItemFilter(mOffTheRecordFilter);
+        mInvalidStateFilter = new InvalidStateOfflineItemFilter(mOffTheRecordFilter);
+        mDeleteUndoFilter = new DeleteUndoOfflineItemFilter(mInvalidStateFilter);
         mTypeFilter = new TypeOfflineItemFilter(mDeleteUndoFilter);
         mSearchFilter = new SearchOfflineItemFilter(mTypeFilter);
         mListMutator = new DateOrderedListMutator(mSearchFilter, mModel);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/UiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/UiUtils.java
index de3eed5..35ca576 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/UiUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/UiUtils.java
@@ -117,9 +117,7 @@
     public static boolean canHaveThumbnails(OfflineItem item) {
         switch (item.filter) {
             case OfflineItemFilter.FILTER_PAGE:
-            // TODO(shaktisahu, xingliu): Remove this after video thumbnail generation pipeline is
-            // done.
-            // case OfflineItemFilter.FILTER_VIDEO:
+            case OfflineItemFilter.FILTER_VIDEO:
             case OfflineItemFilter.FILTER_IMAGE:
                 return true;
             default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java
index 4c752178..25ee4a60 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/GenericViewHolder.java
@@ -9,9 +9,7 @@
 import android.support.annotation.DrawableRes;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -22,6 +20,7 @@
 import org.chromium.chrome.browser.download.home.list.UiUtils;
 import org.chromium.chrome.browser.download.home.view.SelectionView;
 import org.chromium.chrome.browser.modelutil.PropertyModel;
+import org.chromium.chrome.browser.widget.TintedImageView;
 import org.chromium.chrome.download.R;
 import org.chromium.components.offline_items_collection.OfflineItemVisuals;
 
@@ -32,7 +31,7 @@
 
     private final TextView mTitle;
     private final TextView mCaption;
-    private final AppCompatImageView mThumbnailView;
+    private final TintedImageView mThumbnailView;
 
     private Bitmap mThumbnailBitmap;
 
@@ -53,7 +52,7 @@
 
         mTitle = (TextView) itemView.findViewById(R.id.title);
         mCaption = (TextView) itemView.findViewById(R.id.caption);
-        mThumbnailView = (AppCompatImageView) itemView.findViewById(R.id.thumbnail);
+        mThumbnailView = (TintedImageView) itemView.findViewById(R.id.thumbnail);
     }
 
     // ListItemViewHolder implementation.
@@ -84,7 +83,7 @@
             assert !mThumbnailBitmap.isRecycled();
 
             mThumbnailView.setBackground(null);
-            ImageViewCompat.setImageTintList(mThumbnailView, null);
+            mThumbnailView.setTint(null);
 
             RoundedBitmapDrawable drawable =
                     RoundedBitmapDrawableFactory.create(resources, mThumbnailBitmap);
@@ -95,9 +94,8 @@
             mThumbnailView.getBackground().setLevel(
                     resources.getInteger(R.integer.list_item_level_default));
             mThumbnailView.setImageResource(mIconId);
-            ImageViewCompat.setImageTintList(mThumbnailView,
-                    AppCompatResources.getColorStateList(
-                            mThumbnailView.getContext(), R.color.dark_mode_tint));
+            mThumbnailView.setTint(AppCompatResources.getColorStateList(
+                    mThumbnailView.getContext(), R.color.dark_mode_tint));
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressVideoViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressVideoViewHolder.java
index 6d214b0c..5a12ed80 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressVideoViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressVideoViewHolder.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.download.home.list.holder;
 
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -16,6 +15,7 @@
 import org.chromium.chrome.browser.download.home.list.UiUtils;
 import org.chromium.chrome.browser.download.home.list.view.CircularProgressView;
 import org.chromium.chrome.browser.modelutil.PropertyModel;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.download.R;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemState;
@@ -28,7 +28,7 @@
     private final TextView mTitle;
     private final TextView mCaption;
     private final CircularProgressView mActionButton;
-    private final AppCompatImageButton mCancelButton;
+    private final TintedImageButton mCancelButton;
 
     /**
      * Creates a new {@link InProgressViewHolder} instance.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java
index ee2f125..186e8df 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/InProgressViewHolder.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.download.home.list.holder;
 
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -16,6 +15,7 @@
 import org.chromium.chrome.browser.download.home.list.UiUtils;
 import org.chromium.chrome.browser.download.home.list.view.CircularProgressView;
 import org.chromium.chrome.browser.modelutil.PropertyModel;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.download.R;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemState;
@@ -28,7 +28,7 @@
     private final TextView mTitle;
     private final TextView mCaption;
     private final CircularProgressView mActionButton;
-    private final AppCompatImageButton mCancelButton;
+    private final TintedImageButton mCancelButton;
 
     /**
      * Creates a new {@link InProgressViewHolder} instance.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java
index 75cc8fd..de4bfff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/view/SelectionView.java
@@ -6,12 +6,12 @@
 
 import android.content.Context;
 import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
-import android.support.v7.widget.AppCompatImageView;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 /**
  * A helper UI widget that provides visual feedback when the selection state of the underlying view
@@ -19,8 +19,8 @@
  * selected. The caller can define the UI behavior at each of these states by subclassing this view.
  */
 public class SelectionView extends FrameLayout {
-    private final AppCompatImageView mCheck;
-    private final AppCompatImageView mCircle;
+    private final TintedImageView mCheck;
+    private final TintedImageView mCircle;
     private final AnimatedVectorDrawableCompat mCheckDrawable;
 
     private boolean mIsSelected;
@@ -31,8 +31,8 @@
     public SelectionView(Context context, AttributeSet attrs) {
         super(context, attrs);
         LayoutInflater.from(context).inflate(R.layout.list_selection_handle_view, this, true);
-        mCheck = (AppCompatImageView) findViewById(R.id.check);
-        mCircle = (AppCompatImageView) findViewById(R.id.circle);
+        mCheck = (TintedImageView) findViewById(R.id.check);
+        mCircle = (TintedImageView) findViewById(R.id.circle);
         mCheckDrawable = AnimatedVectorDrawableCompat.create(
                 context, R.drawable.ic_check_googblue_24dp_animated);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
index f898fab..202bd0a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
@@ -11,9 +11,7 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.view.MarginLayoutParamsCompat;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.AttributeSet;
@@ -32,6 +30,7 @@
 import org.chromium.chrome.browser.widget.ListMenuButton.Item;
 import org.chromium.chrome.browser.widget.MaterialProgressBar;
 import org.chromium.chrome.browser.widget.ThumbnailProvider;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.download.R;
 import org.chromium.components.offline_items_collection.OfflineItem;
@@ -101,7 +100,7 @@
     private TextView mDownloadStatusView;
     private TextView mDownloadPercentageView;
     private MaterialProgressBar mProgressView;
-    private AppCompatImageButton mPauseResumeButton;
+    private TintedImageButton mPauseResumeButton;
     private View mCancelButton;
 
     /**
@@ -155,7 +154,7 @@
         mDownloadStatusView = (TextView) findViewById(R.id.status_view);
         mDownloadPercentageView = (TextView) findViewById(R.id.percentage_view);
 
-        mPauseResumeButton = (AppCompatImageButton) findViewById(R.id.pause_button);
+        mPauseResumeButton = (TintedImageButton) findViewById(R.id.pause_button);
         mCancelButton = findViewById(R.id.cancel_button);
 
         mMoreButton.setDelegate(this);
@@ -180,6 +179,11 @@
     }
 
     @Override
+    public String getMimeType() {
+        return mItem == null ? null : mItem.getMimeType();
+    }
+
+    @Override
     public @Nullable String getContentId() {
         return mItem == null ? "" : mItem.getId();
     }
@@ -344,7 +348,7 @@
             mIconView.getBackground().setLevel(
                     getResources().getInteger(R.integer.list_item_level_selected));
             mIconView.setImageDrawable(mCheckDrawable);
-            ImageViewCompat.setImageTintList(mIconView, mCheckedIconForegroundColorList);
+            mIconView.setTint(mCheckedIconForegroundColorList);
             mCheckDrawable.start();
         } else if (mThumbnailBitmap != null) {
             assert !mThumbnailBitmap.isRecycled();
@@ -353,13 +357,13 @@
                     Bitmap.createScaledBitmap(mThumbnailBitmap, mIconSize, mIconSize, false),
                     getResources().getDimensionPixelSize(
                             R.dimen.list_item_start_icon_corner_radius)));
-            ImageViewCompat.setImageTintList(mIconView, null);
+            mIconView.setTint(null);
         } else {
             mIconView.setBackgroundResource(mIconBackgroundResId);
             mIconView.getBackground().setLevel(
                     getResources().getInteger(R.integer.list_item_level_default));
             mIconView.setImageResource(mIconResId);
-            ImageViewCompat.setImageTintList(mIconView, mIconForegroundColorList);
+            mIconView.setTint(mIconForegroundColorList);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
index 0ae7e87..c6ce60b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
@@ -7,9 +7,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageView;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
 import android.util.AttributeSet;
@@ -20,6 +18,7 @@
 import org.chromium.chrome.browser.download.ui.DownloadHistoryAdapter.SubsectionHeader;
 import org.chromium.chrome.browser.download.ui.DownloadItemSelectionDelegate.SubsectionHeaderSelectionObserver;
 import org.chromium.chrome.browser.widget.DateDividedAdapter.TimedItem;
+import org.chromium.chrome.browser.widget.TintedImageView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.download.R;
 
@@ -40,7 +39,7 @@
 
     private TextView mDescriptionTextView;
     private ImageView mExpandImage;
-    private AppCompatImageView mIconImageView;
+    private TintedImageView mIconImageView;
 
     public OfflineGroupHeaderView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -55,7 +54,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mIconImageView = (AppCompatImageView) findViewById(R.id.icon_view);
+        mIconImageView = (TintedImageView) findViewById(R.id.icon_view);
         mDescriptionTextView = (TextView) findViewById(R.id.description);
         mExpandImage = (ImageView) findViewById(R.id.expand_icon);
     }
@@ -117,7 +116,7 @@
                     getResources().getInteger(R.integer.list_item_level_selected));
 
             mIconImageView.setImageDrawable(mCheckDrawable);
-            ImageViewCompat.setImageTintList(mIconImageView, mCheckedIconForegroundColorList);
+            mIconImageView.setTint(mCheckedIconForegroundColorList);
             mCheckDrawable.start();
         } else {
             mIconImageView.setBackgroundResource(mIconBackgroundResId);
@@ -125,7 +124,7 @@
                     getResources().getInteger(R.integer.list_item_level_default));
 
             mIconImageView.setImageResource(R.drawable.ic_chrome);
-            ImageViewCompat.setImageTintList(mIconImageView, mIconForegroundColorList);
+            mIconImageView.setTint(mIconForegroundColorList);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
index bbd4697..b610b826 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -11,7 +11,6 @@
 import android.support.graphics.drawable.VectorDrawableCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -24,13 +23,14 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 
 /**
  * The SelectableItemView for items displayed in the browsing history UI.
  */
 public class HistoryItemView extends SelectableItemView<HistoryItem> implements LargeIconCallback {
-    private AppCompatImageButton mRemoveButton;
+    private TintedImageButton mRemoveButton;
     private VectorDrawableCompat mBlockedVisitDrawable;
     private View mContentView;
 
@@ -62,7 +62,7 @@
         super.onFinishInflate();
         mIconView.setImageResource(R.drawable.default_favicon);
         mContentView = findViewById(R.id.content);
-        mRemoveButton = (AppCompatImageButton) findViewById(R.id.remove);
+        mRemoveButton = (TintedImageButton) findViewById(R.id.remove);
         mRemoveButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
index a66105b..9b1ecff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -6,7 +6,6 @@
 
 import android.support.design.widget.TabLayout;
 import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -21,6 +20,7 @@
 import org.chromium.chrome.browser.infobar.translate.TranslateTabLayout;
 import org.chromium.chrome.browser.snackbar.Snackbar;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.ui.widget.Toast;
 
 /**
@@ -104,7 +104,7 @@
     private TranslateMenuHelper mOverflowMenuHelper;
     private TranslateMenuHelper mLanguageMenuHelper;
 
-    private AppCompatImageButton mMenuButton;
+    private TintedImageButton mMenuButton;
     private InfoBarCompactLayout mParent;
 
     private TranslateSnackbarController mSnackbarController;
@@ -239,8 +239,7 @@
             }
         });
 
-        mMenuButton =
-                (AppCompatImageButton) content.findViewById(R.id.translate_infobar_menu_button);
+        mMenuButton = (TintedImageButton) content.findViewById(R.id.translate_infobar_menu_button);
         mMenuButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
index a3173a6..ca104d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateMenuHelper.java
@@ -8,7 +8,6 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.AppCompatImageView;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -23,6 +22,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.infobar.TranslateOptions;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -287,8 +287,8 @@
                     menuItemView = getItemView(
                             menuItemView, position, parent, R.layout.translate_menu_item_checked);
 
-                    AppCompatImageView checkboxIcon =
-                            (AppCompatImageView) menuItemView.findViewById(R.id.menu_item_icon);
+                    TintedImageView checkboxIcon =
+                            (TintedImageView) menuItemView.findViewById(R.id.menu_item_icon);
                     if (getItem(position).mId == TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE
                             && mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE)) {
                         checkboxIcon.setVisibility(View.VISIBLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index b43056d..bf78c48 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -22,9 +22,7 @@
 import android.support.annotation.Nullable;
 import android.support.v4.view.MarginLayoutParamsCompat;
 import android.support.v4.view.ViewCompat;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.SparseArray;
@@ -79,6 +77,7 @@
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.browser.widget.ScrimView.ScrimParams;
 import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
@@ -111,10 +110,10 @@
     private ScrimParams mScrimParams;
 
     protected ImageView mNavigationButton;
-    protected AppCompatImageButton mSecurityButton;
+    protected TintedImageButton mSecurityButton;
     protected TextView mVerboseStatusTextView;
-    protected AppCompatImageButton mDeleteButton;
-    protected AppCompatImageButton mMicButton;
+    protected TintedImageButton mDeleteButton;
+    protected TintedImageButton mMicButton;
     protected View mUrlBar;
     private final boolean mIsTablet;
 
@@ -396,12 +395,12 @@
         mIsTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(context);
         mNavigationButtonType = mIsTablet ? NavigationButtonType.PAGE : NavigationButtonType.EMPTY;
 
-        mSecurityButton = (AppCompatImageButton) findViewById(R.id.security_button);
+        mSecurityButton = (TintedImageButton) findViewById(R.id.security_button);
         mSecurityIconResource = 0;
 
         mVerboseStatusTextView = (TextView) findViewById(R.id.location_bar_verbose_status);
 
-        mDeleteButton = (AppCompatImageButton) findViewById(R.id.delete_button);
+        mDeleteButton = (TintedImageButton) findViewById(R.id.delete_button);
 
         mUrlBar = findViewById(R.id.url_bar);
         mUrlCoordinator = new UrlBarCoordinator((UrlBar) mUrlBar);
@@ -410,7 +409,7 @@
         mSuggestionItems = new ArrayList<OmniboxResultItem>();
         mSuggestionListAdapter = new OmniboxResultsAdapter(getContext(), mSuggestionItems);
 
-        mMicButton = (AppCompatImageButton) findViewById(R.id.mic_button);
+        mMicButton = (TintedImageButton) findViewById(R.id.mic_button);
 
         mUrlActionContainer = (LinearLayout) findViewById(R.id.url_action_container);
 
@@ -1017,8 +1016,7 @@
         } else {
             // ImageView#setImageResource is no-op if given resource is the current one.
             mSecurityButton.setImageResource(id);
-            ImageViewCompat.setImageTintList(
-                    mSecurityButton, mToolbarDataProvider.getSecurityIconColorStateList());
+            mSecurityButton.setTint(mToolbarDataProvider.getSecurityIconColorStateList());
         }
 
         int contentDescriptionId = getToolbarDataProvider().getSecurityIconContentDescription();
@@ -2125,8 +2123,8 @@
         if (updateUseDarkColors()) updateSecurityIcon();
         int id = mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint;
         ColorStateList colorStateList = AppCompatResources.getColorStateList(getContext(), id);
-        ImageViewCompat.setImageTintList(mMicButton, colorStateList);
-        ImageViewCompat.setImageTintList(mDeleteButton, colorStateList);
+        mMicButton.setTint(colorStateList);
+        mDeleteButton.setTint(colorStateList);
 
         setNavigationButtonType(mNavigationButtonType);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
index 4ae1304..2f42e70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
@@ -8,7 +8,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.widget.TextViewCompat;
-import android.support.v7.widget.AppCompatImageView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -20,6 +19,7 @@
 import org.chromium.chrome.browser.download.DownloadDirectoryProvider;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.widget.TintedImageView;
 import org.chromium.chrome.download.R;
 
 import java.util.ArrayList;
@@ -146,7 +146,7 @@
             }
         }
 
-        AppCompatImageView imageView = (AppCompatImageView) view.findViewById(R.id.icon_view);
+        TintedImageView imageView = (TintedImageView) view.findViewById(R.id.icon_view);
         imageView.setVisibility(View.GONE);
 
         return view;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListBaseAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListBaseAdapter.java
index 3cd386ae..ed7fa35 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListBaseAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListBaseAdapter.java
@@ -11,7 +11,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.view.ViewCompat;
-import android.support.v7.widget.AppCompatImageView;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.support.v7.widget.helper.ItemTouchHelper;
@@ -26,6 +25,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.widget.ListMenuButton;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -52,7 +52,7 @@
         private TextView mTitle;
         private TextView mDescription;
 
-        private AppCompatImageView mStartIcon;
+        private TintedImageView mStartIcon;
         private ListMenuButton mMoreButton;
 
         LanguageRowViewHolder(View view) {
@@ -61,7 +61,7 @@
             mTitle = (TextView) view.findViewById(R.id.title);
             mDescription = (TextView) view.findViewById(R.id.description);
 
-            mStartIcon = (AppCompatImageView) view.findViewById(R.id.icon_view);
+            mStartIcon = (TintedImageView) view.findViewById(R.id.icon_view);
             mMoreButton = (ListMenuButton) view.findViewById(R.id.more);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
index 695b294..021fbe6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -13,7 +13,6 @@
 import android.os.Bundle;
 import android.support.annotation.StringRes;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.InputType;
 import android.text.SpannableString;
 import android.text.Spanned;
@@ -36,6 +35,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.components.sync.AndroidSyncSettings;
 import org.chromium.ui.text.SpanApplier;
 import org.chromium.ui.widget.Toast;
@@ -266,7 +266,7 @@
     }
 
     private void hookupCopyUsernameButton(View usernameView) {
-        final AppCompatImageButton copyUsernameButton =
+        final TintedImageButton copyUsernameButton =
                 usernameView.findViewById(R.id.password_entry_editor_copy);
         copyUsernameButton.setImageDrawable(
                 AppCompatResources.getDrawable(getActivity(), R.drawable.ic_content_copy_black));
@@ -288,7 +288,7 @@
     }
 
     private void hookupCopySiteButton(View siteView) {
-        final AppCompatImageButton copySiteButton =
+        final TintedImageButton copySiteButton =
                 siteView.findViewById(R.id.password_entry_editor_copy);
         copySiteButton.setContentDescription(
                 getActivity().getString(R.string.password_entry_editor_copy_stored_site));
@@ -362,7 +362,7 @@
     }
 
     private void hookupPasswordButtons() {
-        final AppCompatImageButton copyPasswordButton =
+        final TintedImageButton copyPasswordButton =
                 mView.findViewById(R.id.password_entry_editor_copy_password);
         final ImageButton viewPasswordButton =
                 mView.findViewById(R.id.password_entry_editor_view_password);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
index 5da2c6d..a0c93b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
@@ -390,5 +390,10 @@
         public Promise<Bitmap> getPromise() {
             return mThumbnailReceivedPromise;
         }
+
+        @Override
+        public String getMimeType() {
+            return null;
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
index 03e48c5..e1cf6e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBinder.java
@@ -16,7 +16,6 @@
 import android.os.SystemClock;
 import android.support.annotation.Nullable;
 import android.support.v4.text.BidiFormatter;
-import android.support.v4.widget.ImageViewCompat;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.view.View;
@@ -37,6 +36,7 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.util.ViewUtils;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 /**
  * This class is directly connected to suggestions view holders. It takes over the responsibility
@@ -252,7 +252,7 @@
         } else {
             mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder);
         }
-        if (!mIsContextual) ImageViewCompat.setImageTintList(mThumbnailView, null);
+        if (!mIsContextual) ((TintedImageView) mThumbnailView).setTint(null);
 
         // Fetch thumbnail for the current article.
         mImageFetcher.makeArticleThumbnailRequest(
@@ -301,7 +301,7 @@
         mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP);
         mThumbnailView.setBackground(null);
         mThumbnailView.setImageDrawable(thumbnail);
-        if (!mIsContextual) ImageViewCompat.setImageTintList(mThumbnailView, null);
+        if (!mIsContextual) ((TintedImageView) mThumbnailView).setTint(null);
     }
 
     private void setThumbnailFromFileType(@DownloadFilter.Type int fileType) {
@@ -313,9 +313,7 @@
         mThumbnailView.setBackgroundColor(iconBackgroundColor);
         mThumbnailView.setImageResource(
                 DownloadUtils.getIconResId(fileType, DownloadUtils.IconSize.DP_36));
-        if (!mIsContextual) {
-            ImageViewCompat.setImageTintList(mThumbnailView, iconForegroundColorList);
-        }
+        if (!mIsContextual) ((TintedImageView) mThumbnailView).setTint(iconForegroundColorList);
     }
 
     private void setDefaultFaviconOnView(int faviconSizePx) {
@@ -344,7 +342,7 @@
 
         mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP);
         mThumbnailView.setBackground(null);
-        if (!mIsContextual) ImageViewCompat.setImageTintList(mThumbnailView, null);
+        if (!mIsContextual) ((TintedImageView) mThumbnailView).setTint(null);
         int duration = (int) (FADE_IN_ANIMATION_TIME_MS
                 * ChromeAnimation.Animation.getAnimationMultiplier());
         if (duration == 0) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java
index 44106cdcb..bdceb17 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.toolbar;
 
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -14,6 +13,7 @@
 import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor;
 import org.chromium.chrome.browser.toolbar.ToolbarButtonSlotData.ToolbarButtonData;
 import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 
 /**
  * This class is responsible for pushing updates to both the Android view and the compositor
@@ -34,19 +34,19 @@
         /** A handle to the composited bottom toolbar layer. */
         public ScrollingBottomViewSceneLayer sceneLayer;
 
-        /** Cached {@link android.support.v7.widget.AppCompatImageButton} of the first button. */
-        public final AppCompatImageButton firstImageButton;
+        /** Cached {@link TintedImageButton} of the first button. */
+        public final TintedImageButton firstTintedImageButton;
 
-        /** Cached {@link android.support.v7.widget.AppCompatImageButton} of the second button. */
-        public final AppCompatImageButton secondImageButton;
+        /** Cached {@link TintedImageButton} of the second button. */
+        public final TintedImageButton secondTintedImageButton;
 
         /**
          * @param toolbarRootView The Android View based toolbar.
          */
         public ViewHolder(ScrollingBottomViewResourceFrameLayout toolbarRootView) {
             toolbarRoot = toolbarRootView;
-            firstImageButton = toolbarRoot.findViewById(R.id.first_button);
-            secondImageButton = toolbarRoot.findViewById(R.id.second_button);
+            firstTintedImageButton = toolbarRoot.findViewById(R.id.first_button);
+            secondTintedImageButton = toolbarRoot.findViewById(R.id.second_button);
         }
     }
 
@@ -86,18 +86,18 @@
         } else if (BottomToolbarModel.TOOLBAR_SWIPE_HANDLER == propertyKey) {
             view.toolbarRoot.setSwipeDetector(model.get(BottomToolbarModel.TOOLBAR_SWIPE_HANDLER));
         } else if (BottomToolbarModel.FIRST_BUTTON_DATA == propertyKey) {
-            updateButton(view.firstImageButton, model.get(BottomToolbarModel.FIRST_BUTTON_DATA),
-                    useLightIcons(model));
+            updateButton(view.firstTintedImageButton,
+                    model.get(BottomToolbarModel.FIRST_BUTTON_DATA), useLightIcons(model));
         } else if (BottomToolbarModel.SECOND_BUTTON_DATA == propertyKey) {
-            updateButton(view.secondImageButton, model.get(BottomToolbarModel.SECOND_BUTTON_DATA),
-                    useLightIcons(model));
+            updateButton(view.secondTintedImageButton,
+                    model.get(BottomToolbarModel.SECOND_BUTTON_DATA), useLightIcons(model));
         } else if (BottomToolbarModel.PRIMARY_COLOR == propertyKey) {
             final boolean useLightIcons = useLightIcons(model);
             view.toolbarRoot.findViewById(R.id.bottom_sheet_toolbar)
                     .setBackgroundColor(model.get(BottomToolbarModel.PRIMARY_COLOR));
-            updateButtonDrawable(view.firstImageButton,
+            updateButtonDrawable(view.firstTintedImageButton,
                     model.get(BottomToolbarModel.FIRST_BUTTON_DATA), useLightIcons);
-            updateButtonDrawable(view.secondImageButton,
+            updateButtonDrawable(view.secondTintedImageButton,
                     model.get(BottomToolbarModel.SECOND_BUTTON_DATA), useLightIcons);
         } else {
             assert false : "Unhandled property detected in BottomToolbarViewBinder!";
@@ -110,7 +110,7 @@
     }
 
     private static void updateButton(
-            AppCompatImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) {
+            TintedImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) {
         if (buttonData == null) {
             ToolbarButtonData.clearButton(button);
         } else {
@@ -119,7 +119,7 @@
     }
 
     private static void updateButtonDrawable(
-            AppCompatImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) {
+            TintedImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) {
         if (buttonData != null) buttonData.updateButtonDrawable(button, useLightIcons);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
index 799c412d..5d82548 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -23,8 +23,6 @@
 import android.support.annotation.Nullable;
 import android.support.v4.text.BidiFormatter;
 import android.support.v4.view.MarginLayoutParamsCompat;
-import android.support.v4.widget.ImageViewCompat;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.SpannableString;
 import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
@@ -62,6 +60,7 @@
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.net.GURLUtils;
@@ -132,7 +131,7 @@
     private View mLiteStatusSeparatorView;
     private UrlBarCoordinator mUrlCoordinator;
     private TextView mTitleBar;
-    private AppCompatImageButton mSecurityButton;
+    private TintedImageButton mSecurityButton;
     private LinearLayout mCustomActionButtons;
     private ImageButton mCloseButton;
 
@@ -504,8 +503,7 @@
 
     private void updateButtonsTint() {
         if (getMenuButton() != null) {
-            ImageViewCompat.setImageTintList(
-                    getMenuButton(), mUseDarkColors ? mDarkModeTint : mLightModeTint);
+            getMenuButton().setTint(mUseDarkColors ? mDarkModeTint : mLightModeTint);
         }
         updateButtonTint(mCloseButton);
         int numCustomActionButtons = mCustomActionButtons.getChildCount();
@@ -551,8 +549,7 @@
         } else {
             // ImageView#setImageResource is no-op if given resource is the current one.
             mSecurityButton.setImageResource(securityIconResource);
-            ImageViewCompat.setImageTintList(
-                    mSecurityButton, getToolbarDataProvider().getSecurityIconColorStateList());
+            mSecurityButton.setTint(getToolbarDataProvider().getSecurityIconColorStateList());
             mAnimDelegate.showSecurityButton();
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java
index 7f13edf..29eba6c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.toolbar;
 
 import android.content.Context;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -17,12 +16,14 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 
 /**
  * View that displays the home page button.
  */
-public class HomePageButton extends AppCompatImageButton
+public class HomePageButton extends TintedImageButton
         implements OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener {
+
     private static final int ID_REMOVE = 0;
 
     /** Constructor inflating from XML. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
index b93bafd39..b48b03161 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
@@ -6,20 +6,21 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.support.v4.widget.ImageViewCompat;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.View.AccessibilityDelegate;
+import android.view.View.OnTouchListener;
 import android.widget.FrameLayout;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 
 /**
  * The overflow menu button.
  */
 class MenuButton extends FrameLayout {
-    /** The {@link android.support.v7.widget.AppCompatImageButton} for the menu button. */
-    private AppCompatImageButton mMenuImageButton;
+    /** The {@link TintedImageButton} for the menu button. */
+    private TintedImageButton mMenuTintedImageButton;
 
     /** The view for the update badge. */
     private View mUpdateBadgeView;
@@ -31,7 +32,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mMenuImageButton = findViewById(R.id.menu_button);
+        mMenuTintedImageButton = findViewById(R.id.menu_button);
         mUpdateBadgeView = findViewById(R.id.menu_badge);
     }
 
@@ -40,12 +41,12 @@
      *                        clicked.
      */
     void setTouchListener(OnTouchListener onTouchListener) {
-        mMenuImageButton.setOnTouchListener(onTouchListener);
+        mMenuTintedImageButton.setOnTouchListener(onTouchListener);
     }
 
     @Override
     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
-        mMenuImageButton.setAccessibilityDelegate(delegate);
+        mMenuTintedImageButton.setAccessibilityDelegate(delegate);
     }
 
     /**
@@ -63,7 +64,7 @@
     }
 
     View getMenuButton() {
-        return mMenuImageButton;
+        return mMenuTintedImageButton;
     }
 
     /**
@@ -71,6 +72,6 @@
      *                 tinted).
      */
     void setTint(ColorStateList tintList) {
-        ImageViewCompat.setImageTintList(mMenuImageButton, tintList);
+        mMenuTintedImageButton.setTint(tintList);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java
index c5089fef..8599e1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java
@@ -13,11 +13,11 @@
 import android.graphics.drawable.Drawable;
 import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.View;
 import android.view.View.OnClickListener;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.ui.interpolators.BakedBezierInterpolator;
 
 /**
@@ -75,19 +75,19 @@
         }
 
         /**
-         * @param imageButton The {@link AppCompatImageButton} this button data will fill.
+         * @param imageButton The {@link TintedImageButton} this button data will fill.
          * @param isLight Whether or not to use light mode.
          */
-        void updateButton(AppCompatImageButton imageButton, boolean isLight) {
+        void updateButton(TintedImageButton imageButton, boolean isLight) {
             imageButton.setOnClickListener(mOnClickListener);
             updateButtonDrawable(imageButton, isLight);
         }
 
         /**
-         * @param imageButton The {@link AppCompatImageButton} this button data will fill.
+         * @param imageButton The {@link TintedImageButton} this button data will fill.
          * @param isLight Whether or not to use light mode.
          */
-        void updateButtonDrawable(AppCompatImageButton imageButton, boolean isLight) {
+        void updateButtonDrawable(TintedImageButton imageButton, boolean isLight) {
             ObjectAnimator fadeOutAnim =
                     ObjectAnimator.ofFloat(imageButton, View.ALPHA, 1.0f, 0.0f);
             fadeOutAnim.setDuration(FADE_DURATION / 2);
@@ -124,7 +124,7 @@
             animatorSet.start();
         }
 
-        static void clearButton(AppCompatImageButton button) {
+        static void clearButton(TintedImageButton button) {
             ToolbarButtonData emptyButtonData =
                     new ToolbarButtonData(null, "", "", null, button.getContext());
             emptyButtonData.updateButton(button, false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index f8cd899..125178c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -18,7 +18,6 @@
 import android.support.annotation.StringRes;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.InputDevice;
 import android.view.MotionEvent;
@@ -45,6 +44,7 @@
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.browser.widget.PulseDrawable;
 import org.chromium.chrome.browser.widget.ScrimView;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.ToolbarProgressBar;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
@@ -63,7 +63,7 @@
     /**
      * The ImageButton view that represents the menu button.
      */
-    protected AppCompatImageButton mMenuButton;
+    protected TintedImageButton mMenuButton;
     private ImageView mMenuBadge;
     private View mMenuButtonWrapper;
     private AppMenuButtonHelper mAppMenuButtonHelper;
@@ -156,7 +156,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mMenuButton = (AppCompatImageButton) findViewById(R.id.menu_button);
+        mMenuButton = (TintedImageButton) findViewById(R.id.menu_button);
         mMenuBadge = (ImageView) findViewById(R.id.menu_badge);
         mMenuButtonWrapper = findViewById(R.id.menu_button_wrapper);
 
@@ -306,9 +306,9 @@
     }
 
     /**
-     * @return The {@link AppCompatImageButton} containing the menu button.
+     * @return The {@link TintedImageButton} containing the menu button.
      */
-    protected AppCompatImageButton getMenuButton() {
+    protected TintedImageButton getMenuButton() {
         return mMenuButton;
     }
 
@@ -986,7 +986,7 @@
      * #onNativeLibraryReady() & once in #onFinishInflate() (see https://crbug.com/862887).
      * @param ntpButton The button that needs to be changed.
      */
-    protected void changeIconToNTPIcon(AppCompatImageButton ntpButton) {
+    protected void changeIconToNTPIcon(TintedImageButton ntpButton) {
         if (FeatureUtilities.isNewTabPageButtonEnabled())
             ntpButton.setImageResource(R.drawable.ic_home);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index e3ace30..789ce1d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -30,9 +30,7 @@
 import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.animation.FastOutSlowInInterpolator;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.graphics.drawable.DrawableWrapper;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.util.Property;
 import android.util.TypedValue;
@@ -78,6 +76,7 @@
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.chrome.browser.util.ViewUtils;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.animation.CancelAwareAnimatorListener;
 import org.chromium.chrome.browser.widget.newtab.NewTabButton;
 import org.chromium.chrome.browser.widget.textbubble.TextBubble;
@@ -148,11 +147,11 @@
     private IncognitoToggleTabLayout mIncognitoToggleTabLayout;
     protected ImageView mToggleTabStackButton;
     protected NewTabButton mNewTabButton;
-    protected @Nullable AppCompatImageButton mHomeButton;
+    protected @Nullable TintedImageButton mHomeButton;
     private TextView mUrlBar;
     protected View mUrlActionContainer;
     protected ImageView mToolbarShadow;
-    private @Nullable AppCompatImageButton mExperimentalButton;
+    private @Nullable TintedImageButton mExperimentalButton;
 
     private final int mProgressBackBackgroundColorWhite;
 
@@ -394,7 +393,7 @@
 
             mToolbarButtonsContainer = (ViewGroup) findViewById(R.id.toolbar_buttons);
 
-            mHomeButton = (AppCompatImageButton) findViewById(R.id.home_button);
+            mHomeButton = (TintedImageButton) findViewById(R.id.home_button);
             changeIconToNTPIcon(mHomeButton);
             if (FeatureUtilities.isBottomToolbarEnabled()) {
                 disableMenuButton();
@@ -494,7 +493,7 @@
         mToggleTabStackButton.setOnKeyListener(new KeyboardNavigationListener() {
             @Override
             public View getNextFocusForward() {
-                final AppCompatImageButton menuButton = getMenuButton();
+                final TintedImageButton menuButton = getMenuButton();
                 if (menuButton != null && menuButton.isShown()) {
                     return menuButton;
                 } else {
@@ -1381,7 +1380,7 @@
         }
 
         // Draw the menu button if necessary.
-        final AppCompatImageButton menuButton = getMenuButton();
+        final TintedImageButton menuButton = getMenuButton();
         if (menuButton != null && !mShowMenuBadge && mTabSwitcherAnimationMenuDrawable != null
                 && mUrlExpansionPercent != 1f) {
             mTabSwitcherAnimationMenuDrawable.setBounds(menuButton.getPaddingLeft(),
@@ -1721,8 +1720,7 @@
     private void addHomeButton() {
         mHomeButton.setVisibility(
                 urlHasFocus() || isTabSwitcherAnimationRunning() ? INVISIBLE : VISIBLE);
-        ColorStateList tintList = mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint;
-        ImageViewCompat.setImageTintList(mHomeButton, tintList);
+        mHomeButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
         mBrowsingModeViews.add(mHomeButton);
     }
 
@@ -2576,14 +2574,12 @@
         }
 
         if (getMenuButton() != null) {
-            ColorStateList tintList = mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint;
-            ImageViewCompat.setImageTintList(getMenuButton(), tintList);
+            getMenuButton().setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
         }
 
         updateModernLocationBarColor(getLocationBarColorForToolbarColor(currentPrimaryColor));
         if (mExperimentalButton != null) {
-            ColorStateList tintList = mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint;
-            ImageViewCompat.setImageTintList(mExperimentalButton, tintList);
+            mExperimentalButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
         }
 
         setMenuButtonHighlightDrawable(mHighlightingMenu);
@@ -2591,9 +2587,7 @@
             setAppMenuUpdateBadgeDrawable(mUseLightToolbarDrawables);
         }
         ColorStateList tint = mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint;
-        if (mIsHomeButtonEnabled && mHomeButton != null) {
-            ImageViewCompat.setImageTintList(mHomeButton, tint);
-        }
+        if (mIsHomeButtonEnabled && mHomeButton != null) mHomeButton.setTint(tint);
 
         mLocationBar.updateVisualsForState();
 
@@ -2695,7 +2689,7 @@
             OnClickListener onClickListener, int drawableResId, int contentDescriptionResId) {
         if (mExperimentalButton == null) {
             ViewStub viewStub = findViewById(R.id.experimental_button_stub);
-            mExperimentalButton = (AppCompatImageButton) viewStub.inflate();
+            mExperimentalButton = (TintedImageButton) viewStub.inflate();
 
             if (!isMenuButtonPresent()) mExperimentalButton.setPadding(0, 0, 0, 0);
             mExperimentalButtonTranslation = getResources().getDimensionPixelSize(
@@ -2714,8 +2708,7 @@
         mExperimentalButton.setImageResource(drawableResId);
         mExperimentalButton.setContentDescription(
                 getContext().getResources().getString(contentDescriptionResId));
-        ImageViewCompat.setImageTintList(
-                mExperimentalButton, mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
+        mExperimentalButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
 
         if (mTabSwitcherState == STATIC_TAB) {
             if (!mUrlFocusChangeInProgress && !urlHasFocus()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
index 4626f83..9e034ac5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
@@ -11,9 +11,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.support.v4.view.ViewCompat;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -34,6 +32,7 @@
 import org.chromium.chrome.browser.util.AccessibilityUtil;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.ui.base.DeviceFormFactor;
 
 import java.util.ArrayList;
@@ -48,13 +47,13 @@
     // The number of toolbar buttons that can be hidden at small widths (reload, back, forward).
     public static final int HIDEABLE_BUTTON_COUNT = 3;
 
-    private AppCompatImageButton mHomeButton;
-    private AppCompatImageButton mBackButton;
-    private AppCompatImageButton mForwardButton;
-    private AppCompatImageButton mReloadButton;
-    private AppCompatImageButton mBookmarkButton;
-    private AppCompatImageButton mSaveOfflineButton;
-    private AppCompatImageButton mSecurityButton;
+    private TintedImageButton mHomeButton;
+    private TintedImageButton mBackButton;
+    private TintedImageButton mForwardButton;
+    private TintedImageButton mReloadButton;
+    private TintedImageButton mBookmarkButton;
+    private TintedImageButton mSaveOfflineButton;
+    private TintedImageButton mSecurityButton;
     private ImageButton mAccessibilitySwitcherButton;
 
     private OnClickListener mBookmarkListener;
@@ -64,7 +63,7 @@
 
     private boolean mShowTabStack;
     private boolean mToolbarButtonsVisible;
-    private AppCompatImageButton[] mToolbarButtons;
+    private TintedImageButton[] mToolbarButtons;
 
     private NavigationPopup mNavigationPopup;
 
@@ -99,12 +98,12 @@
         super.onFinishInflate();
         mLocationBar = (LocationBarTablet) findViewById(R.id.location_bar);
 
-        mHomeButton = (AppCompatImageButton) findViewById(R.id.home_button);
+        mHomeButton = (TintedImageButton) findViewById(R.id.home_button);
         changeIconToNTPIcon(mHomeButton);
-        mBackButton = (AppCompatImageButton) findViewById(R.id.back_button);
-        mForwardButton = (AppCompatImageButton) findViewById(R.id.forward_button);
-        mReloadButton = (AppCompatImageButton) findViewById(R.id.refresh_button);
-        mSecurityButton = (AppCompatImageButton) findViewById(R.id.security_button);
+        mBackButton = (TintedImageButton) findViewById(R.id.back_button);
+        mForwardButton = (TintedImageButton) findViewById(R.id.forward_button);
+        mReloadButton = (TintedImageButton) findViewById(R.id.refresh_button);
+        mSecurityButton = (TintedImageButton) findViewById(R.id.security_button);
         mShowTabStack = AccessibilityUtil.isAccessibilityEnabled()
                 && isAccessibilityTabSwitcherPreferenceEnabled();
 
@@ -117,7 +116,7 @@
         mAccessibilitySwitcherButton.setImageDrawable(mTabSwitcherButtonDrawable);
         updateSwitcherButtonVisibility(mShowTabStack);
 
-        mBookmarkButton = (AppCompatImageButton) findViewById(R.id.bookmark_button);
+        mBookmarkButton = (TintedImageButton) findViewById(R.id.bookmark_button);
 
         final View menuButtonWrapper = getMenuButtonWrapper();
         menuButtonWrapper.setVisibility(View.VISIBLE);
@@ -128,13 +127,13 @@
                     getResources().getDimensionPixelSize(R.dimen.tablet_toolbar_end_padding), 0);
         }
 
-        mSaveOfflineButton = (AppCompatImageButton) findViewById(R.id.save_offline_button);
+        mSaveOfflineButton = (TintedImageButton) findViewById(R.id.save_offline_button);
 
         // Initialize values needed for showing/hiding toolbar buttons when the activity size
         // changes.
         mShouldAnimateButtonVisibilityChange = false;
         mToolbarButtonsVisible = true;
-        mToolbarButtons = new AppCompatImageButton[] {mBackButton, mForwardButton, mReloadButton};
+        mToolbarButtons = new TintedImageButton[] {mBackButton, mForwardButton, mReloadButton};
     }
 
     @Override
@@ -383,16 +382,11 @@
             setBackgroundColor(color);
             getProgressBar().setThemeColor(color, isIncognito());
 
-            ImageViewCompat.setImageTintList(
-                    getMenuButton(), incognito ? mLightModeTint : mDarkModeTint);
-            ImageViewCompat.setImageTintList(
-                    mHomeButton, incognito ? mLightModeTint : mDarkModeTint);
-            ImageViewCompat.setImageTintList(
-                    mBackButton, incognito ? mLightModeTint : mDarkModeTint);
-            ImageViewCompat.setImageTintList(
-                    mForwardButton, incognito ? mLightModeTint : mDarkModeTint);
-            ImageViewCompat.setImageTintList(
-                    mSaveOfflineButton, incognito ? mLightModeTint : mDarkModeTint);
+            getMenuButton().setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mHomeButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mBackButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mForwardButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mSaveOfflineButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
             if (incognito) {
                 mLocationBar.getContainerView().getBackground().setAlpha(
                         ToolbarPhone.LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA);
@@ -477,8 +471,7 @@
             mReloadButton.setContentDescription(getContext().getString(
                     R.string.accessibility_btn_refresh));
         }
-        ImageViewCompat.setImageTintList(
-                mReloadButton, isIncognito() ? mLightModeTint : mDarkModeTint);
+        mReloadButton.setTint(isIncognito() ? mLightModeTint : mDarkModeTint);
         mReloadButton.setEnabled(!mIsInTabSwitcherMode);
     }
 
@@ -487,16 +480,14 @@
         if (isBookmarked) {
             mBookmarkButton.setImageResource(R.drawable.btn_star_filled);
             // Non-incognito mode shows a blue filled star.
-            ImageViewCompat.setImageTintList(mBookmarkButton,
-                    isIncognito() ? mLightModeTint
-                                  : AppCompatResources.getColorStateList(
-                                            getContext(), R.color.blue_mode_tint));
+            mBookmarkButton.setTint(isIncognito() ? mLightModeTint
+                                                  : AppCompatResources.getColorStateList(
+                                                            getContext(), R.color.blue_mode_tint));
             mBookmarkButton.setContentDescription(getContext().getString(
                     R.string.edit_bookmark));
         } else {
             mBookmarkButton.setImageResource(R.drawable.btn_star);
-            ImageViewCompat.setImageTintList(
-                    mBookmarkButton, isIncognito() ? mLightModeTint : mDarkModeTint);
+            mBookmarkButton.setTint(isIncognito() ? mLightModeTint : mDarkModeTint);
             mBookmarkButton.setContentDescription(getContext().getString(
                     R.string.accessibility_menu_bookmark));
         }
@@ -613,7 +604,7 @@
         if (mShouldAnimateButtonVisibilityChange) {
             runToolbarButtonsVisibilityAnimation(visible);
         } else {
-            for (AppCompatImageButton button : mToolbarButtons) {
+            for (TintedImageButton button : mToolbarButtons) {
                 button.setVisibility(visible ? View.VISIBLE : View.GONE);
             }
             mLocationBar.setShouldShowButtonsWhenUnfocused(visible);
@@ -655,7 +646,7 @@
         Collection<Animator> animators = new ArrayList<>();
 
         // Create animators for all of the toolbar buttons.
-        for (AppCompatImageButton button : mToolbarButtons) {
+        for (TintedImageButton button : mToolbarButtons) {
             animators.add(mLocationBar.createShowButtonAnimator(button));
         }
 
@@ -669,7 +660,7 @@
         set.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                for (AppCompatImageButton button : mToolbarButtons) {
+                for (TintedImageButton button : mToolbarButtons) {
                     button.setVisibility(View.VISIBLE);
                 }
                 // Set the padding at the start of the animation so the toolbar buttons don't jump
@@ -690,7 +681,7 @@
         Collection<Animator> animators = new ArrayList<>();
 
         // Create animators for all of the toolbar buttons.
-        for (AppCompatImageButton button : mToolbarButtons) {
+        for (TintedImageButton button : mToolbarButtons) {
             animators.add(mLocationBar.createHideButtonAnimator(button));
         }
 
@@ -707,7 +698,7 @@
                 // Only set end visibility and alpha if the animation is ending because it's
                 // completely finished and not because it was canceled.
                 if (mToolbarButtons[0].getAlpha() == 0.f) {
-                    for (AppCompatImageButton button : mToolbarButtons) {
+                    for (TintedImageButton button : mToolbarButtons) {
                         button.setVisibility(View.GONE);
                         button.setAlpha(1.f);
                     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
new file mode 100644
index 0000000..ceca4af
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
@@ -0,0 +1,87 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget;
+
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import org.chromium.chrome.R;
+
+/**
+ * Utility for tinting an ImageView and its Drawable.
+ *
+ * Example usage in XML:
+ * <ImageViewTinterInstanceOwner
+ *     xmlns:android="http://schemas.android.com/apk/res/android"
+ *     xmlns:app="http://schemas.android.com/apk/res-auto"
+ *     app:chrometint="@color/default_icon_color_blue" />
+ */
+public class ImageViewTinter {
+    /** Classes that own an ImageViewTinter must implement these functions. */
+    public static interface ImageViewTinterOwner {
+        /** See {@link ImageViewTinter#drawableStateChanged}. */
+        void drawableStateChanged();
+
+        /** See {@link ImageViewTinter#setTint}. */
+        void setTint(ColorStateList tintList);
+
+        /** See {@link ImageView#onDraw}. */
+        void onDraw(Canvas canvas);
+    }
+
+    private ImageView mImageView;
+    private ColorStateList mTintList;
+
+    /**
+     * Constructor.  Should be called with the AttributeSet and style of the ImageView so that XML
+     * attributes for it can be parsed.
+     * @param view     ImageView being tinted.
+     * @param attrs    AttributeSet that is pulled in from an XML layout.  May be null.
+     * @param defStyle Style that is pulled in from an XML layout.
+     */
+    public ImageViewTinter(ImageViewTinterOwner view, @Nullable AttributeSet attrs, int defStyle) {
+        mImageView = (ImageView) view;
+
+        // Parse out the attributes from the XML.
+        if (attrs != null) {
+            TypedArray a = mImageView.getContext().obtainStyledAttributes(
+                    attrs, R.styleable.TintedImage, defStyle, 0);
+            setTint(a.getColorStateList(R.styleable.TintedImage_chrometint));
+            a.recycle();
+        }
+    }
+
+    /**
+     * Sets the tint color for the given ImageView for all states.
+     * @param tintList The set of colors to use.
+     */
+    public void setTint(ColorStateList tintList) {
+        if (mTintList == tintList) return;
+        mTintList = tintList;
+        updateTintColor();
+    }
+
+    /** Call when the state of the Drawable has changed. */
+    public void drawableStateChanged() {
+        updateTintColor();
+    }
+
+    private void updateTintColor() {
+        if (mImageView.getDrawable() == null) {
+            return;
+        } else if (mTintList == null) {
+            mImageView.clearColorFilter();
+            return;
+        }
+
+        int tintColor = mTintList.getColorForState(mImageView.getDrawableState(), 0);
+        mImageView.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
index 6ce4179d..86e4b26 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
@@ -9,7 +9,6 @@
 import android.graphics.Rect;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.StringRes;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -29,7 +28,7 @@
  * results.
  */
 public class ListMenuButton
-        extends AppCompatImageButton implements AnchoredPopupWindow.LayoutObserver {
+        extends TintedImageButton implements AnchoredPopupWindow.LayoutObserver {
     private final static int INVALID_RES_ID = 0;
 
     /** A class that represents a single item in the popup menu. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailGenerator.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailGenerator.java
index f05b33e..a1bf97e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailGenerator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailGenerator.java
@@ -42,7 +42,7 @@
         boolean hasFilePath = !TextUtils.isEmpty(request.getFilePath());
         assert hasFilePath;
         nativeRetrieveThumbnail(getNativeThumbnailGenerator(), request.getContentId(),
-                request.getFilePath(), request.getIconSize(), callback);
+                request.getFilePath(), request.getMimeType(), request.getIconSize(), callback);
     }
 
     /**
@@ -80,5 +80,6 @@
     private native long nativeInit();
     private native void nativeDestroy(long nativeThumbnailGenerator);
     private native void nativeRetrieveThumbnail(long nativeThumbnailGenerator, String contentId,
-            String filePath, int thumbnailSize, ThumbnailGeneratorCallback callback);
-}
\ No newline at end of file
+            String filePath, String mimeType, int thumbnailSize,
+            ThumbnailGeneratorCallback callback);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailProvider.java
index c496dd2..26da3c16 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ThumbnailProvider.java
@@ -20,6 +20,10 @@
         @Nullable
         String getFilePath();
 
+        /** The mime type of the file. */
+        @Nullable
+        String getMimeType();
+
         /** Content ID that uniquely identifies the file. */
         @Nullable
         String getContentId();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java
new file mode 100644
index 0000000..baf542e
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java
@@ -0,0 +1,78 @@
+// 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.
+
+package org.chromium.chrome.browser.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+
+import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner;
+
+/**
+ * Implementation of ImageButton that allows tinting the Drawable for all states.
+ * For usage, see {@link ImageViewTinter}.
+ */
+public class TintedImageButton extends ImageButton implements ImageViewTinterOwner {
+    private ImageViewTinter mTinter;
+
+    public TintedImageButton(Context context) {
+        super(context);
+        init(null, 0);
+    }
+
+    public TintedImageButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs, 0);
+    }
+
+    public TintedImageButton(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs, defStyle);
+    }
+
+    private void init(AttributeSet attrs, int defStyle) {
+        mTinter = new ImageViewTinter(this, attrs, defStyle);
+    }
+
+    @Override
+    public void drawableStateChanged() {
+        super.drawableStateChanged();
+        mTinter.drawableStateChanged();
+    }
+
+    @Override
+    public void setImageDrawable(@Nullable Drawable drawable) {
+        super.setImageDrawable(drawable);
+        maybeUpdateTint();
+    }
+
+    @Override
+    public void setImageResource(int resId) {
+        super.setImageResource(resId);
+        maybeUpdateTint();
+    }
+
+    @Override
+    public void setTint(ColorStateList tintList) {
+        mTinter.setTint(tintList);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+    }
+
+    private void maybeUpdateTint() {
+        if (mTinter == null) {
+            // Got indirectly invoked from the superclass constructor, nothing to do yet.
+            return;
+        }
+        mTinter.drawableStateChanged();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java
new file mode 100644
index 0000000..61c2df7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java
@@ -0,0 +1,78 @@
+// 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.
+
+package org.chromium.chrome.browser.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.AppCompatImageView;
+import android.util.AttributeSet;
+
+import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner;
+
+/**
+ * Implementation of ImageView that allows tinting its Drawable for all states.
+ * For usage, see {@link ImageViewTinter}.
+ */
+public class TintedImageView extends AppCompatImageView implements ImageViewTinterOwner {
+    private ImageViewTinter mTinter;
+
+    public TintedImageView(Context context) {
+        super(context);
+        init(null, 0);
+    }
+
+    public TintedImageView(Context context, AttributeSet attrs) {
+        super(context, attrs, 0);
+        init(attrs, 0);
+    }
+
+    public TintedImageView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs, defStyle);
+    }
+
+    private void init(AttributeSet attrs, int defStyle) {
+        mTinter = new ImageViewTinter(this, attrs, defStyle);
+    }
+
+    @Override
+    public void drawableStateChanged() {
+        super.drawableStateChanged();
+        mTinter.drawableStateChanged();
+    }
+
+    @Override
+    public void setImageDrawable(@Nullable Drawable drawable) {
+        super.setImageDrawable(drawable);
+        maybeUpdateTint();
+    }
+
+    @Override
+    public void setImageResource(int resId) {
+        super.setImageResource(resId);
+        maybeUpdateTint();
+    }
+
+    @Override
+    public void setTint(ColorStateList tintList) {
+        mTinter.setTint(tintList);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+    }
+
+    private void maybeUpdateTint() {
+        if (mTinter == null) {
+            // Got indirectly invoked from the superclass constructor, nothing to do yet.
+            return;
+        }
+        mTinter.drawableStateChanged();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
index c34dbe1..c8650e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
@@ -13,10 +13,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.os.Handler;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
-import android.support.v7.widget.AppCompatImageView;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
@@ -37,6 +34,8 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.widget.TintedImageButton;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 /**
  * A widget that shows a single row of the {@link AccessibilityTabModelListView} list.
@@ -73,8 +72,8 @@
     private LinearLayout mTabContents;
     private TextView mTitleView;
     private TextView mDescriptionView;
-    private AppCompatImageView mFaviconView;
-    private AppCompatImageButton mCloseButton;
+    private TintedImageView mFaviconView;
+    private TintedImageButton mCloseButton;
 
     // The children on the undo view.
     private LinearLayout mUndoContents;
@@ -312,13 +311,13 @@
             mFaviconView.getBackground().setLevel(mIncognitoLevel);
             ApiCompatibilityUtils.setTextAppearance(mTitleView, R.style.WhiteTitle1);
             ApiCompatibilityUtils.setTextAppearance(mDescriptionView, R.style.WhiteBody);
-            ImageViewCompat.setImageTintList(mCloseButton, mLightCloseIconColor);
+            mCloseButton.setTint(mLightCloseIconColor);
         } else {
             setBackgroundResource(R.color.modern_primary_color);
             mFaviconView.getBackground().setLevel(mDefaultLevel);
             ApiCompatibilityUtils.setTextAppearance(mTitleView, R.style.BlackTitle1);
             ApiCompatibilityUtils.setTextAppearance(mDescriptionView, R.style.BlackBody);
-            ImageViewCompat.setImageTintList(mCloseButton, mDarkCloseIconColor);
+            mCloseButton.setTint(mDarkCloseIconColor);
         }
 
         if (TextUtils.isEmpty(url)) {
@@ -334,11 +333,11 @@
             Bitmap bitmap = mTab.getFavicon();
             if (bitmap != null) {
                 // Don't tint favicon bitmaps.
-                ImageViewCompat.setImageTintList(mFaviconView, null);
+                mFaviconView.setTint(null);
                 mFaviconView.setImageBitmap(bitmap);
             } else {
                 mFaviconView.setImageResource(R.drawable.ic_globe_24dp);
-                ImageViewCompat.setImageTintList(mFaviconView, mDarkIconColor);
+                mFaviconView.setTint(mDarkIconColor);
             }
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
index d5f2c78..01930f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
@@ -7,9 +7,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.support.design.widget.TabLayout;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageView;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -23,6 +21,7 @@
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.widget.TintedImageView;
 import org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelAdapter.AccessibilityTabModelAdapterListener;
 
 /**
@@ -37,8 +36,8 @@
     private TabLayout mStackButtonWrapper;
     private TabLayout.Tab mStandardButton;
     private TabLayout.Tab mIncognitoButton;
-    private AppCompatImageView mStandardButtonIcon;
-    private AppCompatImageView mIncognitoButtonIcon;
+    private TintedImageView mStandardButtonIcon;
+    private TintedImageView mIncognitoButtonIcon;
 
     private ColorStateList mTabIconDarkColor;
     private ColorStateList mTabIconLightColor;
@@ -107,12 +106,12 @@
                 AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
         // Setting scaleY here to make sure the icons are not flipped due to the scaleY of its
         // container layout.
-        mStandardButtonIcon = new AppCompatImageView(getContext());
+        mStandardButtonIcon = new TintedImageView(getContext());
         mStandardButtonIcon.setImageResource(R.drawable.btn_normal_tabs);
         mStandardButtonIcon.setScaleY(-1.0f);
         mStandardButtonIcon.setContentDescription(
                 getResources().getString(R.string.accessibility_tab_switcher_standard_stack));
-        mIncognitoButtonIcon = new AppCompatImageView(getContext());
+        mIncognitoButtonIcon = new TintedImageView(getContext());
         mIncognitoButtonIcon.setImageResource(R.drawable.btn_incognito_tabs);
         mIncognitoButtonIcon.setScaleY(-1.0f);
         mIncognitoButtonIcon.setContentDescription(getResources().getString(
@@ -179,15 +178,15 @@
                     getResources(), R.color.incognito_modern_primary_color));
             mStackButtonWrapper.setSelectedTabIndicatorColor(
                     mTabIconSelectedLightColor.getDefaultColor());
-            ImageViewCompat.setImageTintList(mStandardButtonIcon, mTabIconLightColor);
-            ImageViewCompat.setImageTintList(mIncognitoButtonIcon, mTabIconSelectedLightColor);
+            mStandardButtonIcon.setTint(mTabIconLightColor);
+            mIncognitoButtonIcon.setTint(mTabIconSelectedLightColor);
         } else {
             setBackgroundColor(
                     ApiCompatibilityUtils.getColor(getResources(), R.color.modern_primary_color));
             mStackButtonWrapper.setSelectedTabIndicatorColor(
                     mTabIconSelectedDarkColor.getDefaultColor());
-            ImageViewCompat.setImageTintList(mStandardButtonIcon, mTabIconSelectedDarkColor);
-            ImageViewCompat.setImageTintList(mIncognitoButtonIcon, mTabIconDarkColor);
+            mStandardButtonIcon.setTint(mTabIconSelectedDarkColor);
+            mIncognitoButtonIcon.setTint(mTabIconDarkColor);
         }
         // Ensure the tab in tab layout is correctly selected when tab switcher is
         // first opened.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
index 933f5c7..e24411c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
@@ -15,7 +15,6 @@
 import android.provider.Settings;
 import android.support.annotation.IntDef;
 import android.support.v4.view.accessibility.AccessibilityEventCompat;
-import android.support.v7.widget.AppCompatImageButton;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.Selection;
@@ -46,6 +45,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.VerticallyFixedEditText;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -73,9 +73,9 @@
     // Toolbar UI
     private TextView mFindStatus;
     protected FindQuery mFindQuery;
-    protected AppCompatImageButton mCloseFindButton;
-    protected AppCompatImageButton mFindPrevButton;
-    protected AppCompatImageButton mFindNextButton;
+    protected TintedImageButton mCloseFindButton;
+    protected TintedImageButton mFindPrevButton;
+    protected TintedImageButton mFindNextButton;
 
     private FindResultBar mResultBar;
 
@@ -310,7 +310,7 @@
 
         mFindStatus = (TextView) findViewById(R.id.find_status);
 
-        mFindPrevButton = (AppCompatImageButton) findViewById(R.id.find_prev_button);
+        mFindPrevButton = (TintedImageButton) findViewById(R.id.find_prev_button);
         mFindPrevButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -318,7 +318,7 @@
             }
         });
 
-        mFindNextButton = (AppCompatImageButton) findViewById(R.id.find_next_button);
+        mFindNextButton = (TintedImageButton) findViewById(R.id.find_next_button);
         mFindNextButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -328,7 +328,7 @@
 
         setPrevNextEnabled(false);
 
-        mCloseFindButton = (AppCompatImageButton) findViewById(R.id.close_find_button);
+        mCloseFindButton = (TintedImageButton) findViewById(R.id.close_find_button);
         mCloseFindButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
index 0685416..a2874a5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
@@ -7,7 +7,6 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
@@ -49,17 +48,17 @@
             setBackgroundColor(ColorUtils.getDefaultThemeColor(getResources(), true));
             ColorStateList white =
                     AppCompatResources.getColorStateList(getContext(), R.color.light_mode_tint);
-            ImageViewCompat.setImageTintList(mFindNextButton, white);
-            ImageViewCompat.setImageTintList(mFindPrevButton, white);
-            ImageViewCompat.setImageTintList(mCloseFindButton, white);
+            mFindNextButton.setTint(white);
+            mFindPrevButton.setTint(white);
+            mCloseFindButton.setTint(white);
             queryTextColorId = R.color.find_in_page_query_white_color;
         } else {
             setBackgroundColor(Color.WHITE);
             ColorStateList dark =
                     AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
-            ImageViewCompat.setImageTintList(mFindNextButton, dark);
-            ImageViewCompat.setImageTintList(mFindPrevButton, dark);
-            ImageViewCompat.setImageTintList(mCloseFindButton, dark);
+            mFindNextButton.setTint(dark);
+            mFindPrevButton.setTint(dark);
+            mCloseFindButton.setTint(dark);
             queryTextColorId = R.color.default_text_color;
         }
         mFindQuery.setTextColor(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/incognitotoggle/IncognitoToggleButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/incognitotoggle/IncognitoToggleButton.java
index f932324..f0cc03a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/incognitotoggle/IncognitoToggleButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/incognitotoggle/IncognitoToggleButton.java
@@ -6,9 +6,7 @@
 
 import android.content.Context;
 import android.support.annotation.StringRes;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -18,6 +16,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 
 /**
  * A {@link View} that allows a user to toggle between incognito and normal {@link TabModel}s. This
@@ -25,7 +24,7 @@
  * TabModelSelector switches between normal and incognito modes. It can be subclassed (e.g. as is
  * done in IncognitoToggleButtonTablet) to add additional behaviors.
  */
-public class IncognitoToggleButton extends AppCompatImageButton {
+public class IncognitoToggleButton extends TintedImageButton {
     // TODO(crbug.com/843749): refactor this class so it doesn't need to hold a reference to
     // TabModelSelector.
     protected TabModelSelector mTabModelSelector;
@@ -74,9 +73,8 @@
      */
     protected void setImage(boolean isIncognitoSelected) {
         setImageResource(R.drawable.incognito_simple);
-        ImageViewCompat.setImageTintList(this,
-                AppCompatResources.getColorStateList(getContext(),
-                        isIncognitoSelected ? R.color.white_mode_tint : R.color.dark_mode_tint));
+        setTint(AppCompatResources.getColorStateList(getContext(),
+                isIncognitoSelected ? R.color.white_mode_tint : R.color.dark_mode_tint));
     }
 
     private void updateButtonResource() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
index 55f827ab..294b6e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
@@ -10,14 +10,13 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
-import android.support.v4.widget.ImageViewCompat;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageView;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.TintedImageView;
 
 /**
  * Default implementation of SelectableItemViewBase.
@@ -29,7 +28,7 @@
     protected final int mSelectedLevel;
     protected final AnimatedVectorDrawableCompat mCheckDrawable;
 
-    protected AppCompatImageView mIconView;
+    protected TintedImageView mIconView;
     protected TextView mTitleView;
     protected TextView mDescriptionView;
     protected ColorStateList mIconColorList;
@@ -53,13 +52,13 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mIconView = (AppCompatImageView) findViewById(R.id.icon_view);
+        mIconView = (TintedImageView) findViewById(R.id.icon_view);
         mTitleView = (TextView) findViewById(R.id.title);
         mDescriptionView = (TextView) findViewById(R.id.description);
 
         if (mIconView != null) {
             mIconView.setBackgroundResource(R.drawable.list_item_icon_modern_bg);
-            ImageViewCompat.setImageTintList(mIconView, getDefaultIconTint());
+            mIconView.setTint(getDefaultIconTint());
         }
     }
 
@@ -83,12 +82,12 @@
         if (isChecked()) {
             mIconView.getBackground().setLevel(mSelectedLevel);
             mIconView.setImageDrawable(mCheckDrawable);
-            ImageViewCompat.setImageTintList(mIconView, mIconColorList);
+            mIconView.setTint(mIconColorList);
             mCheckDrawable.start();
         } else {
             mIconView.getBackground().setLevel(mDefaultLevel);
             mIconView.setImageDrawable(mIconDrawable);
-            ImageViewCompat.setImageTintList(mIconView, getDefaultIconTint());
+            mIconView.setTint(getDefaultIconTint());
         }
     }
 
@@ -113,7 +112,7 @@
      * @param isSelected    Whether the item is selected or not.
      */
     public static void applyModernIconStyle(
-            AppCompatImageView imageView, Drawable defaultIcon, boolean isSelected) {
+            TintedImageView imageView, Drawable defaultIcon, boolean isSelected) {
         imageView.setBackgroundResource(R.drawable.list_item_icon_modern_bg);
         imageView.setImageDrawable(isSelected
                         ? TintedDrawable.constructTintedDrawable(imageView.getContext(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
index 1cd0dfb..4fd14ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -16,7 +16,6 @@
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.content.res.AppCompatResources;
-import android.support.v7.widget.AppCompatImageButton;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
 import android.text.TextUtils;
@@ -45,6 +44,7 @@
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.widget.NumberRollView;
 import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver;
 import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
@@ -98,7 +98,7 @@
     private LinearLayout mSearchView;
     private EditText mSearchText;
     private EditText mSearchEditText;
-    private AppCompatImageButton mClearTextButton;
+    private TintedImageButton mClearTextButton;
     private SearchDelegate mSearchDelegate;
     private boolean mSearchEnabled;
     private boolean mIsVrEnabled;
@@ -296,7 +296,7 @@
             public void afterTextChanged(Editable s) {}
         });
 
-        mClearTextButton = (AppCompatImageButton) findViewById(R.id.clear_text_button);
+        mClearTextButton = (TintedImageButton) findViewById(R.id.clear_text_button);
         mClearTextButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 0997cea..ba80c08 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -485,6 +485,7 @@
   "java/src/org/chromium/chrome/browser/download/home/filter/FilterProperties.java",
   "java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java",
   "java/src/org/chromium/chrome/browser/download/home/filter/FilterViewBinder.java",
+  "java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java",
   "java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilter.java",
   "java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterObserver.java",
   "java/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterSource.java",
@@ -1622,6 +1623,7 @@
   "java/src/org/chromium/chrome/browser/widget/FadingShadow.java",
   "java/src/org/chromium/chrome/browser/widget/FadingShadowView.java",
   "java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java",
+  "java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java",
   "java/src/org/chromium/chrome/browser/widget/ListMenuButton.java",
   "java/src/org/chromium/chrome/browser/widget/LoadingView.java",
   "java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java",
@@ -1645,6 +1647,8 @@
   "java/src/org/chromium/chrome/browser/widget/ThumbnailProvider.java",
   "java/src/org/chromium/chrome/browser/widget/ThumbnailProviderImpl.java",
   "java/src/org/chromium/chrome/browser/widget/TintedDrawable.java",
+  "java/src/org/chromium/chrome/browser/widget/TintedImageButton.java",
+  "java/src/org/chromium/chrome/browser/widget/TintedImageView.java",
   "java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java",
   "java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java",
   "java/src/org/chromium/chrome/browser/widget/VerticallyFixedEditText.java",
@@ -2157,6 +2161,7 @@
   "javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/webauth/AuthenticatorTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/DualControlLayoutTest.java",
+  "javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java",
   "javatests/src/org/chromium/chrome/browser/widget/RadioButtonLayoutTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMediaParserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMediaParserTest.java
index 96fe0a8..b39060d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMediaParserTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMediaParserTest.java
@@ -63,7 +63,7 @@
         // The native DownloadMediaParser needs to be created on UI thread.
         ThreadUtils.runOnUiThreadBlocking(() -> {
             DownloadMediaParserBridge parser = new DownloadMediaParserBridge(
-                    mimeType, filePath, mediaFile.length(), (DownloadMediaData mediaData) -> {
+                    mimeType, filePath, (DownloadMediaData mediaData) -> {
                         result.mediaData = mediaData;
                         result.done = true;
                     });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 5137015..48fc68b8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -23,7 +23,6 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.intent.rule.IntentsTestRule;
 import android.support.test.filters.SmallTest;
-import android.support.v7.widget.AppCompatImageButton;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.text.TextUtils;
@@ -53,6 +52,7 @@
 import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
 import org.chromium.chrome.browser.signin.SignoutReason;
 import org.chromium.chrome.browser.widget.DateDividedAdapter;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
@@ -190,7 +190,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                ((AppCompatImageButton) itemView.findViewById(R.id.remove)).performClick();
+                ((TintedImageButton) itemView.findViewById(R.id.remove)).performClick();
             }
         });
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
index 0919498..0bc7323 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.omnibox;
 
 import android.support.test.filters.SmallTest;
-import android.support.v7.widget.AppCompatImageButton;
 import android.view.View;
 
 import org.junit.Assert;
@@ -25,6 +24,7 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceTestUtils;
 import org.chromium.chrome.browser.toolbar.ToolbarModel;
+import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
@@ -131,17 +131,16 @@
         return (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
     }
 
-    private AppCompatImageButton getDeleteButton() {
-        return (AppCompatImageButton) mActivityTestRule.getActivity().findViewById(
-                R.id.delete_button);
+    private TintedImageButton getDeleteButton() {
+        return (TintedImageButton) mActivityTestRule.getActivity().findViewById(R.id.delete_button);
     }
 
-    private AppCompatImageButton getMicButton() {
-        return (AppCompatImageButton) mActivityTestRule.getActivity().findViewById(R.id.mic_button);
+    private TintedImageButton getMicButton() {
+        return (TintedImageButton) mActivityTestRule.getActivity().findViewById(R.id.mic_button);
     }
 
-    private AppCompatImageButton getSecurityButton() {
-        return (AppCompatImageButton) mActivityTestRule.getActivity().findViewById(
+    private TintedImageButton getSecurityButton() {
+        return (TintedImageButton) mActivityTestRule.getActivity().findViewById(
                 R.id.security_button);
     }
 
@@ -270,7 +269,7 @@
         mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.NONE);
         setUrlToPageUrl(locationBar);
 
-        AppCompatImageButton securityButton = getSecurityButton();
+        TintedImageButton securityButton = getSecurityButton();
         Assert.assertNotEquals(SEARCH_TERMS, urlBar.getText().toString());
         ThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertNotEquals(mTestToolbarModel.getSecurityIconResource(
@@ -290,7 +289,7 @@
         mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
         setUrlToPageUrl(locationBar);
 
-        AppCompatImageButton securityButton = getSecurityButton();
+        TintedImageButton securityButton = getSecurityButton();
         Assert.assertEquals(securityButton.getVisibility(), View.VISIBLE);
         ThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertEquals(mTestToolbarModel.getSecurityIconResource(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
new file mode 100644
index 0000000..9ec150a3d
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
@@ -0,0 +1,180 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.UiThreadTestRule;
+import android.support.v7.content.res.AppCompatResources;
+import android.view.LayoutInflater;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+
+/**
+ * Tests the classes that use ImageViewTinter.
+ *
+ * In an ideal world, these tests would simply use an XmlPullParser and XML that is defined inside
+ * this test, but Android explicitly disallows that because it pre-processes the XML files:
+ * https://developer.android.com/reference/android/view/LayoutInflater.html
+ *
+ * An alternative would be to have test-specific layout directories, but these don't seem to be
+ * able to reference the instrumented package's resources.  Instead, the tests reference XML for
+ * actual controls used in the production app.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class ImageViewTinterTest {
+    @Rule
+    public UiThreadTestRule mRule = new UiThreadTestRule();
+
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mContext.setTheme(R.style.MainTheme);
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageView_attributeParsingExplicitTint() throws Exception {
+        // The tint is explicitly set to a blue in the XML.
+        int color = ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.blue_mode_tint);
+        TintedImageView clearStorageView = (TintedImageView) LayoutInflater.from(mContext).inflate(
+                R.layout.clear_storage, null, false);
+        Assert.assertNotNull(clearStorageView.getColorFilter());
+        Assert.assertTrue(checkIfTintWasApplied(clearStorageView, color));
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageButton_attributeParsingExplicitTint() throws Exception {
+        // The tint was explicitly set to a color.
+        int color = ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.dark_mode_tint);
+        TintedImageButton colorTint =
+                createImageView(R.layout.search_toolbar, R.id.clear_text_button);
+        Assert.assertNotNull(colorTint.getColorFilter());
+        Assert.assertTrue(checkIfTintWasApplied(colorTint, color));
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageView_attributeParsingNullTint() throws Exception {
+        // The tint is explicitly set to null in the XML.
+        int color = ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.blue_mode_tint);
+        TintedImageView nullTint = createImageView(R.layout.title_button_menu_item, R.id.checkbox);
+        Assert.assertNull(nullTint.getColorFilter());
+        Assert.assertFalse(checkIfTintWasApplied(nullTint, color));
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageButton_attributeParsingNullTint() throws Exception {
+        // The tint is explicitly set to null in the XML.  An image resource needs to be set here
+        // because the layout doesn't define one by default.
+        int color =
+                ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.blue_when_enabled);
+        TintedImageButton nullTint = createImageView(R.layout.title_button_menu_item, R.id.button);
+        Assert.assertNull(nullTint.getColorFilter());
+        nullTint.setImageResource(R.drawable.plus);
+        Assert.assertFalse(checkIfTintWasApplied(nullTint, color));
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageView_setTint() throws Exception {
+        // The tint is explicitly set to null for this object in the XML.
+        TintedImageView nullTint = createImageView(R.layout.title_button_menu_item, R.id.checkbox);
+        checkSetTintWorksCorrectly(nullTint);
+    }
+
+    @Test
+    @SmallTest
+    public void testTintedImageButton_setTint() throws Exception {
+        // The tint is explicitly set to null for this object in the XML.
+        TintedImageButton nullTint = createImageView(R.layout.title_button_menu_item, R.id.button);
+        checkSetTintWorksCorrectly(nullTint);
+    }
+
+    private void checkSetTintWorksCorrectly(ImageViewTinterOwner view) {
+        ImageView imageView = (ImageView) view;
+        int color = ApiCompatibilityUtils.getColor(
+                mContext.getResources(), R.color.default_icon_color_blue);
+
+        Assert.assertNull(imageView.getColorFilter());
+        if (imageView.getDrawable() == null) {
+            // An image resource is set here in case the layout does not define one.
+            imageView.setImageResource(R.drawable.plus);
+        }
+        Assert.assertFalse(checkIfTintWasApplied(view, color));
+
+        // Set the tint to one color.
+        ColorStateList colorList =
+                AppCompatResources.getColorStateList(mContext, R.color.light_active_color);
+        view.setTint(colorList);
+        Assert.assertNotNull(imageView.getColorFilter());
+        Assert.assertTrue(checkIfTintWasApplied(view, color));
+
+        // Clear it out.
+        view.setTint(null);
+        Assert.assertNull(imageView.getColorFilter());
+        Assert.assertFalse(checkIfTintWasApplied(view, color));
+
+        // Set it to another color.
+        int otherColor =
+                ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.google_red_700);
+        ColorStateList otherColorList =
+                AppCompatResources.getColorStateList(mContext, R.color.google_red_700);
+        view.setTint(otherColorList);
+        Assert.assertNotNull(imageView.getColorFilter());
+        Assert.assertTrue(checkIfTintWasApplied(view, otherColor));
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T extends ImageView> T createImageView(int layoutId, int ownerId) {
+        ViewGroup root = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutId, null, false);
+        return (T) root.findViewById(ownerId);
+    }
+
+    private boolean checkIfTintWasApplied(
+            ImageViewTinterOwner imageViewTinterOwner, int expectedColor) {
+        int unspecifiedSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        Assert.assertTrue(imageViewTinterOwner instanceof ImageView);
+        ImageView imageView = (ImageView) imageViewTinterOwner;
+        imageView.measure(unspecifiedSpec, unspecifiedSpec);
+        imageView.layout(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight());
+
+        // Draw the ImageView into a Canvas so we can check that the tint was applied.
+        Drawable drawable = imageView.getDrawable();
+        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        imageViewTinterOwner.onDraw(canvas);
+
+        // Search for any pixel that is of the expected color.
+        for (int x = 0; x < bitmap.getWidth(); x++) {
+            for (int y = 0; y < bitmap.getHeight(); y++) {
+                if (expectedColor == bitmap.getPixel(x, y)) return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailDiskStorageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailDiskStorageTest.java
index 3bd51de..6482d31 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailDiskStorageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailDiskStorageTest.java
@@ -64,6 +64,11 @@
         }
 
         @Override
+        public String getMimeType() {
+            return null;
+        }
+
+        @Override
         public String getContentId() {
             return mContentId;
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
index cf320d8..7828b74 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
@@ -189,6 +189,11 @@
         }
 
         @Override
+        public String getMimeType() {
+            return null;
+        }
+
+        @Override
         public @Nullable String getContentId() {
             return "contentId"; // None-null value for ThumbnailProviderImpl to work
         }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterTest.java
index c0f2fa9..4b14409d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/download/home/filter/OfflineItemFilterTest.java
@@ -39,9 +39,13 @@
         }
 
         public void setFilters(Set<OfflineItem> items) {
+            setFiltersSilently(items);
+            onFilterChanged();
+        }
+
+        public void setFiltersSilently(Set<OfflineItem> items) {
             mFilteredItems.clear();
             mFilteredItems.addAll(items);
-            onFilterChanged();
         }
 
         // OfflineItemFilter implementation.
@@ -163,6 +167,7 @@
         OfflineItem newItem2 = new OfflineItem();
         sourceItems.remove(item2);
         sourceItems.add(newItem2);
+        filter.setFiltersSilently(CollectionUtil.newHashSet(item1, newItem2, item4));
         filter.onItemUpdated(item2, newItem2);
         verify(mObserver, never()).onItemUpdated(item2, newItem2);
         Assert.assertEquals(CollectionUtil.newHashSet(item3), filter.getItems());
@@ -188,4 +193,41 @@
         verify(mObserver, times(1)).onItemUpdated(item3, newItem3);
         Assert.assertEquals(CollectionUtil.newHashSet(newItem3), filter.getItems());
     }
+
+    @Test
+    public void testUpdateFiltering() {
+        OfflineItem item1 = new OfflineItem();
+        OfflineItem item2 = new OfflineItem();
+        Collection<OfflineItem> sourceItems = CollectionUtil.newHashSet(item1, item2);
+        when(mSource.getItems()).thenReturn(sourceItems);
+
+        OfflineItemFilterImpl filter = new OfflineItemFilterImpl(mSource);
+        filter.addObserver(mObserver);
+        verify(mSource, times(1)).addObserver(filter);
+        verify(mSource, times(1)).getItems();
+        Assert.assertEquals(sourceItems, filter.getItems());
+
+        // Filter items.
+        filter.setFilters(CollectionUtil.newHashSet(item2));
+        verify(mObserver, times(1)).onItemsRemoved(CollectionUtil.newHashSet(item2));
+        Assert.assertEquals(CollectionUtil.newHashSet(item1), filter.getItems());
+
+        // Updated item goes from unfiltered to filtered.
+        OfflineItem newItem1 = new OfflineItem();
+        filter.setFiltersSilently(CollectionUtil.newHashSet(newItem1, item2));
+        sourceItems.remove(item1);
+        sourceItems.add(newItem1);
+        filter.onItemUpdated(item1, newItem1);
+        verify(mObserver, times(1)).onItemsRemoved(CollectionUtil.newHashSet(item1));
+        Assert.assertTrue(filter.getItems().isEmpty());
+
+        // Updated item goes from filtered to unfiltered.
+        OfflineItem newItem2 = new OfflineItem();
+        filter.setFiltersSilently(CollectionUtil.newHashSet(newItem1));
+        sourceItems.remove(item2);
+        sourceItems.add(newItem2);
+        filter.onItemUpdated(item2, newItem2);
+        verify(mObserver, times(1)).onItemsAdded(CollectionUtil.newHashSet(newItem2));
+        Assert.assertEquals(CollectionUtil.newHashSet(newItem2), filter.getItems());
+    }
 }
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 4941516..7b7ace0f 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3188,12 +3188,6 @@
         <message name="IDS_TASK_MANAGER_ARC_SYSTEM" desc="The prefix for an ARC system processes row">
           System: <ph name="ARC_PROCESS_NAME">$1<ex>com.android.systemui</ex></ph>
         </message>
-        <message name="IDS_TASK_MANAGER_ISOLATED_SUBFRAMES_PREFIX" desc="The prefix for an out-of-process-iframe row in the Task Manager for subframes that were isolated because of 'top document isolation' mode">
-          Subframes for: <ph name="PARENT_SITE">$1<ex>https://youtube.com/</ex></ph>
-        </message>
-        <message name="IDS_TASK_MANAGER_ISOLATED_INCOGNITO_SUBFRAMES_PREFIX" desc="The prefix for an Incognito out-of-process-iframe row in the Task Manager for subframes that were isolated because of 'top document isolation' mode">
-          Incognito subframes for: <ph name="PARENT_SITE">$1<ex>https://youtube.com/</ex></ph>
-        </message>
       </if>
 
       <message name="IDS_UTILITY_PROCESS_IMAGE_DECODER_NAME" desc="The name of the utility process used for decoding images.">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 5930028..0528f78 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1424,10 +1424,10 @@
       Display name (optional)
     </message>
     <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_USERNAME" desc="Title for the input that lets users specify their username for an SMB share.">
-      Username
+      Username (optional)
     </message>
     <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_PASSWORD" desc="Title for the input that lets users specify their password for an SMB Share.">
-      Password
+      Password (optional)
     </message>
     <message name="IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_SUCCESS_MESSAGE" desc="The message shown when a new SMB share is successfully mounted.">
       Share mounted successfully.
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 3d7e89e..ebdab35db 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -108,6 +108,8 @@
     "autocomplete/shortcuts_backend_factory.h",
     "autofill/address_normalizer_factory.cc",
     "autofill/address_normalizer_factory.h",
+    "autofill/autofill_profile_validator_factory.cc",
+    "autofill/autofill_profile_validator_factory.h",
     "autofill/personal_data_manager_factory.cc",
     "autofill/personal_data_manager_factory.h",
     "autofill/risk_util.cc",
@@ -453,6 +455,8 @@
     "download/offline_item_utils.h",
     "download/save_package_file_picker.cc",
     "download/save_package_file_picker.h",
+    "download/thumbnail_util.cc",
+    "download/thumbnail_util.h",
     "download/trusted_sources_manager.cc",
     "download/trusted_sources_manager.h",
     "download/trusted_sources_manager_win.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 51b0c48..20db1f4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -145,6 +145,8 @@
 #include "ui/native_theme/native_theme_features.h"
 #include "ui/views/views_switches.h"
 
+#include "services/service_manager/sandbox/features.h"
+
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/chrome_feature_list.h"
 #include "chrome/browser/android/explore_sites/explore_sites_feature.h"
@@ -2232,10 +2234,6 @@
      flag_descriptions::kSiteIsolationTrialOptOutName,
      flag_descriptions::kSiteIsolationTrialOptOutDescription, kOsAll,
      MULTI_VALUE_TYPE(kSiteIsolationTrialOptOutChoices)},
-    {"enable-top-document-isolation",
-     flag_descriptions::kTopDocumentIsolationName,
-     flag_descriptions::kTopDocumentIsolationDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kTopDocumentIsolation)},
     {"enable-use-zoom-for-dsf", flag_descriptions::kEnableUseZoomForDsfName,
      flag_descriptions::kEnableUseZoomForDsfDescription, kOsAll,
      MULTI_VALUE_TYPE(kEnableUseZoomForDSFChoices)},
@@ -2434,6 +2432,11 @@
      flag_descriptions::kOpenVRDescription, kOsWin,
      FEATURE_VALUE_TYPE(features::kOpenVR)},
 #endif  // ENABLE_OPENVR
+#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE)
+    {"xr-sandbox", flag_descriptions::kXRSandboxName,
+     flag_descriptions::kXRSandboxDescription, kOsWin,
+     FEATURE_VALUE_TYPE(service_manager::features::kXRSandbox)},
+#endif  // ENABLE_ISOLATED_XR_SERVICE
 #endif  // ENABLE_VR
 #if defined(OS_CHROMEOS)
     {"disable-accelerated-mjpeg-decode",
diff --git a/chrome/browser/android/download/download_media_parser.cc b/chrome/browser/android/download/download_media_parser.cc
index 41c4a6e..78e6cd6 100644
--- a/chrome/browser/android/download/download_media_parser.cc
+++ b/chrome/browser/android/download/download_media_parser.cc
@@ -6,9 +6,11 @@
 
 #include "base/bind.h"
 #include "base/files/file.h"
+#include "base/files/file_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
+#include "base/task_runner_util.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "chrome/browser/android/download/local_media_data_source_factory.h"
 #include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
@@ -38,19 +40,23 @@
 void OnRequestOverlayInfo(bool decoder_requires_restart_for_overlay,
                           const media::ProvideOverlayInfoCB& overlay_info_cb) {
   // No android overlay associated with video thumbnail.
-  overlay_info_cb.Run(media::OverlayInfo());
+  if (overlay_info_cb)
+    overlay_info_cb.Run(media::OverlayInfo());
+}
+
+int64_t GetFileSize(const base::FilePath& file_path) {
+  int64_t size = 0;
+  if (!base::GetFileSize(file_path, &size))
+    return -1;
+  return size;
 }
 
 }  // namespace
 
-DownloadMediaParser::DownloadMediaParser(int64_t size,
-                                         const std::string& mime_type,
-                                         const base::FilePath& file_path,
-                                         ParseCompleteCB parse_complete_cb)
-    : size_(size),
-      mime_type_(mime_type),
+DownloadMediaParser::DownloadMediaParser(const std::string& mime_type,
+                                         const base::FilePath& file_path)
+    : mime_type_(mime_type),
       file_path_(file_path),
-      parse_complete_cb_(std::move(parse_complete_cb)),
       file_task_runner_(
           base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})),
       decode_done_(false),
@@ -58,13 +64,30 @@
 
 DownloadMediaParser::~DownloadMediaParser() = default;
 
-void DownloadMediaParser::Start() {
+void DownloadMediaParser::Start(ParseCompleteCB parse_complete_cb) {
+  parse_complete_cb_ = std::move(parse_complete_cb);
+
   // Only process media mime types.
   if (!IsSupportedMediaMimeType(mime_type_)) {
     OnError();
     return;
   }
 
+  // Get the size of the file if needed.
+  base::PostTaskAndReplyWithResult(
+      file_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&GetFileSize, file_path_),
+      base::BindOnce(&DownloadMediaParser::OnReadFileSize,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void DownloadMediaParser::OnReadFileSize(int64_t file_size) {
+  if (file_size < 0) {
+    OnError();
+    return;
+  }
+
+  size_ = file_size;
   RetrieveMediaParser(
       content::ServiceManagerConnection::GetForProcess()->GetConnector());
 }
@@ -188,6 +211,7 @@
 
   decoder_->Start(base::BindOnce(&DownloadMediaParser::OnVideoFrameDecoded,
                                  weak_factory_.GetWeakPtr()));
+  video_frame_data_.reset();
 }
 
 void DownloadMediaParser::OnVideoFrameDecoded(
@@ -205,8 +229,15 @@
 
 void DownloadMediaParser::RenderVideoFrame(
     scoped_refptr<media::VideoFrame> video_frame) {
+  media::Context3D context;
+  gpu::ContextSupport* context_support = nullptr;
   auto context_provider =
       gpu_factories_ ? gpu_factories_->GetMediaContextProvider() : nullptr;
+  if (context_provider) {
+    context = media::Context3D(context_provider->ContextGL(),
+                               context_provider->GrContext());
+    context_support = context_provider->ContextSupport();
+  }
 
   media::PaintCanvasVideoRenderer renderer;
   SkBitmap bitmap;
@@ -215,11 +246,7 @@
 
   // Draw the video frame to |bitmap|.
   cc::SkiaPaintCanvas canvas(bitmap);
-  media::Context3D context =
-      context_provider ? media::Context3D(context_provider->ContextGL(),
-                                          context_provider->GrContext())
-                       : media::Context3D();
-  renderer.Copy(video_frame, &canvas, context);
+  renderer.Copy(video_frame, &canvas, context, context_support);
 
   NotifyComplete(std::move(bitmap));
 }
diff --git a/chrome/browser/android/download/download_media_parser.h b/chrome/browser/android/download/download_media_parser.h
index 1b7c209..48c6b82 100644
--- a/chrome/browser/android/download/download_media_parser.h
+++ b/chrome/browser/android/download/download_media_parser.h
@@ -34,9 +34,9 @@
 // Parse local media files, including media metadata and thumbnails.
 // Metadata is always parsed in utility process for both audio and video files.
 //
-// For video file, the thumbnail may be poster image in metadata or extracted
-// video frame. The frame extraction always happens in utility process. The
-// decoding may happen in utility or GPU process based on video codec.
+// For video file, the thumbnail will be the a video key frame. The frame
+// extraction always happens in utility process. The decoding may happen in
+// utility or GPU process based on video codec.
 class DownloadMediaParser : public MediaParserProvider, public media::MediaLog {
  public:
   using ParseCompleteCB =
@@ -44,19 +44,19 @@
                               chrome::mojom::MediaMetadataPtr media_metadata,
                               SkBitmap bitmap)>;
 
-  DownloadMediaParser(int64_t size,
-                      const std::string& mime_type,
-                      const base::FilePath& file_path,
-                      ParseCompleteCB parse_complete_cb);
+  DownloadMediaParser(const std::string& mime_type,
+                      const base::FilePath& file_path);
   ~DownloadMediaParser() override;
 
-  // Parse media metadata in a local file. All file IO will run on
+  // Parse media metadata and thumbnail in a local file. All file IO will run on
   // |file_task_runner|. The metadata is parsed in an utility process safely.
   // The thumbnail is retrieved from GPU process or utility process based on
   // different codec.
-  void Start();
+  void Start(ParseCompleteCB parse_complete_cb);
 
  private:
+  void OnReadFileSize(int64_t file_size);
+
   // MediaParserProvider implementation:
   void OnMediaParserCreated() override;
   void OnConnectionError() override;
diff --git a/chrome/browser/android/download/download_media_parser_bridge.cc b/chrome/browser/android/download/download_media_parser_bridge.cc
index 0508cd8..d363e0508 100644
--- a/chrome/browser/android/download/download_media_parser_bridge.cc
+++ b/chrome/browser/android/download/download_media_parser_bridge.cc
@@ -47,7 +47,6 @@
     const base::android::JavaParamRef<jobject>& jcaller,
     const base::android::JavaParamRef<jstring>& jmime_type,
     const base::android::JavaParamRef<jstring>& jfile_path,
-    jlong jtotal_size,
     const base::android::JavaParamRef<jobject>& jcallback) {
   base::FilePath file_path(
       base::android::ConvertJavaStringToUTF8(env, jfile_path));
@@ -55,22 +54,18 @@
       base::android::ConvertJavaStringToUTF8(env, jmime_type);
 
   auto* bridge = new DownloadMediaParserBridge(
-      static_cast<int64_t>(jtotal_size), mime_type, file_path,
+      mime_type, file_path,
       base::BindOnce(&OnMediaParsed,
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback)));
   return reinterpret_cast<intptr_t>(bridge);
 }
 
 DownloadMediaParserBridge::DownloadMediaParserBridge(
-    int64_t size,
     const std::string& mime_type,
     const base::FilePath& file_path,
     DownloadMediaParser::ParseCompleteCB parse_complete_cb)
-    : parser_(std::make_unique<DownloadMediaParser>(
-          size,
-          mime_type,
-          file_path,
-          std::move(parse_complete_cb))) {}
+    : parser_(std::make_unique<DownloadMediaParser>(mime_type, file_path)),
+      parse_complete_cb_(std::move(parse_complete_cb)) {}
 
 DownloadMediaParserBridge::~DownloadMediaParserBridge() = default;
 
@@ -79,5 +74,5 @@
 }
 
 void DownloadMediaParserBridge::Start(JNIEnv* env, jobject obj) {
-  parser_->Start();
+  parser_->Start(std::move(parse_complete_cb_));
 }
diff --git a/chrome/browser/android/download/download_media_parser_bridge.h b/chrome/browser/android/download/download_media_parser_bridge.h
index 7bbac04..a028055 100644
--- a/chrome/browser/android/download/download_media_parser_bridge.h
+++ b/chrome/browser/android/download/download_media_parser_bridge.h
@@ -19,7 +19,6 @@
 class DownloadMediaParserBridge {
  public:
   DownloadMediaParserBridge(
-      int64_t size,
       const std::string& mime_type,
       const base::FilePath& file_path,
       DownloadMediaParser::ParseCompleteCB parse_complete_cb);
@@ -31,6 +30,7 @@
  private:
   // The media parser that does actual jobs in a sandboxed process.
   std::unique_ptr<DownloadMediaParser> parser_;
+  DownloadMediaParser::ParseCompleteCB parse_complete_cb_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadMediaParserBridge);
 };
diff --git a/chrome/browser/android/ntp/android_content_suggestions_notifier.cc b/chrome/browser/android/ntp/android_content_suggestions_notifier.cc
index 6b12a2d..39649c69 100644
--- a/chrome/browser/android/ntp/android_content_suggestions_notifier.cc
+++ b/chrome/browser/android/ntp/android_content_suggestions_notifier.cc
@@ -39,7 +39,7 @@
     base::Time timeout_at,
     int priority) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  SkBitmap skimage = image.AsImageSkia().GetRepresentation(1.0f).sk_bitmap();
+  SkBitmap skimage = image.AsImageSkia().GetRepresentation(1.0f).GetBitmap();
   if (skimage.empty())
     return false;
 
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index 0df762c..dce5be8 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -397,7 +397,7 @@
     return;
   }
 
-  SkBitmap favicon = image.AsImageSkia().GetRepresentation(1.0f).sk_bitmap();
+  SkBitmap favicon = image.AsImageSkia().GetRepresentation(1.0f).GetBitmap();
   if (favicon.empty())
     return;
 
diff --git a/chrome/browser/android/widget/thumbnail_generator.cc b/chrome/browser/android/widget/thumbnail_generator.cc
index d08816c..58c4246 100644
--- a/chrome/browser/android/widget/thumbnail_generator.cc
+++ b/chrome/browser/android/widget/thumbnail_generator.cc
@@ -8,6 +8,8 @@
 
 #include "base/android/jni_string.h"
 #include "base/threading/thread_restrictions.h"
+#include "chrome/browser/android/download/download_media_parser.h"
+#include "chrome/browser/download/thumbnail_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "jni/ThumbnailGenerator_jni.h"
 #include "ui/gfx/android/java_bitmap.h"
@@ -15,6 +17,30 @@
 class SkBitmap;
 
 using base::android::JavaParamRef;
+using base::android::ScopedJavaGlobalRef;
+
+namespace {
+
+void ForwardJavaCallback(const ScopedJavaGlobalRef<jobject>& java_delegate,
+                         const ScopedJavaGlobalRef<jstring>& content_id,
+                         int icon_size,
+                         const ScopedJavaGlobalRef<jobject>& callback,
+                         SkBitmap thumbnail) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_ThumbnailGenerator_onThumbnailRetrieved(
+      env, java_delegate, content_id, icon_size,
+      thumbnail.drawsNothing() ? NULL : gfx::ConvertToJavaBitmap(&thumbnail),
+      callback);
+}
+
+void OnThumbnailScaled(base::OnceCallback<void(SkBitmap)> java_callback,
+                       SkBitmap scaled_thumbnail) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  std::move(java_callback).Run(std::move(scaled_thumbnail));
+}
+
+}  // namespace
 
 ThumbnailGenerator::ThumbnailGenerator(const JavaParamRef<jobject>& jobj)
     : java_delegate_(jobj), weak_factory_(this) {
@@ -29,19 +55,27 @@
   delete this;
 }
 
-void ThumbnailGenerator::OnThumbnailRetrieved(
-    const base::android::ScopedJavaGlobalRef<jstring>& content_id,
-    int icon_size,
-    const base::android::ScopedJavaGlobalRef<jobject>& callback,
+void ThumbnailGenerator::OnImageThumbnailRetrieved(
+    base::OnceCallback<void(SkBitmap)> java_callback,
     const SkBitmap& thumbnail) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Send the bitmap back to Java-land.
-  JNIEnv* env = base::android::AttachCurrentThread();
-  Java_ThumbnailGenerator_onThumbnailRetrieved(
-      env, java_delegate_, content_id, icon_size,
-      thumbnail.drawsNothing() ? NULL : gfx::ConvertToJavaBitmap(&thumbnail),
-      callback);
+  std::move(java_callback).Run(std::move(thumbnail));
+}
+
+void ThumbnailGenerator::OnVideoThumbnailRetrieved(
+    base::OnceCallback<void(SkBitmap)> java_callback,
+    int icon_size,
+    std::unique_ptr<DownloadMediaParser> parser,
+    bool success,
+    chrome::mojom::MediaMetadataPtr media_metadata,
+    SkBitmap thumbnail) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // Scale the bitmap before sending back to Java.
+  ScaleDownBitmap(icon_size, std::move(thumbnail),
+                  base::BindOnce(&OnThumbnailScaled, std::move(java_callback)));
 }
 
 void ThumbnailGenerator::RetrieveThumbnail(
@@ -49,20 +83,42 @@
     const JavaParamRef<jobject>& jobj,
     const JavaParamRef<jstring>& jcontent_id,
     const JavaParamRef<jstring>& jfile_path,
+    const JavaParamRef<jstring>& jmime_type,
     jint icon_size,
     const JavaParamRef<jobject>& callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  std::string file_path =
-      base::android::ConvertJavaStringToUTF8(env, jfile_path);
+  base::FilePath file_path = base::FilePath::FromUTF8Unsafe(
+      base::android::ConvertJavaStringToUTF8(env, jfile_path));
 
+  std::string mime_type =
+      jmime_type.is_null()
+          ? ""
+          : base::android::ConvertJavaStringToUTF8(env, jmime_type);
+
+  // Bind everything passed back to Java.
+  auto java_callback =
+      base::BindOnce(&ForwardJavaCallback, java_delegate_,
+                     ScopedJavaGlobalRef<jstring>(jcontent_id), icon_size,
+                     ScopedJavaGlobalRef<jobject>(callback));
+
+  // Retrieve video thumbnail.
+  if (base::StartsWith(mime_type, "video/",
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+    auto parser = std::make_unique<DownloadMediaParser>(mime_type, file_path);
+    parser->Start(base::BindOnce(&ThumbnailGenerator::OnVideoThumbnailRetrieved,
+                                 weak_factory_.GetWeakPtr(),
+                                 std::move(java_callback), icon_size,
+                                 std::move(parser)));
+    return;
+  }
+
+  // Retrieve image thumbnail.
   auto request = std::make_unique<ImageThumbnailRequest>(
       icon_size,
-      base::BindOnce(
-          &ThumbnailGenerator::OnThumbnailRetrieved, weak_factory_.GetWeakPtr(),
-          base::android::ScopedJavaGlobalRef<jstring>(jcontent_id), icon_size,
-          base::android::ScopedJavaGlobalRef<jobject>(callback)));
-  request->Start(base::FilePath::FromUTF8Unsafe(file_path));
+      base::BindOnce(&ThumbnailGenerator::OnImageThumbnailRetrieved,
+                     weak_factory_.GetWeakPtr(), std::move(java_callback)));
+  request->Start(file_path);
 
   // Dropping ownership of |request| here because it will clean itself up once
   // the started request finishes.
diff --git a/chrome/browser/android/widget/thumbnail_generator.h b/chrome/browser/android/widget/thumbnail_generator.h
index 0b5cd00..add0647 100644
--- a/chrome/browser/android/widget/thumbnail_generator.h
+++ b/chrome/browser/android/widget/thumbnail_generator.h
@@ -5,11 +5,15 @@
 #ifndef CHROME_BROWSER_ANDROID_WIDGET_THUMBNAIL_GENERATOR_H_
 #define CHROME_BROWSER_ANDROID_WIDGET_THUMBNAIL_GENERATOR_H_
 
+#include <memory>
 #include <string>
 
 #include "base/android/jni_android.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/download/image_thumbnail_request.h"
+#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h"
+
+class DownloadMediaParser;
 
 // Kicks off asynchronous pipelines for creating thumbnails for local files.
 // The native-side ThumbnailGenerator is owned by the Java-side and can be
@@ -31,19 +35,29 @@
       const base::android::JavaParamRef<jobject>& jobj,
       const base::android::JavaParamRef<jstring>& jcontent_id,
       const base::android::JavaParamRef<jstring>& jfile_path,
+      const base::android::JavaParamRef<jstring>& jmime_type,
       jint icon_size,
       const base::android::JavaParamRef<jobject>& callback);
 
  private:
   ~ThumbnailGenerator();
 
-  // Called when the thumbnail is ready.  |thumbnail| will be empty on failure.
-  void OnThumbnailRetrieved(
-      const base::android::ScopedJavaGlobalRef<jstring>& content_id,
-      int icon_size,
-      const base::android::ScopedJavaGlobalRef<jobject>& callback,
+  // Called when the image thumbnail is ready.  |thumbnail| will be empty on
+  // failure.
+  void OnImageThumbnailRetrieved(
+      base::OnceCallback<void(SkBitmap)> java_callback,
       const SkBitmap& thumbnail);
 
+  // Called when the video thumbnail is ready.  |thumbnail| will be empty on
+  // failure.
+  void OnVideoThumbnailRetrieved(
+      base::OnceCallback<void(SkBitmap)> java_callback,
+      int icon_size,
+      std::unique_ptr<DownloadMediaParser> parser,
+      bool success,
+      chrome::mojom::MediaMetadataPtr media_metadata,
+      SkBitmap thumbnail);
+
   // This is a {@link ThumbnailGenerator} Java object.
   base::android::ScopedJavaGlobalRef<jobject> java_delegate_;
   base::WeakPtrFactory<ThumbnailGenerator> weak_factory_;
diff --git a/chrome/browser/autofill/autofill_profile_validator_factory.cc b/chrome/browser/autofill/autofill_profile_validator_factory.cc
new file mode 100644
index 0000000..7ff68c5
--- /dev/null
+++ b/chrome/browser/autofill/autofill_profile_validator_factory.cc
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill/autofill_profile_validator_factory.h"
+
+#include <memory>
+
+#include "chrome/browser/autofill/validation_rules_storage_factory.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
+#include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
+
+namespace autofill {
+
+// static
+AutofillProfileValidator* AutofillProfileValidatorFactory::GetInstance() {
+  static base::LazyInstance<AutofillProfileValidatorFactory>::DestructorAtExit
+      instance = LAZY_INSTANCE_INITIALIZER;
+  return &(instance.Get().autofill_profile_validator_);
+}
+
+AutofillProfileValidatorFactory::AutofillProfileValidatorFactory()
+    : autofill_profile_validator_(
+          std::make_unique<ChromeMetadataSource>(
+              I18N_ADDRESS_VALIDATION_DATA_URL,
+              g_browser_process->system_network_context_manager()
+                  ? g_browser_process->system_network_context_manager()
+                        ->GetSharedURLLoaderFactory()
+                  : nullptr),
+          ValidationRulesStorageFactory::CreateStorage()) {}
+
+AutofillProfileValidatorFactory::~AutofillProfileValidatorFactory() {}
+
+}  // namespace autofill
diff --git a/chrome/browser/autofill/autofill_profile_validator_factory.h b/chrome/browser/autofill/autofill_profile_validator_factory.h
new file mode 100644
index 0000000..85d14134
--- /dev/null
+++ b/chrome/browser/autofill/autofill_profile_validator_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
+#define CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "components/autofill/core/browser/autofill_profile_validator.h"
+
+namespace autofill {
+
+// Singleton that owns a single AutofillProfileValidator instance.
+class AutofillProfileValidatorFactory {
+ public:
+  static AutofillProfileValidator* GetInstance();
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<AutofillProfileValidatorFactory>;
+
+  AutofillProfileValidatorFactory();
+  ~AutofillProfileValidatorFactory();
+
+  // The only instance that exists.
+  AutofillProfileValidator autofill_profile_validator_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidatorFactory);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
diff --git a/chrome/browser/autofill/personal_data_manager_factory.cc b/chrome/browser/autofill/personal_data_manager_factory.cc
index 1d8816d..8d87dbc 100644
--- a/chrome/browser/autofill/personal_data_manager_factory.cc
+++ b/chrome/browser/autofill/personal_data_manager_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/autofill/autofill_profile_validator_factory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
@@ -51,6 +52,7 @@
       profile, ServiceAccessType::EXPLICIT_ACCESS);
   service->Init(local_storage, account_storage, profile->GetPrefs(),
                 IdentityManagerFactory::GetForProfile(profile),
+                AutofillProfileValidatorFactory::GetInstance(),
                 profile->IsOffTheRecord());
   return service;
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index b915c89..b038d1b 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1604,22 +1604,6 @@
 #endif
 }
 
-bool ChromeContentBrowserClient::
-    ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-        const GURL& url,
-        content::SiteInstance* parent_site_instance) {
-  if (IsNTPSiteInstance(parent_site_instance))
-    return true;
-
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-  return ChromeContentBrowserClientExtensionsPart::
-      ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-          url, parent_site_instance);
-#else
-  return false;
-#endif
-}
-
 bool ChromeContentBrowserClient::ShouldStayInParentProcessForNTP(
     const GURL& url,
     SiteInstance* parent_site_instance) {
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 66d96ca..c229f00 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -146,9 +146,6 @@
                                 ui::PageTransition* transition,
                                 bool* is_renderer_initiated,
                                 content::Referrer* referrer) override;
-  bool ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-      const GURL& url,
-      content::SiteInstance* parent_site_instance) override;
   bool ShouldStayInParentProcessForNTP(
       const GURL& url,
       content::SiteInstance* parent_site_instance) override;
diff --git a/chrome/browser/chromeos/arc/OWNERS b/chrome/browser/chromeos/arc/OWNERS
index d7d81e7..1888633 100644
--- a/chrome/browser/chromeos/arc/OWNERS
+++ b/chrome/browser/chromeos/arc/OWNERS
@@ -1,4 +1,3 @@
 elijahtaylor@chromium.org
 hidehiko@chromium.org
-lhchavez@chromium.org
 yusukes@chromium.org
diff --git a/chrome/browser/chromeos/arc/app_shortcuts/OWNERS b/chrome/browser/chromeos/arc/app_shortcuts/OWNERS
new file mode 100644
index 0000000..eb939e5
--- /dev/null
+++ b/chrome/browser/chromeos/arc/app_shortcuts/OWNERS
@@ -0,0 +1 @@
+khmel@chromium.org
diff --git a/chrome/browser/chromeos/arc/extensions/OWNERS b/chrome/browser/chromeos/arc/extensions/OWNERS
new file mode 100644
index 0000000..198d182b
--- /dev/null
+++ b/chrome/browser/chromeos/arc/extensions/OWNERS
@@ -0,0 +1,2 @@
+khmel@chromium.org
+hidehiko@chromium.org
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index f29cc82..77907e18 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -748,8 +748,7 @@
   InputConnectionImpl* connection = service()->GetInputConnectionForTesting();
   ASSERT_NE(nullptr, connection);
   connection->CommitText(base::ASCIIToUTF16("text"), 0);
-  // It's called from both of FinishComposingText() and CommitText().
-  EXPECT_EQ(2, test_context_handler.commit_text_call_count());
+  EXPECT_EQ(1, test_context_handler.commit_text_call_count());
   // Trigger an observer method to trigger text input state updating.
   engine_handler->SetSurroundingText("", 0, 0, 0);
   EXPECT_EQ(1, bridge()->update_text_input_state_calls_count_);
@@ -763,9 +762,20 @@
   connection->FinishComposingText();
   EXPECT_EQ(1, test_context_handler.commit_text_call_count());
 
+  base::string16 text = base::ASCIIToUTF16("text");
   test_context_handler.Reset();
-  connection->SetComposingText(base::ASCIIToUTF16("text"), 0);
+  connection->SetComposingText(text, 0);
   EXPECT_EQ(1, test_context_handler.update_preedit_text_call_count());
+  EXPECT_EQ(
+      text,
+      test_context_handler.last_update_composition_arg().composition_text.text);
+  // Committing the composing text calls ClearComposition() and CommitText().
+  connection->CommitText(base::ASCIIToUTF16("text"), 0);
+  EXPECT_EQ(2, test_context_handler.update_preedit_text_call_count());
+  EXPECT_EQ(
+      base::ASCIIToUTF16(""),
+      test_context_handler.last_update_composition_arg().composition_text.text);
+  EXPECT_EQ(1, test_context_handler.commit_text_call_count());
 
   engine_handler->FocusOut();
 
diff --git a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
index 76803fe..b23a1741 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
@@ -76,10 +76,10 @@
                                      int new_cursor_pos) {
   StartStateUpdateTimer();
 
-  // Confirm the current composing text at first.
-  FinishComposingTextInternal();
-
   std::string error;
+  // Clear the current composing text at first.
+  if (!ime_engine_->ClearComposition(input_context_id_, &error))
+    LOG(ERROR) << "ClearComposition failed: error=\"" << error << "\"";
   if (!ime_engine_->CommitText(input_context_id_,
                                base::UTF16ToUTF8(text).c_str(), &error))
     LOG(ERROR) << "CommitText failed: error=\"" << error << "\"";
@@ -103,7 +103,15 @@
 
 void InputConnectionImpl::FinishComposingText() {
   StartStateUpdateTimer();
-  FinishComposingTextInternal();
+
+  std::string error;
+  if (!ime_engine_->CommitText(input_context_id_,
+                               base::UTF16ToUTF8(composing_text_).c_str(),
+                               &error)) {
+    LOG(ERROR) << "FinishComposingText: CommitText() failed, error=\"" << error
+               << "\"";
+  }
+  composing_text_.clear();
 }
 
 void InputConnectionImpl::SetComposingText(const base::string16& text,
@@ -142,15 +150,4 @@
                      true /* is_input_state_update_requested */));
 }
 
-void InputConnectionImpl::FinishComposingTextInternal() {
-  std::string error;
-  if (!ime_engine_->CommitText(input_context_id_,
-                               base::UTF16ToUTF8(composing_text_).c_str(),
-                               &error)) {
-    LOG(ERROR) << "FinishComposingText: CommitText() failed, error=\"" << error
-               << "\"";
-  }
-  composing_text_.clear();
-}
-
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.h b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.h
index 3952fd22..9804b37 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.h
+++ b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.h
@@ -49,7 +49,6 @@
   // update surely. Some implementations of TextInputClient are synchronous. If
   // starting timer is after API call, the timer won't be cancelled.
   void StartStateUpdateTimer();
-  void FinishComposingTextInternal();
 
   chromeos::InputMethodEngine* const ime_engine_;  // Not owned
   ArcInputMethodManagerBridge* const imm_bridge_;  // Not owned
diff --git a/chrome/browser/chromeos/arc/optin/OWNERS b/chrome/browser/chromeos/arc/optin/OWNERS
new file mode 100644
index 0000000..198d182b
--- /dev/null
+++ b/chrome/browser/chromeos/arc/optin/OWNERS
@@ -0,0 +1,2 @@
+khmel@chromium.org
+hidehiko@chromium.org
diff --git a/chrome/browser/chromeos/arc/tts/OWNERS b/chrome/browser/chromeos/arc/tts/OWNERS
new file mode 100644
index 0000000..9cfcb59
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tts/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/chromeos/arc/accessibility/OWNERS
diff --git a/chrome/browser/chromeos/arc/video/OWNERS b/chrome/browser/chromeos/arc/video/OWNERS
new file mode 100644
index 0000000..5d140d09
--- /dev/null
+++ b/chrome/browser/chromeos/arc/video/OWNERS
@@ -0,0 +1 @@
+file://components/arc/video_accelerator/OWNERS
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index 729d47f..934d955 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
@@ -17,6 +18,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chromeos/chromeos_paths.h"
 #include "extensions/common/constants.h"
@@ -40,12 +42,12 @@
     arc::kPlayStoreAppId,
     extension_misc::kFilesManagerAppId,
     extension_misc::kGmailAppId,
-    extension_misc::kCalendarAppId,
     extension_misc::kGoogleDocAppId,
     extension_misc::kGoogleSlidesAppId,
     extension_misc::kGoogleSheetsAppId,
+    extension_misc::kDriveHostedAppId,
     extension_misc::kGoogleKeepAppId,
-    extension_misc::kGooglePhotosAppId,
+    extension_misc::kCalendarAppId,
     extension_misc::kYoutubeAppId,
     arc::kPlayMoviesAppId,                   // Play Movies & TV ARC app
     extension_misc::kGooglePlayMoviesAppId,  // Play Movies & TV Chrome app
@@ -54,15 +56,22 @@
     arc::kPlayGamesAppId,
     arc::kPlayBooksAppId,                   // Play Books ARC app
     extension_misc::kGooglePlayBooksAppId,  // Play Books Chrome app
-    extension_misc::kGoogleMapsAppId,
-    extension_misc::kDriveHostedAppId,
+    app_list::kInternalAppIdCamera,
     extension_misc::kCameraAppId,
+    extension_misc::kGooglePhotosAppId,
+    app_list::kDefaultPageBreak1,  // First default page break
+    extension_misc::kGoogleMapsAppId,
+    app_list::kInternalAppIdSettings,
+    app_list::kInternalAppIdDiscover,
+    extension_misc::kGeniusAppId,
     extension_misc::kCalculatorAppId,
     extension_misc::kTextEditorAppId,
+    arc::kGoogleDuo,
+    arc::kLightRoom,
+    arc::kInfinitePainter,
     extension_misc::kGooglePlusAppId,
     extension_misc::kChromeRemoteDesktopAppId,
     extensions::kWebStoreAppId,
-    extension_misc::kGeniusAppId,
 };
 
 // Reads external ordinal json file and returned the parsed value. Returns NULL
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index 034b8d0..30845a3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -260,12 +260,13 @@
 
 // Calls a response callback on the UI thread.
 void GetFileMetadataRespondOnUIThread(
-    const storage::FileSystemOperation::GetMetadataCallback& callback,
+    storage::FileSystemOperation::GetMetadataCallback callback,
     base::File::Error result,
     const base::File::Info& file_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(callback, result, file_info));
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::UI},
+      base::BindOnce(std::move(callback), result, file_info));
 }
 
 }  // namespace
@@ -656,10 +657,11 @@
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const FileSystemURL& url,
     int fields,
-    const storage::FileSystemOperation::GetMetadataCallback& callback) {
+    storage::FileSystemOperation::GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   file_system_context->operation_runner()->GetMetadata(
-      url, fields, base::Bind(&GetFileMetadataRespondOnUIThread, callback));
+      url, fields,
+      base::BindOnce(&GetFileMetadataRespondOnUIThread, std::move(callback)));
 }
 
 // Checks if the available space of the |path| is enough for required |bytes|.
@@ -708,12 +710,12 @@
       file_manager::util::GetDownloadsMountPointName(GetProfile())) {
     return base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(&GetFileMetadataOnIOThread, file_system_context,
-                       source_url_,
-                       storage::FileSystemOperation::GET_METADATA_FIELD_SIZE,
-                       base::Bind(&FileManagerPrivateInternalStartCopyFunction::
-                                      RunAfterGetFileMetadata,
-                                  this)));
+        base::BindOnce(
+            &GetFileMetadataOnIOThread, file_system_context, source_url_,
+            storage::FileSystemOperation::GET_METADATA_FIELD_SIZE,
+            base::BindOnce(&FileManagerPrivateInternalStartCopyFunction::
+                               RunAfterGetFileMetadata,
+                           this)));
   }
 
   return base::PostTaskWithTraits(
diff --git a/chrome/browser/chromeos/file_manager/crostini_file_tasks.cc b/chrome/browser/chromeos/file_manager/crostini_file_tasks.cc
index c158170..afd4c8f 100644
--- a/chrome/browser/chromeos/file_manager/crostini_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/crostini_file_tasks.cc
@@ -76,7 +76,7 @@
                        kCrostiniAppActionID),
         registry_service->GetRegistration(app_ids[i])->Name(),
         extensions::api::file_manager_private::Verb::VERB_OPEN_WITH,
-        GeneratePNGDataUrl(icons[i].GetRepresentation(scale).sk_bitmap()),
+        GeneratePNGDataUrl(icons[i].GetRepresentation(scale).GetBitmap()),
         false /* is_default */, false /* is_generic */));
   }
 
diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.cc b/chrome/browser/chromeos/file_manager/fileapi_util.cc
index 1e151d6..a05a8ff 100644
--- a/chrome/browser/chromeos/file_manager/fileapi_util.cc
+++ b/chrome/browser/chromeos/file_manager/fileapi_util.cc
@@ -357,9 +357,10 @@
         storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
             storage::FileSystemOperation::GET_METADATA_FIELD_SIZE |
             storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
-        base::Bind(&ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
-                       OnGotMetadataOnIOThread,
-                   base::Unretained(this), base::Passed(&lifetime), it));
+        base::BindOnce(
+            &ConvertSelectedFileInfoListToFileChooserFileInfoListImpl::
+                OnGotMetadataOnIOThread,
+            base::Unretained(this), std::move(lifetime), it));
   }
 
   // Callback invoked after GetMetadata.
@@ -423,7 +424,7 @@
     storage::FileSystemOperationRunner::GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   file_system_context->operation_runner()->GetMetadata(internal_url, fields,
-                                                       callback);
+                                                       std::move(callback));
 }
 
 }  // namespace
@@ -577,7 +578,7 @@
 void CheckIfDirectoryExists(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const base::FilePath& directory_path,
-    const storage::FileSystemOperationRunner::StatusCallback& callback) {
+    storage::FileSystemOperationRunner::StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   storage::ExternalFileSystemBackend* const backend =
@@ -589,14 +590,15 @@
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&CheckIfDirectoryExistsOnIoThread, file_system_context,
-                     internal_url, google_apis::CreateRelayCallback(callback)));
+                     internal_url,
+                     google_apis::CreateRelayCallback(std::move(callback))));
 }
 
 void GetMetadataForPath(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const base::FilePath& entry_path,
     int fields,
-    const storage::FileSystemOperationRunner::GetMetadataCallback& callback) {
+    storage::FileSystemOperationRunner::GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   storage::ExternalFileSystemBackend* const backend =
@@ -609,7 +611,7 @@
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&GetMetadataForPathOnIoThread, file_system_context,
                      internal_url, fields,
-                     google_apis::CreateRelayCallback(callback)));
+                     google_apis::CreateRelayCallback(std::move(callback))));
 }
 
 storage::FileSystemURL CreateIsolatedURLFromVirtualPath(
diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.h b/chrome/browser/chromeos/file_manager/fileapi_util.h
index e1a8745..1bc9df2 100644
--- a/chrome/browser/chromeos/file_manager/fileapi_util.h
+++ b/chrome/browser/chromeos/file_manager/fileapi_util.h
@@ -161,14 +161,14 @@
 void CheckIfDirectoryExists(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const base::FilePath& directory_path,
-    const storage::FileSystemOperationRunner::StatusCallback& callback);
+    storage::FileSystemOperationRunner::StatusCallback callback);
 
 // Get metadata for an entry at |entry_path| absolute path.
 void GetMetadataForPath(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const base::FilePath& entry_path,
     int fields,
-    const storage::FileSystemOperationRunner::GetMetadataCallback& callback);
+    storage::FileSystemOperationRunner::GetMetadataCallback callback);
 
 // Obtains isolated file system URL from |virtual_path| pointing a file in the
 // external file system.
diff --git a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc
index 1d6d82e6..e809636 100644
--- a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc
+++ b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc
@@ -91,12 +91,12 @@
 void PrepareFileAfterCheckExistOnIOThread(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const storage::FileSystemURL& url,
-    const storage::FileSystemOperation::StatusCallback& callback,
+    storage::FileSystemOperation::StatusCallback callback,
     base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (error != base::File::FILE_ERROR_NOT_FOUND) {
-    callback.Run(error);
+    std::move(callback).Run(error);
     return;
   }
 
@@ -106,7 +106,8 @@
   //
   // Note that the preceding call to FileExists is necessary for handling
   // read only filesystems that blindly rejects handling CreateFile().
-  file_system_context->operation_runner()->CreateFile(url, false, callback);
+  file_system_context->operation_runner()->CreateFile(url, false,
+                                                      std::move(callback));
 }
 
 // Checks whether a file exists at the given |url|, and try creating it if it
@@ -118,10 +119,10 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   file_system_context->operation_runner()->FileExists(
-      url, base::Bind(&PrepareFileAfterCheckExistOnIOThread,
-                      file_system_context, url,
-                      base::Bind(&BoolCallbackAsFileErrorCallback,
-                                 base::Passed(std::move(callback)))));
+      url, base::BindOnce(&PrepareFileAfterCheckExistOnIOThread,
+                          std::move(file_system_context), url,
+                          base::BindOnce(&BoolCallbackAsFileErrorCallback,
+                                         std::move(callback))));
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/fileapi/recent_download_source.cc b/chrome/browser/chromeos/fileapi/recent_download_source.cc
index f41487d2..cdf8989 100644
--- a/chrome/browser/chromeos/fileapi/recent_download_source.cc
+++ b/chrome/browser/chromeos/fileapi/recent_download_source.cc
@@ -48,24 +48,25 @@
 }
 
 void OnGetMetadataOnIOThread(
-    const storage::FileSystemOperation::GetMetadataCallback& callback,
+    storage::FileSystemOperation::GetMetadataCallback callback,
     base::File::Error result,
     const base::File::Info& info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(callback, result, info));
+                           base::BindOnce(std::move(callback), result, info));
 }
 
 void GetMetadataOnIOThread(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const storage::FileSystemURL& url,
     int fields,
-    const storage::FileSystemOperation::GetMetadataCallback& callback) {
+    storage::FileSystemOperation::GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   file_system_context->operation_runner()->GetMetadata(
-      url, fields, base::Bind(&OnGetMetadataOnIOThread, callback));
+      url, fields,
+      base::BindOnce(&OnGetMetadataOnIOThread, std::move(callback)));
 }
 
 }  // namespace
@@ -138,8 +139,8 @@
               &GetMetadataOnIOThread,
               base::WrapRefCounted(params_.value().file_system_context()), url,
               storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
-              base::Bind(&RecentDownloadSource::OnGetMetadata,
-                         weak_ptr_factory_.GetWeakPtr(), url)));
+              base::BindOnce(&RecentDownloadSource::OnGetMetadata,
+                             weak_ptr_factory_.GetWeakPtr(), url)));
     }
   }
 
diff --git a/chrome/browser/chromeos/fileapi/recent_drive_source.cc b/chrome/browser/chromeos/fileapi/recent_drive_source.cc
index cff4f351..d1805f0 100644
--- a/chrome/browser/chromeos/fileapi/recent_drive_source.cc
+++ b/chrome/browser/chromeos/fileapi/recent_drive_source.cc
@@ -28,24 +28,25 @@
 namespace {
 
 void OnGetMetadataOnIOThread(
-    const storage::FileSystemOperation::GetMetadataCallback& callback,
+    storage::FileSystemOperation::GetMetadataCallback callback,
     base::File::Error result,
     const base::File::Info& info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(callback, result, info));
+                           base::BindOnce(std::move(callback), result, info));
 }
 
 void GetMetadataOnIOThread(
     scoped_refptr<storage::FileSystemContext> file_system_context,
     const storage::FileSystemURL& url,
     int fields,
-    const storage::FileSystemOperation::GetMetadataCallback& callback) {
+    storage::FileSystemOperation::GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   file_system_context->operation_runner()->GetMetadata(
-      url, fields, base::Bind(&OnGetMetadataOnIOThread, callback));
+      url, fields,
+      base::BindOnce(&OnGetMetadataOnIOThread, std::move(callback)));
 }
 
 }  // namespace
@@ -139,8 +140,8 @@
             &GetMetadataOnIOThread,
             base::WrapRefCounted(params_.value().file_system_context()), url,
             storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
-            base::Bind(&RecentDriveSource::OnGetMetadata,
-                       weak_ptr_factory_.GetWeakPtr(), url)));
+            base::BindOnce(&RecentDriveSource::OnGetMetadata,
+                           weak_ptr_factory_.GetWeakPtr(), url)));
   }
 
   if (num_inflight_stats_ == 0)
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
index 267fd4a3..7d6d362 100644
--- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -232,7 +232,7 @@
       ADD_FAILURE() << "No image representation.";
       average_color_ = SkColorSetARGB(0, 0, 0, 0);
     }
-    average_color_ = ComputeAverageColor(representation.sk_bitmap());
+    average_color_ = ComputeAverageColor(representation.GetBitmap());
     if (run_loop_)
       run_loop_->Quit();
   }
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h
index aaa87d2..5c0c293 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.h
+++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -12,7 +12,6 @@
 #include "components/viz/host/client_frame_sink_video_capturer.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "media/renderers/paint_canvas_video_renderer.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 namespace blink {
@@ -59,7 +58,6 @@
   content::RenderWidgetHost::MouseEventCallback mouse_event_callback_;
   content::RenderWidgetHost* host_;
   std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
-  media::PaintCanvasVideoRenderer video_renderer_;
   base::WeakPtrFactory<DevToolsEyeDropper> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DevToolsEyeDropper);
diff --git a/chrome/browser/download/image_thumbnail_request.cc b/chrome/browser/download/image_thumbnail_request.cc
index ffb8ef5..417c4d7 100644
--- a/chrome/browser/download/image_thumbnail_request.cc
+++ b/chrome/browser/download/image_thumbnail_request.cc
@@ -9,6 +9,7 @@
 #include "base/files/file_util.h"
 #include "base/task/post_task.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "chrome/browser/download/thumbnail_util.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "skia/ext/image_operations.h"
@@ -41,26 +42,6 @@
   return data;
 }
 
-SkBitmap ScaleDownBitmap(int icon_size, const SkBitmap& decoded_image) {
-  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  if (decoded_image.drawsNothing())
-    return decoded_image;
-
-  // Shrink the image down so that its smallest dimension is equal to or
-  // smaller than the requested size.
-  int min_dimension = std::min(decoded_image.width(), decoded_image.height());
-
-  if (min_dimension <= icon_size)
-    return decoded_image;
-
-  uint64_t width = static_cast<uint64_t>(decoded_image.width());
-  uint64_t height = static_cast<uint64_t>(decoded_image.height());
-  return skia::ImageOperations::Resize(
-      decoded_image, skia::ImageOperations::RESIZE_BEST,
-      width * icon_size / min_dimension, height * icon_size / min_dimension);
-}
-
 }  // namespace
 
 ImageThumbnailRequest::ImageThumbnailRequest(
@@ -87,11 +68,9 @@
 
 void ImageThumbnailRequest::OnImageDecoded(const SkBitmap& decoded_image) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
-      base::BindOnce(&ScaleDownBitmap, icon_size_, decoded_image),
-      base::BindOnce(&ImageThumbnailRequest::FinishRequest,
-                     weak_ptr_factory_.GetWeakPtr()));
+  ScaleDownBitmap(icon_size_, decoded_image,
+                  base::BindOnce(&ImageThumbnailRequest::FinishRequest,
+                                 weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ImageThumbnailRequest::OnDecodeImageFailed() {
@@ -110,9 +89,10 @@
   ImageDecoder::Start(this, data);
 }
 
-void ImageThumbnailRequest::FinishRequest(const SkBitmap& thumbnail) {
+void ImageThumbnailRequest::FinishRequest(SkBitmap thumbnail) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(std::move(callback_), thumbnail));
+  base::PostTaskWithTraits(
+      FROM_HERE, {content::BrowserThread::UI},
+      base::BindOnce(std::move(callback_), std::move(thumbnail)));
   delete this;
 }
diff --git a/chrome/browser/download/image_thumbnail_request.h b/chrome/browser/download/image_thumbnail_request.h
index ef95f53d..7febd12 100644
--- a/chrome/browser/download/image_thumbnail_request.h
+++ b/chrome/browser/download/image_thumbnail_request.h
@@ -33,7 +33,7 @@
 
   void OnLoadComplete(const std::string& data);
 
-  void FinishRequest(const SkBitmap& thumbnail);
+  void FinishRequest(SkBitmap thumbnail);
 
   const int icon_size_;
   base::OnceCallback<void(const SkBitmap&)> callback_;
diff --git a/chrome/browser/download/thumbnail_util.cc b/chrome/browser/download/thumbnail_util.cc
new file mode 100644
index 0000000..21d7ba0
--- /dev/null
+++ b/chrome/browser/download/thumbnail_util.cc
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/download/thumbnail_util.h"
+
+#include "base/logging.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_thread.h"
+#include "skia/ext/image_operations.h"
+
+namespace {
+
+SkBitmap ScaleDownBitmapOnIOThread(int icon_size, SkBitmap bitmap) {
+  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  if (bitmap.drawsNothing())
+    return bitmap;
+
+  // Shrink the image down so that its smallest dimension is equal to or
+  // smaller than the requested size.
+  int min_dimension = std::min(bitmap.width(), bitmap.height());
+
+  if (min_dimension <= icon_size)
+    return bitmap;
+
+  uint64_t width = static_cast<uint64_t>(bitmap.width());
+  uint64_t height = static_cast<uint64_t>(bitmap.height());
+  return skia::ImageOperations::Resize(
+      bitmap, skia::ImageOperations::RESIZE_BEST,
+      width * icon_size / min_dimension, height * icon_size / min_dimension);
+}
+
+}  // namespace
+
+void ScaleDownBitmap(int icon_size,
+                     const SkBitmap& bitmap,
+                     base::OnceCallback<void(SkBitmap)> callback) {
+  DCHECK(callback);
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  // Scale down bitmap on another thread.
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+      base::BindOnce(&ScaleDownBitmapOnIOThread, icon_size, std::move(bitmap)),
+      std::move(callback));
+}
diff --git a/chrome/browser/download/thumbnail_util.h b/chrome/browser/download/thumbnail_util.h
new file mode 100644
index 0000000..a337651
--- /dev/null
+++ b/chrome/browser/download/thumbnail_util.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOWNLOAD_THUMBNAIL_UTIL_H_
+#define CHROME_BROWSER_DOWNLOAD_THUMBNAIL_UTIL_H_
+
+#include "base/callback.h"
+
+class SkBitmap;
+
+// Scale down the bitmap. The result is returned in the |callback|. The aspect
+// ratio is kept. The maximum size of the width or height will be no greater
+// than |icon_size|.
+void ScaleDownBitmap(int icon_size,
+                     const SkBitmap& bitmap,
+                     base::OnceCallback<void(SkBitmap)> callback);
+
+#endif  // CHROME_BROWSER_DOWNLOAD_THUMBNAIL_UTIL_H_
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 9ad91ec..bb3604b 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -341,8 +341,10 @@
 void DownloadFileIconExtractorImpl::OnIconLoadComplete(
     float scale, const IconURLCallback& callback, gfx::Image* icon) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  callback.Run(!icon ? std::string() : webui::GetBitmapDataUrl(
-      icon->ToImageSkia()->GetRepresentation(scale).sk_bitmap()));
+  callback.Run(
+      !icon ? std::string()
+            : webui::GetBitmapDataUrl(
+                  icon->ToImageSkia()->GetRepresentation(scale).GetBitmap()));
 }
 
 IconLoader::IconSize IconLoaderSizeFromPixelSize(int pixel_size) {
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index e96645d..aa5dd63e 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -103,11 +103,11 @@
   icon_portion.ClampToCenteredSize(model_icon.Size());
 
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
-      model_icon.AsImageSkia().GetRepresentation(1.0f).sk_bitmap(),
+      model_icon.AsImageSkia().GetRepresentation(1.0f).GetBitmap(),
       gfx::ImageSkiaOperations::ExtractSubset(bar_rendering.AsImageSkia(),
                                               icon_portion)
           .GetRepresentation(1.0f)
-          .sk_bitmap()));
+          .GetBitmap()));
 }
 
 class BrowserActionApiTest : public ExtensionApiTest {
diff --git a/chrome/browser/extensions/chrome_app_icon_unittest.cc b/chrome/browser/extensions/chrome_app_icon_unittest.cc
index 5f665e09..692109c 100644
--- a/chrome/browser/extensions/chrome_app_icon_unittest.cc
+++ b/chrome/browser/extensions/chrome_app_icon_unittest.cc
@@ -162,8 +162,8 @@
   for (size_t i = 0; i < image1_reps.size(); ++i) {
     const float scale = image1_reps[i].scale();
     const gfx::ImageSkiaRep& image_rep2 = image2.GetRepresentation(scale);
-    if (gfx::test::AreBitmapsClose(image1_reps[i].sk_bitmap(),
-                                   image_rep2.sk_bitmap(), 0)) {
+    if (gfx::test::AreBitmapsClose(image1_reps[i].GetBitmap(),
+                                   image_rep2.GetBitmap(), 0)) {
       return false;
     }
   }
diff --git a/chrome/browser/extensions/chrome_app_sorting.cc b/chrome/browser/extensions/chrome_app_sorting.cc
index b4adf2e..c44410e 100644
--- a/chrome/browser/extensions/chrome_app_sorting.cc
+++ b/chrome/browser/extensions/chrome_app_sorting.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_sync_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension_constants.h"
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -23,6 +24,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/extensions/default_app_order.h"
+#include "chrome/browser/ui/app_list/page_break_constants.h"
 #endif
 
 namespace extensions {
@@ -583,6 +585,15 @@
     default_ordinals_[extension_id].page_ordinal = page_ordinal;
     default_ordinals_[extension_id].app_launch_ordinal = app_launch_ordinal;
     app_launch_ordinal = app_launch_ordinal.CreateAfter();
+#if defined(OS_CHROMEOS)
+    // Default page breaks are installed by default for first-time users so that
+    // we can make default apps span multiple pages in the Launcher without
+    // fully filling those pages. If |extension_id| is of a default page break,
+    // then apps that follow it in the order should have an incremented page
+    // ordinal.
+    if (app_list::IsDefaultPageBreakItem(extension_id))
+      page_ordinal = page_ordinal.CreateAfter();
+#endif  // defined(OS_CHROMEOS)
   }
 }
 
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
index 5a83c55..a9380ce 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -807,19 +807,6 @@
 }
 
 // static
-bool ChromeContentBrowserClientExtensionsPart::
-    ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-        const GURL& subframe_url,
-        content::SiteInstance* parent_site_instance) {
-  const Extension* extension =
-      ExtensionRegistry::Get(parent_site_instance->GetBrowserContext())
-          ->enabled_extensions()
-          .GetExtensionOrAppByURL(parent_site_instance->GetSiteURL());
-
-  return extension && extension->is_hosted_app();
-}
-
-// static
 void ChromeContentBrowserClientExtensionsPart::
     LogInitiatorSchemeBypassingDocumentBlocking(
         const url::Origin& initiator_origin,
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
index d5ed7944..2f0a8c84 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
@@ -84,10 +84,6 @@
   static std::unique_ptr<content::VpnServiceProxy> GetVpnServiceProxy(
       content::BrowserContext* browser_context);
 
-  static bool ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-      const GURL& url,
-      content::SiteInstance* parent_site_instance);
-
   static void LogInitiatorSchemeBypassingDocumentBlocking(
       const url::Origin& initiator_origin,
       int render_process_id,
diff --git a/chrome/browser/extensions/extension_action.cc b/chrome/browser/extensions/extension_action.cc
index a8ad0a9..4c05554 100644
--- a/chrome/browser/extensions/extension_action.cc
+++ b/chrome/browser/extensions/extension_action.cc
@@ -48,7 +48,7 @@
     gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale);
     color_utils::HSL shift = {-1, 0, 0.5};
     return gfx::ImageSkiaRep(
-        SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift),
+        SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.GetBitmap(), shift),
         icon_rep.scale());
   }
 
diff --git a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
index 9262301..875d344 100644
--- a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
+++ b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
@@ -42,7 +42,7 @@
 bool ImageRepsAreEqual(const gfx::ImageSkiaRep& image_rep1,
                        const gfx::ImageSkiaRep& image_rep2) {
   return image_rep1.scale() == image_rep2.scale() &&
-         gfx::BitmapsAreEqual(image_rep1.sk_bitmap(), image_rep2.sk_bitmap());
+         gfx::BitmapsAreEqual(image_rep1.GetBitmap(), image_rep2.GetBitmap());
 }
 
 gfx::Image EnsureImageSize(const gfx::Image& original, int size) {
diff --git a/chrome/browser/extensions/extension_action_storage_manager.cc b/chrome/browser/extensions/extension_action_storage_manager.cc
index 6a3b028..2842143 100644
--- a/chrome/browser/extensions/extension_action_storage_manager.cc
+++ b/chrome/browser/extensions/extension_action_storage_manager.cc
@@ -185,7 +185,7 @@
     for (const gfx::ImageSkiaRep& rep : image_reps) {
       int size = static_cast<int>(rep.scale() * icon.width());
       std::string size_string = base::IntToString(size);
-      icon_value->SetString(size_string, BitmapToString(rep.sk_bitmap()));
+      icon_value->SetString(size_string, BitmapToString(rep.GetBitmap()));
     }
     dict->Set(kIconStorageKey, std::move(icon_value));
   }
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index e30137f..2f7ef04 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -64,8 +64,8 @@
   const gfx::ImageSkia& image = is_app ?
       extensions::util::GetDefaultAppIcon() :
       extensions::util::GetDefaultExtensionIcon();
-  return image.GetRepresentation(
-      gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
+  return image.GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale())
+      .GetBitmap();
 }
 
 // If auto confirm is enabled then posts a task to proceed with or cancel the
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index 88e16d59..48520165 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -265,8 +265,7 @@
     const gfx::ImageSkiaRep& image_rep = image_reps[i];
     scoped_refptr<base::RefCountedBytes> bitmap_data(
         new base::RefCountedBytes());
-    if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.sk_bitmap(),
-                                          false,
+    if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.GetBitmap(), false,
                                           &bitmap_data->data())) {
       favicon_base::FaviconRawBitmapResult bitmap_result;
       bitmap_result.bitmap_data = bitmap_data;
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 5d8265c9..4f03dcf 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -297,6 +297,47 @@
   EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
 }
 
+// Tests chrome.runtime.onInstalled fires for extension service workers.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, OnInstalledEvent) {
+  ASSERT_TRUE(RunExtensionTest(
+      "service_worker/worker_based_background/events_on_installed"))
+      << message_;
+}
+
+// Listens for "runtime.onStartup" event early so that tests can wait for the
+// event on startup (and not miss it).
+class ServiceWorkerOnStartupTest : public ServiceWorkerBasedBackgroundTest {
+ public:
+  ServiceWorkerOnStartupTest() = default;
+  ~ServiceWorkerOnStartupTest() override = default;
+
+  bool WaitForOnStartupEvent() { return listener_->WaitUntilSatisfied(); }
+
+  void CreatedBrowserMainParts(content::BrowserMainParts* main_parts) override {
+    // At this point, the notification service is initialized but the profile
+    // and extensions have not.
+    listener_ = std::make_unique<ExtensionTestMessageListener>(
+        "onStartup event", false);
+    ServiceWorkerBasedBackgroundTest::CreatedBrowserMainParts(main_parts);
+  }
+
+ private:
+  std::unique_ptr<ExtensionTestMessageListener> listener_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerOnStartupTest);
+};
+
+// Tests "runtime.onStartup" for extension SW.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerOnStartupTest, PRE_Event) {
+  ASSERT_TRUE(RunExtensionTest(
+      "service_worker/worker_based_background/on_startup_event"))
+      << message_;
+}
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerOnStartupTest, Event) {
+  EXPECT_TRUE(WaitForOnStartupEvent());
+}
+
 // Class that dispatches an event to |extension_id| right after a
 // non-lazy listener to the event is added from the extension's Service Worker.
 class EarlyWorkerMessageSender : public EventRouter::Observer {
@@ -1411,5 +1452,11 @@
 INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
                         ServiceWorkerBasedBackgroundTest,
                         ::testing::Values(JAVASCRIPT_BINDINGS));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithNativeBindings,
+                        ServiceWorkerOnStartupTest,
+                        ::testing::Values(NATIVE_BINDINGS));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerTestWithJSBindings,
+                        ServiceWorkerOnStartupTest,
+                        ::testing::Values(JAVASCRIPT_BINDINGS));
 
 }  // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 0b6ae8f..62a8ec84 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1859,12 +1859,6 @@
 const char kTLS13VariantDraft23[] = "Enabled (Draft 23)";
 const char kTLS13VariantFinal[] = "Enabled (Final)";
 
-const char kTopDocumentIsolationName[] = "Top document isolation";
-const char kTopDocumentIsolationDescription[] =
-    "Highly experimental performance mode where cross-site iframes are kept in "
-    "a separate process from the top document. In this mode, iframes from "
-    "different third-party sites will be allowed to share a process.";
-
 const char kTopSitesFromSiteEngagementName[] = "Top Sites from Site Engagement";
 const char kTopSitesFromSiteEngagementDescription[] =
     "Enable Top Sites on the New Tab Page to be sourced and sorted using site "
@@ -3586,6 +3580,12 @@
     "Windows 10 or later).";
 #endif  // ENABLE_OPENVR
 
+#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE)
+const char kXRSandboxName[] = "XR device sandboxing";
+const char kXRSandboxDescription[] =
+    "If enabled, Chrome will host VR APIs in a restricted process on desktop.";
+#endif  // ENABLE_ISOLATED_XR_SERVICE
+
 #endif  // ENABLE_VR
 
 #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 1ee435a..93245c4a 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1127,9 +1127,6 @@
 extern const char kThreadedScrollingName[];
 extern const char kThreadedScrollingDescription[];
 
-extern const char kTopDocumentIsolationName[];
-extern const char kTopDocumentIsolationDescription[];
-
 extern const char kTopSitesFromSiteEngagementName[];
 extern const char kTopSitesFromSiteEngagementDescription[];
 
@@ -2193,6 +2190,11 @@
 extern const char kOpenVRDescription[];
 #endif  // ENABLE_OPENVR
 
+#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE)
+extern const char kXRSandboxName[];
+extern const char kXRSandboxDescription[];
+#endif  // ENABLE_ISOLATED_XR_SERVICE
+
 #endif  // ENABLE_VR
 
 #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/media/android/cdm/media_drm_credential_manager.cc b/chrome/browser/media/android/cdm/media_drm_credential_manager.cc
index 656ae710..eb922ea 100644
--- a/chrome/browser/media/android/cdm/media_drm_credential_manager.cc
+++ b/chrome/browser/media/android/cdm/media_drm_credential_manager.cc
@@ -21,8 +21,6 @@
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 #include "url/gurl.h"
 
-#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
-
 using base::android::JavaParamRef;
 using base::android::ScopedJavaGlobalRef;
 
diff --git a/chrome/browser/media/android/cdm/media_drm_license_manager.cc b/chrome/browser/media/android/cdm/media_drm_license_manager.cc
index 37cdc1a..3d16a50 100644
--- a/chrome/browser/media/android/cdm/media_drm_license_manager.cc
+++ b/chrome/browser/media/android/cdm/media_drm_license_manager.cc
@@ -15,8 +15,6 @@
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 #include "url/origin.h"
 
-#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
-
 namespace {
 // Unprovision MediaDrm in IO thread.
 void ClearMediaDrmLicensesBlocking(
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index c2bb7321..9e4abd92 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -518,12 +518,12 @@
                                 Values(SrcType::SRC)));
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
-#if BUILDFLAG(SHOULD_BUNDLE_WIDEVINE_CDM)
+#if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
 INSTANTIATE_TEST_CASE_P(MSE_Widevine,
                         EncryptedMediaTest,
                         Combine(Values(kWidevineKeySystem),
                                 Values(SrcType::MSE)));
-#endif  // #if BUILDFLAG(SHOULD_BUNDLE_WIDEVINE_CDM)
+#endif  // #if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
   TestSimplePlayback("bear-320x240-av_enc-a.webm", kWebMVorbisAudioVp8Video);
diff --git a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
index e6e2f9a..8676ad9e 100644
--- a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
@@ -82,13 +82,13 @@
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
 // Expectations for Widevine.
-#if BUILDFLAG(SHOULD_BUNDLE_WIDEVINE_CDM)
+#if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
 #define EXPECT_WV_SUCCESS EXPECT_SUCCESS
 #define EXPECT_WV_PROPRIETARY EXPECT_PROPRIETARY
 #else
 #define EXPECT_WV_SUCCESS EXPECT_UNSUPPORTED
 #define EXPECT_WV_PROPRIETARY EXPECT_UNSUPPORTED
-#endif  // BUILDFLAG(SHOULD_BUNDLE_WIDEVINE_CDM)
+#endif  // BUILDFLAG(BUNDLE_WIDEVINE_CDM)
 
 };  // namespace
 
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
index 38819a3..5f864e1 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
@@ -18,6 +18,7 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "components/previews/content/previews_content_util.h"
+#include "components/previews/core/previews_experiments.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/previews_state.h"
@@ -129,7 +130,7 @@
   if (resource_loading_hints_seen_)
     builder.Setresource_loading_hints(1);
   if (opt_out_occurred_)
-    builder.Setopt_out(1);
+    builder.Setopt_out(previews::params::IsPreviewsOmniboxUiEnabled() ? 2 : 1);
   if (origin_opt_out_occurred_)
     builder.Setorigin_opt_out(1);
   if (save_data_enabled_)
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
index f592cbf..12edbd9 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/optional.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/loader/chrome_navigation_data.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
@@ -17,6 +18,7 @@
 #include "chrome/browser/previews/previews_infobar_delegate.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
+#include "components/previews/core/previews_features.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "content/public/common/previews_state.h"
 #include "content/public/test/web_contents_tester.h"
@@ -157,14 +159,14 @@
                    bool lite_page_expected,
                    bool noscript_expected,
                    bool resource_loading_hints_expected,
-                   bool opt_out_expected,
+                   int opt_out_value,
                    bool origin_opt_out_expected,
                    bool save_data_enabled_expected) {
     using UkmEntry = ukm::builders::Previews;
     auto entries = test_ukm_recorder().GetEntriesByName(UkmEntry::kEntryName);
     if (!server_lofi_expected && !client_lofi_expected && !lite_page_expected &&
         !noscript_expected && !resource_loading_hints_expected &&
-        !opt_out_expected && !origin_opt_out_expected &&
+        opt_out_value == 0 && !origin_opt_out_expected &&
         !save_data_enabled_expected) {
       EXPECT_EQ(0u, entries.size());
       return;
@@ -183,8 +185,12 @@
       EXPECT_EQ(resource_loading_hints_expected,
                 test_ukm_recorder().EntryHasMetric(
                     entry, UkmEntry::kresource_loading_hintsName));
-      EXPECT_EQ(opt_out_expected, test_ukm_recorder().EntryHasMetric(
-                                      entry, UkmEntry::kopt_outName));
+      EXPECT_EQ(opt_out_value != 0, test_ukm_recorder().EntryHasMetric(
+                                        entry, UkmEntry::kopt_outName));
+      if (opt_out_value != 0) {
+        test_ukm_recorder().ExpectEntryMetric(entry, UkmEntry::kopt_outName,
+                                              opt_out_value);
+      }
       EXPECT_EQ(origin_opt_out_expected,
                 test_ukm_recorder().EntryHasMetric(
                     entry, UkmEntry::korigin_opt_outName));
@@ -229,7 +235,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -246,7 +252,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -261,11 +267,17 @@
               false /* client_lofi_expected */, true /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, LitePageOptOut) {
+TEST_F(PreviewsUKMObserverTest, LitePageOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(true /* data_reduction_proxy_used */, true /* lite_page_received */,
           false /* noscript_on */, false /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -278,7 +290,29 @@
               false /* client_lofi_expected */, true /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              1 /* opt_out_value */, false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, LitePageOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(true /* data_reduction_proxy_used */, true /* lite_page_received */,
+          false /* noscript_on */, false /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+
+  ValidateUKM(false /* server_lofi_expected */,
+              false /* client_lofi_expected */, true /* lite_page_expected */,
+              false /* noscript_expected */,
+              false /* resource_loading_hints_expected */,
+              2 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -293,11 +327,17 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               true /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, NoScriptOptOut) {
+TEST_F(PreviewsUKMObserverTest, NoScriptOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
           true /* noscript_on */, false /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -310,7 +350,29 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               true /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              1 /* opt_out_value */, false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, NoScriptOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
+          true /* noscript_on */, false /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+
+  ValidateUKM(false /* server_lofi_expected */,
+              false /* client_lofi_expected */, false /* lite_page_expected */,
+              true /* noscript_expected */,
+              false /* resource_loading_hints_expected */,
+              2 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -324,12 +386,18 @@
   ValidateUKM(false /* server_lofi_expected */,
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
-              true /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              true /* resource_loading_hints_expected */, 0 /* opt_out_value */,
+              false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOut) {
+TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
           false /* noscript_on */, true /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -341,8 +409,30 @@
   ValidateUKM(false /* server_lofi_expected */,
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
-              true /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              true /* resource_loading_hints_expected */, 1 /* opt_out_value */,
+              false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, ResourceLoadingHintsOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
+          false /* noscript_on */, true /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+
+  ValidateUKM(false /* server_lofi_expected */,
+              false /* client_lofi_expected */, false /* lite_page_expected */,
+              false /* noscript_expected */,
+              true /* resource_loading_hints_expected */, 2 /* opt_out_value */,
+              false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -380,11 +470,17 @@
   ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, ClientLoFiOptOut) {
+TEST_F(PreviewsUKMObserverTest, ClientLoFiOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
           false /* noscript_on */, false /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -419,7 +515,51 @@
   ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              1 /* opt_out_value */, false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, ClientLoFiOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(false /* data_reduction_proxy_used */, false /* lite_page_received */,
+          false /* noscript_on */, false /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data =
+      std::make_unique<data_reduction_proxy::DataReductionProxyData>();
+  data->set_client_lofi_requested(true);
+
+  // Prepare 3 resources of varying size and configurations, 2 of which have
+  // client LoFi set.
+  page_load_metrics::ExtraRequestCompleteInfo resources[] = {
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 * 5 /* original_network_content_length */, std::move(data),
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+      // Uncached non-proxied request.
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */,
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+  };
+
+  for (const auto& request : resources)
+    SimulateLoadedResource(request);
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+
+  ValidateUKM(false /* server_lofi_expected */, true /* client_lofi_expected */,
+              false /* lite_page_expected */, false /* noscript_expected */,
+              false /* resource_loading_hints_expected */,
+              2 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -457,11 +597,17 @@
   ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, ServerLoFiOptOut) {
+TEST_F(PreviewsUKMObserverTest, ServerLoFiOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(true /* data_reduction_proxy_used */, false /* lite_page_received */,
           false /* noscript_on */, false /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -497,7 +643,52 @@
   ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              1 /* opt_out_value */, false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, ServerLoFiOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(true /* data_reduction_proxy_used */, false /* lite_page_received */,
+          false /* noscript_on */, false /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data =
+      std::make_unique<data_reduction_proxy::DataReductionProxyData>();
+  data->set_used_data_reduction_proxy(true);
+  data->set_lofi_received(true);
+
+  // Prepare 3 resources of varying size and configurations, 2 of which have
+  // client LoFi set.
+  page_load_metrics::ExtraRequestCompleteInfo resources[] = {
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 * 5 /* original_network_content_length */, std::move(data),
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 /* original_network_content_length */,
+       nullptr /* data_reduction_proxy_data */,
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+  };
+
+  for (const auto& request : resources)
+    SimulateLoadedResource(request);
+
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+
+  ValidateUKM(true /* server_lofi_expected */, false /* client_lofi_expected */,
+              false /* lite_page_expected */, false /* noscript_expected */,
+              false /* resource_loading_hints_expected */,
+              2 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -540,11 +731,17 @@
   ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
-TEST_F(PreviewsUKMObserverTest, BothLoFiOptOut) {
+TEST_F(PreviewsUKMObserverTest, BothLoFiOptOutInfobar) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {} /* enabled features */,
+      {previews::features::
+           kAndroidOmniboxPreviewsBadge} /* disabled features */);
+
   RunTest(true /* data_reduction_proxy_used */, false /* lite_page_received */,
           false /* noscript_on */, false /* resource_loading_hints_on */,
           false /* origin_opt_out */, false /* save_data_enabled */);
@@ -584,7 +781,56 @@
   ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */,
               false /* lite_page_expected */, false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              true /* opt_out_expected */, false /* origin_opt_out_expected */,
+              1 /* opt_out_value */, false /* origin_opt_out_expected */,
+              false /* save_data_enabled_expected */);
+}
+
+TEST_F(PreviewsUKMObserverTest, BothLoFiOptOutChip) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kAndroidOmniboxPreviewsBadge} /* enabled features */,
+      {} /*disabled features */);
+
+  RunTest(true /* data_reduction_proxy_used */, false /* lite_page_received */,
+          false /* noscript_on */, false /* resource_loading_hints_on */,
+          false /* origin_opt_out */, false /* save_data_enabled */);
+
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data1 =
+      std::make_unique<data_reduction_proxy::DataReductionProxyData>();
+  data1->set_used_data_reduction_proxy(true);
+  data1->set_lofi_received(true);
+
+  std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data2 =
+      std::make_unique<data_reduction_proxy::DataReductionProxyData>();
+  data2->set_used_data_reduction_proxy(true);
+  data2->set_client_lofi_requested(true);
+
+  // Prepare 4 resources of varying size and configurations, 1 has Client LoFi,
+  // 1 has Server LoFi.
+  page_load_metrics::ExtraRequestCompleteInfo resources[] = {
+      // Uncached proxied request with .1 compression ratio.
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 * 10 /* original_network_content_length */, std::move(data1),
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+      // Uncached proxied request with .5 compression ratio.
+      {GURL(kDefaultTestUrl), net::HostPortPair(), -1, false /*was_cached*/,
+       1024 * 40 /* raw_body_bytes */,
+       1024 * 40 * 5 /* original_network_content_length */, std::move(data2),
+       content::ResourceType::RESOURCE_TYPE_IMAGE, 0,
+       nullptr /* load_timing_info */},
+  };
+
+  for (const auto& request : resources)
+    SimulateLoadedResource(request);
+  observer()->BroadcastEventToObservers(
+      PreviewsInfoBarDelegate::OptOutEventKey());
+  NavigateToUntrackedUrl();
+  ValidateUKM(true /* server_lofi_expected */, true /* client_lofi_expected */,
+              false /* lite_page_expected */, false /* noscript_expected */,
+              false /* resource_loading_hints_expected */,
+              2 /* opt_out_value */, false /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -599,7 +845,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, true /* origin_opt_out_expected */,
+              0 /* opt_out_value */, true /* origin_opt_out_expected */,
               false /* save_data_enabled_expected */);
 }
 
@@ -614,7 +860,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               true /* save_data_enabled_expected */);
 }
 
@@ -629,7 +875,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               true /* save_data_enabled_expected */);
 }
 
@@ -644,7 +890,7 @@
               false /* client_lofi_expected */, false /* lite_page_expected */,
               false /* noscript_expected */,
               false /* resource_loading_hints_expected */,
-              false /* opt_out_expected */, false /* origin_opt_out_expected */,
+              0 /* opt_out_value */, false /* origin_opt_out_expected */,
               true /* save_data_enabled_expected */);
 }
 
diff --git a/chrome/browser/previews/previews_ui_tab_helper.cc b/chrome/browser/previews/previews_ui_tab_helper.cc
index f52eaf70..f120426 100644
--- a/chrome/browser/previews/previews_ui_tab_helper.cc
+++ b/chrome/browser/previews/previews_ui_tab_helper.cc
@@ -88,8 +88,7 @@
   on_dismiss_callback_ = std::move(on_dismiss_callback);
 
 #if defined(OS_ANDROID)
-  if (base::FeatureList::IsEnabled(
-          previews::features::kAndroidOmniboxPreviewsBadge)) {
+  if (previews::params::IsPreviewsOmniboxUiEnabled()) {
     should_display_android_omnibox_badge_ = true;
     return;
   }
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.css b/chrome/browser/resources/local_ntp/custom_links_edit.css
index aad5dec..363331d 100644
--- a/chrome/browser/resources/local_ntp/custom_links_edit.css
+++ b/chrome/browser/resources/local_ntp/custom_links_edit.css
@@ -128,9 +128,6 @@
   margin-top: 24px;
 }
 
-.buttons-container .right {
-}
-
 button {
   border: none;
   border-radius: 4px;
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.html b/chrome/browser/resources/local_ntp/custom_links_edit.html
index 71e8e903..a3a6924 100644
--- a/chrome/browser/resources/local_ntp/custom_links_edit.html
+++ b/chrome/browser/resources/local_ntp/custom_links_edit.html
@@ -31,8 +31,10 @@
         <div id="invalid-url" class="error-msg"></div>
       </div>
       <div class="buttons-container">
-        <button id="delete" class="secondary" type="button" tabindex="0"></button>
-        <span class="right">
+        <span>
+          <button id="delete" class="secondary" type="button" tabindex="0"></button>
+        </span>
+        <span>
           <button id="cancel" class="secondary" type="button" tabindex="0"></button>
           <button type="submit" id="done" class="primary" tabindex="0"></button>
         </span>
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
index cb45f58f..1c9b605 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
@@ -250,12 +250,12 @@
 }
 
 #sink-search-input {
+  --cr-input-background-color: white;
   --cr-input-container: {
     border-radius: 0;
   }
   --cr-input-error-display: none;
   --cr-input-input: {
-    background-color: white;
     border-bottom: 1px solid var(--paper-grey-800);
   }
   --cr-input-padding-end: 0;
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
index 2f11b9db..d7c9c12b 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
+++ b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
@@ -22,6 +22,9 @@
         --cr-input-error-display: none;
         --cr-input-background-color: transparent;
         --cr-input-color: white;
+        --cr-input-inner-container: {
+          margin-inline-end: -3px;
+        }
         --cr-input-input: {
           text-align: end;
           caret-color: #fff;
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.html b/chrome/browser/resources/print_preview/new/destination_dialog.html
index efedf4d1b..9393359 100644
--- a/chrome/browser/resources/print_preview/new/destination_dialog.html
+++ b/chrome/browser/resources/print_preview/new/destination_dialog.html
@@ -81,8 +81,6 @@
         padding-bottom: 18px;
       }
 
-      /* Height = 100vh - recent (94px + 1 line + 18px) - padding (68px) - */
-      /* header (82px + 1 line) - button (64px) - 2px spinner - 2px extra */
       #printList {
         flex: 1;
         min-height: calc(94px + 20 / 13 * 1rem);
diff --git a/chrome/browser/resources/print_preview/new/destination_list.html b/chrome/browser/resources/print_preview/new/destination_list.html
index 0a74336..7a989b3 100644
--- a/chrome/browser/resources/print_preview/new/destination_list.html
+++ b/chrome/browser/resources/print_preview/new/destination_list.html
@@ -26,7 +26,7 @@
 
       #listContainer {
         flex: 1;
-        min-height: 0;
+        min-height: 84px;
       }
 
       .title,
@@ -73,17 +73,6 @@
         padding-top: 8px;
       }
 
-      .list-item {
-        cursor: default;
-        display: flex;
-        font-size: calc(12/13 * 1em);
-        min-height: 28px;
-        padding-bottom: 2px;
-        padding-inline-end: 2px;
-        padding-inline-start: 14px;
-        padding-top: 2px;
-      }
-
       :not(.moving).list-item {
         transition: background-color 150ms;
       }
diff --git a/chrome/browser/resources/print_preview/new/destination_list.js b/chrome/browser/resources/print_preview/new/destination_list.js
index dd504fb..16f8ab4 100644
--- a/chrome/browser/resources/print_preview/new/destination_list.js
+++ b/chrome/browser/resources/print_preview/new/destination_list.js
@@ -64,12 +64,10 @@
         return;
 
       const entry = assert(entries[0]);
-      const fullHeight = entry.contentRect.height;
-      // Setting maxHeight to 0 freezes the UI when re-rendering the dialog.
-      if (fullHeight > 0) {
-        this.$.list.style.maxHeight = `${fullHeight}px`;
-        this.forceIronResize();
-      }
+      // Don't set maxHeight below the minimum height.
+      const fullHeight = Math.max(entry.contentRect.height, 84);
+      this.$.list.style.maxHeight = `${fullHeight}px`;
+      this.forceIronResize();
     });
     this.resizeObserver_.observe(this.$.listContainer);
   },
diff --git a/chrome/browser/resources/print_preview/new/destination_list_item.html b/chrome/browser/resources/print_preview/new/destination_list_item.html
index ec5cf71..0c1f640 100644
--- a/chrome/browser/resources/print_preview/new/destination_list_item.html
+++ b/chrome/browser/resources/print_preview/new/destination_list_item.html
@@ -17,8 +17,15 @@
     <style include="print-preview-shared action-link cr-hidden-style">
       :host {
         align-items: center;
-        margin: 4px 0;
+        cursor: default;
+        display: flex;
+        font-size: calc(12/13 * 1em);
+        min-height: 28px;
         opacity: .87;
+        padding-bottom: 2px;
+        padding-inline-end: 2px;
+        padding-inline-start: 14px;
+        padding-top: 2px;
         vertical-align: middle;
       }
 
@@ -35,10 +42,11 @@
 
       iron-icon {
         fill: var(--google-grey-600);
+        flex: 0;
         height: 20px;
         margin-inline-end: 12px;
+        min-width: 20px;
         transition: opacity 150ms;
-        width: 20px;
       }
 
       .name {
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn b/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
index cf04a88..272d36e0 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     ":clear_browsing_data_browser_proxy",
     "../device_page:keyboard",
+    "../people_page:sync_browser_proxy",
     "//third_party/polymer/v1_0/components-chromium/iron-pages:iron-pages-extracted",
     "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
     "//ui/webui/resources/js:cr",
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index 8199683c..441f18e 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_tabs_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
@@ -46,6 +47,12 @@
         padding-top: 8px;
       }
 
+      #clearBrowsingDataDialog [slot=footer] {
+        background: var(--paper-grey-50);
+        border-top: none;
+        padding: 0;
+      }
+
       .row {
         align-items: center;
         display: flex;
@@ -88,6 +95,16 @@
         font-size: calc(13 / 15 * 100%);
         padding-top: 8px;
       }
+
+      .divider {
+        border-top: var(--settings-separator-line);
+        margin: 0 16px;
+      }
+
+      #footer-description {
+        color: var(--cr-secondary-text-color);
+        padding: 16px;
+      }
     </style>
 
     <cr-dialog id="clearBrowsingDataDialog"
@@ -127,7 +144,7 @@
                 pref="{{prefs.browser.clear_data.browsing_history_basic}}"
                 label="$i18n{clearBrowsingHistory}"
                 sub-label-html="[[browsingCheckboxLabel_(
-                    isSignedIn_, isSyncingHistory_,
+                    isSignedIn_, isSyncingHistory_, syncStatus.hasError,
                     '$i18nPolymer{clearBrowsingHistorySummary}',
                     '$i18nPolymer{clearBrowsingHistorySummarySignedIn}',
                     '$i18nPolymer{clearBrowsingHistorySummarySynced}')]]"
@@ -239,6 +256,36 @@
             $i18n{clearData}
         </paper-button>
       </div>
+      <div slot="footer" hidden="[[!syncStatus.signedIn]]">
+        <settings-sync-account-control sync-status="[[syncStatus]]"
+            hide-buttons>
+        </settings-sync-account-control>
+        <div class="divider"></div>
+        <div id="footer-description" on-tap="onSyncDescriptionLinkClicked_">
+          <template is="dom-if" if="[[!syncStatus.hasError]]">
+            <span id="sync-info">
+              $i18nRaw{clearBrowsingDataWithSync}
+            </span>
+          </template>
+          <template is="dom-if" if="[[syncStatus.hasError]]">
+            <template is="dom-if" if="[[isSyncPaused_]]">
+              <span id="sync-paused-info">
+                $i18nRaw{clearBrowsingDataWithSyncPaused}
+              </span>
+            </template>
+            <template is="dom-if" if="[[hasPassphraseError_]]">
+              <span id="sync-passphrase-error-info">
+                $i18nRaw{clearBrowsingDataWithSyncPassphraseError}
+              </span>
+            </template>
+            <template is="dom-if" if="[[hasOtherSyncError_]]">
+              <span id="sync-other-error-info">
+                $i18nRaw{clearBrowsingDataWithSyncError}
+              </span>
+            </template>
+          </template>
+        </div>
+      </div>
     </cr-dialog>
 
     <template is="dom-if" if="[[showHistoryDeletionDialog_]]" restamp>
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
index fd323fc5..74626934e 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
@@ -21,6 +21,12 @@
     },
 
     /**
+     * The current sync status, supplied by SyncBrowserProxy.
+     * @type {?settings.SyncStatus}
+     */
+    syncStatus: Object,
+
+    /**
      * Results of browsing data counters, keyed by the suffix of
      * the corresponding data type deletion preference, as reported
      * by the C++ side.
@@ -94,6 +100,28 @@
       value: false,
     },
 
+    /** @private */
+    isSyncPaused_: {
+      type: Boolean,
+      value: false,
+      computed: 'computeIsSyncPaused_(syncStatus)',
+    },
+
+    /** @private */
+    hasPassphraseError_: {
+      type: Boolean,
+      value: false,
+      computed: 'computeHasPassphraseError_(syncStatus)',
+    },
+
+    /** @private */
+    hasOtherSyncError_: {
+      type: Boolean,
+      value: false,
+      computed:
+          'computeHasOtherError_(syncStatus, isSyncPaused_, hasPassphraseError_)',
+    },
+
     /**
      * Time in ms, when the dialog was opened.
      * @private
@@ -109,8 +137,17 @@
   /** @private {settings.ClearBrowsingDataBrowserProxy} */
   browserProxy_: null,
 
+  /** @private {?settings.SyncBrowserProxy} */
+  syncBrowserProxy_: null,
+
   /** @override */
   ready: function() {
+    this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
+    this.syncBrowserProxy_.getSyncStatus().then(
+        this.handleSyncStatus_.bind(this));
+    this.addWebUIListener(
+        'sync-status-changed', this.handleSyncStatus_.bind(this));
+
     this.addWebUIListener(
         'update-sync-state', this.updateSyncState_.bind(this));
     this.addWebUIListener(
@@ -128,6 +165,15 @@
   },
 
   /**
+   * Handler for when the sync state is pushed from the browser.
+   * @param {?settings.SyncStatus} syncStatus
+   * @private
+   */
+  handleSyncStatus_: function(syncStatus) {
+    this.syncStatus = syncStatus;
+  },
+
+  /**
    * Returns true if either clearing is in progress or no data type is selected.
    * @param {boolean} clearingInProgress
    * @param {boolean} clearButtonDisabled
@@ -193,9 +239,9 @@
    * @private
    */
   browsingCheckboxLabel_: function(
-      isSignedIn, isSyncingHistory, historySummary, historySummarySignedIn,
-      historySummarySynced) {
-    if (isSyncingHistory) {
+      isSignedIn, isSyncingHistory, hasSyncError, historySummary,
+      historySummarySignedIn, historySummarySynced) {
+    if (isSyncingHistory && !hasSyncError) {
       return historySummarySynced;
     } else if (isSignedIn) {
       return historySummarySignedIn;
@@ -318,4 +364,53 @@
           'ClearBrowsingData_SwitchTo_AdvancedTab');
     }
   },
+
+  /**
+   * Called when the user clicks the link in the footer.
+   * @param {!Event} e
+   * @private
+   */
+  onSyncDescriptionLinkClicked_: function(e) {
+    if (e.target.tagName === 'A') {
+      e.preventDefault();
+      if (!this.syncStatus.hasError) {
+        this.syncBrowserProxy_.signOut(false /* deleteProfile */);
+        return;
+      }
+
+      if (this.isSyncPaused_) {
+        this.syncBrowserProxy_.startSignIn();
+      } else {
+        // In any other error case, navigate to the sync page.
+        settings.navigateTo(settings.routes.SYNC);
+      }
+    }
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  computeIsSyncPaused_: function() {
+    return !!this.syncStatus.hasError &&
+        this.syncStatus.statusAction === settings.StatusAction.REAUTHENTICATE;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  computeHasPassphraseError_: function() {
+    return !!this.syncStatus.hasError &&
+        this.syncStatus.statusAction === settings.StatusAction.ENTER_PASSPHRASE;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  computeHasOtherError_: function() {
+    return !!this.syncStatus.hasError && !this.isSyncPaused_ &&
+        !this.hasPassphraseError_;
+  },
 });
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js
index e160544f..6baa366 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.js
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -63,6 +63,14 @@
       reflectToAttribute: true,
     },
 
+    // This property should be set by the parent only and should not change
+    // after the element is created.
+    hideButtons: {
+      type: Boolean,
+      value: false,
+      reflectToAttribute: true,
+    },
+
     /** @private {boolean} */
     shouldShowAvatarRow_: {
       type: Boolean,
@@ -242,7 +250,8 @@
    * @private
    */
   shouldShowTurnOffButton_: function() {
-    return !!this.syncStatus.signedIn && !this.embeddedInSubpage;
+    return !this.hideButtons && !!this.syncStatus.signedIn &&
+        !this.embeddedInSubpage;
   },
 
   /**
@@ -250,8 +259,8 @@
    * @private
    */
   shouldShowSigninAgainButton_: function() {
-    return !!this.syncStatus.signedIn && this.embeddedInSubpage &&
-        !!this.syncStatus.hasError &&
+    return !this.hideButtons && !!this.syncStatus.signedIn &&
+        this.embeddedInSubpage && !!this.syncStatus.hasError &&
         this.syncStatus.statusAction == settings.StatusAction.REAUTHENTICATE;
   },
 
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index ea21039..f9a1f689 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -11,6 +11,7 @@
 <link rel="import" href="../clear_browsing_data_dialog/clear_browsing_data_dialog.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../lifetime_browser_proxy.html">
+<link rel="import" href="../people_page/sync_browser_proxy.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_page/settings_animated_pages.html">
 <link rel="import" href="../settings_page/settings_subpage.html">
diff --git a/chrome/browser/resources/settings/settings_page/settings_subpage_search.html b/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
index 916eb74..5e5c0e7 100644
--- a/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
+++ b/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
@@ -23,12 +23,12 @@
       }
 
       cr-input {
+        --cr-input-background-color: white;
         --cr-input-container: {
           border-radius: 0;
         }
         --cr-input-error-display: none;
         --cr-input-input: {
-          background-color: white;
           border-bottom: 1px solid var(--google-grey-900);
         }
         --cr-input-padding-end: 0;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
index 277633a..1bbe6d3 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
@@ -8,11 +8,11 @@
 var nuxEmail = nuxEmail || {};
 
 /**
- * @typedef {{
+ * @typedef {?{
  *    name: string,
  *    icon: string,
  *    url: string,
- *    bookmarkId: {string|undefined},
+ *    bookmarkId: (string|undefined),
  * }}
  */
 nuxEmail.EmailProviderModel;
@@ -42,7 +42,7 @@
     },
   },
 
-  /** @private {NuxEmailProxy} */
+  /** @private {nux.NuxEmailProxy} */
   browserProxy_: null,
 
   /** @override */
@@ -110,7 +110,7 @@
   },
 
   /**
-   * @param {nuxEmail.EmailProviderModel=} newEmail
+   * @param {nuxEmail.EmailProviderModel=} emailProvider
    * @private
    */
   revertBookmark_: function(emailProvider) {
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
index 75d2b553..907d3c7 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
@@ -37,6 +37,15 @@
   const INTERACTION_METRIC_COUNT =
       Object.keys(NuxEmailProvidersInteractions).length;
 
+  /**
+   * @typedef {{
+   *    parentId: string,
+   *    title: string,
+   *    url: string,
+   * }}
+   */
+  let bookmarkData;
+
   /** @interface */
   class NuxEmailProxy {
     /** @param {string} id ID provided by callback when bookmark was added. */
@@ -74,8 +83,16 @@
     recordFinalize() {}
   }
 
-  /** @implements {NuxEmailProxy} */
+  /** @implements {nux.NuxEmailProxy} */
   class NuxEmailProxyImpl {
+    constructor() {
+      /** @private {string} */
+      this.firstPart = '';
+
+      /** @private {string} */
+      this.lastPart = '';
+    }
+
     /** @override */
     removeBookmark(id) {
       chrome.bookmarks.remove(id);
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
index 688ffb79..5cec1de 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
@@ -86,7 +86,10 @@
     this.hasAppsSelected = this.computeHasAppsSelected_();
   },
 
-  /** @private {boolean} */
+  /**
+   * @return {boolean}
+   * @private
+   */
   computeHasAppsSelected_: function() {
     return this.appList.some(a => a.selected);
   },
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js
index 48d63ceb..ea98a55f 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js
@@ -12,7 +12,7 @@
     addGoogleApps(selectedApps) {}
   }
 
-  /** @implements {NuxGoogleAppsProxy} */
+  /** @implements {nux.NuxGoogleAppsProxy} */
   class NuxGoogleAppsProxyImpl {
     /** @override */
     addGoogleApps(selectedApps) {
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js b/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js
index fd9cd094..c1cdfa6 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js
@@ -54,7 +54,7 @@
 
   // Notifies all the elements that extended NavigationBehavior.
   function notifyObservers() {
-    const route = history.state.route;
+    const route = /** @type {!welcome.Routes} */ (history.state.route);
     const step = history.state.step;
     routeObservers.forEach((observer) => {
       observer.onRouteChange(route, step);
@@ -73,7 +73,9 @@
 
       // history state was set when page loaded, so when the element first
       // attaches, call the route-change handler to initialize first.
-      this.onRouteChange(history.state.route, history.state.step);
+      this.onRouteChange(
+          /** @type {!welcome.Routes} */ (history.state.route),
+          history.state.step);
     },
 
     /** @override */
@@ -95,7 +97,7 @@
     },
 
     /**
-     * @param {string} route
+     * @param {!welcome.Routes} route
      * @param {number} step
      */
     navigateTo: function(route, step) {
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
index ec5465f1..0e29e03 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -2,8 +2,12 @@
 <html dir="$i18n{textdirection}" lang="$i18n{language}">
 <head>
   <meta charset="utf-8">
-  <title>TODO_TITLE</title>
+  <title>$i18n{headerText}</title>
   <link rel="import" href="chrome://resources/html/polymer.html">
+  <link rel="import" href="chrome://resources/cr_elements/icons.html">
+  <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+  <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+  <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
   <link rel="import" href="nux_set_as_default_proxy.html">
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <style>
@@ -14,7 +18,7 @@
 
   <dom-module id="nux-set-as-default">
     <template>
-      <style>
+      <style include="paper-button-style">
         :host {
           align-items: center;
           display: flex;
@@ -24,11 +28,64 @@
 
         .container {
           text-align: center;
-          width: 800;
+          width: 800px;
+        }
+
+        .logo {
+          margin-bottom: 16px;
+          /* TODO(scottchen): placeholder; replace when asset is available. */
+          width: 32px;
+          height: 32px;
+          display: inline-block;
+          background: red;
+        }
+
+        h1 {
+          color: #202124;
+          font-weight: 500;
+          font-size: 1.5rem;
+          line-height: 2.5rem;
+          margin: 0;
+        }
+
+        h2 {
+          color: #202124;
+          font-weight: unset;
+          font-size: 1.25rem;
+          line-height: 1.875rem;
+          margin: 0;
+          margin-top: 16px;
+          margin-bottom: 48px;
+        }
+
+        img {
+          /* TODO(scottchen): placeholder; replace when asset is available. */
+          width: 454px;
+          height: 186px;
+          display: inline-block;
+          background: red;
+        }
+
+        .button-bar {
+          display: flex;
+          margin-top: 64px;
+          justify-content: space-between;
         }
       </style>
       <div class="container">
-        hi
+        <div class="logo"></div>
+        <h1>TODO_HEADER</h1>
+        <h2>TODO_SUBHEADER</h2>
+        <!-- TODO(scottchen): WIP behind feature flag, add src later. -->
+        <img>
+        <div class="button-bar">
+          <paper-button on-click="onDeclineClick_">
+            TODO_NO_THANKS
+          </paper-button>
+          <paper-button class="action-button" on-click="onSetDefaultClick_">
+            TODO_SET_AS_DEFAULT
+          </paper-button>
+        </div>
       </div>
     </template>
     <script src="nux_set_as_default.js"></script>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
index fa1e154..97e443a 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
@@ -4,4 +4,48 @@
 
 Polymer({
   is: 'nux-set-as-default',
+
+  behaviors: [WebUIListenerBehavior],
+
+  /** @private {nux.NuxSetAsDefaultProxy} */
+  browserProxy_: null,
+
+  /** @override */
+  attached: function() {
+    this.browserProxy_ = nux.NuxSetAsDefaultProxyImpl.getInstance();
+
+    this.addWebUIListener(
+        'browser-default-state-changed',
+        this.onDefaultBrowserChange_.bind(this));
+  },
+
+  /** @private */
+  onDeclineClick_: function() {
+    // TODO(scottchen): Add UMA collection here.
+
+    this.finished_();
+  },
+
+  /** @private */
+  onSetDefaultClick_: function() {
+    this.browserProxy_.setAsDefault();
+  },
+
+  /**
+   * Automatically navigate to the next onboarding step once default changed.
+   * @param {boolean} isDefault
+   * @private
+   */
+  onDefaultBrowserChange_: function(isDefault) {
+    // TODO(scottchen): Add UMA collection here.
+
+    if (isDefault)
+      this.finished_();
+  },
+
+  /** @private */
+  finished_: function() {
+    // TODO(scottchen): use navigation behavior to go to next step once this
+    //     module is integrated with onboarding-welcome's welcome-app.
+  },
 });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
index 19be0e40..d4b50fe 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
@@ -4,10 +4,17 @@
 
 cr.define('nux', function() {
   /** @interface */
-  class NuxSetAsDefaultProxy {}
+  class NuxSetAsDefaultProxy {
+    setAsDefault() {}
+  }
 
-  /** @implements {NuxSetAsDefaultProxy} */
-  class NuxSetAsDefaultProxyImpl {}
+  /** @implements {nux.NuxSetAsDefaultProxy} */
+  class NuxSetAsDefaultProxyImpl {
+    /** @override */
+    setAsDefault() {
+      chrome.send('setAsDefaultBrowser');
+    }
+  }
 
   cr.addSingletonGetter(NuxSetAsDefaultProxyImpl);
 
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
index 09fe062c..4122b2e 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
@@ -27,7 +27,7 @@
   },
 
   /**
-   * @param {string} route
+   * @param {welcome.Routes} route
    * @param {number} step
    * @private
    */
@@ -46,6 +46,7 @@
       this.$.viewManager.switchView('step-' + step);
   },
 
+  /** @param {!Array<string>} modules Array of valid DOM element names. */
   initializeModules: function(modules) {
     assert(this.currentRoute_);  // this.currentRoute_ should be set by now.
     if (this.currentRoute_ == welcome.Routes.LANDING)
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
index 37092369..5f4f64f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -83,6 +83,9 @@
 const char kPageBeforeLandingReferrerURL[] =
     "/safe_browsing/download_protection/navigation_observer/"
     "page_before_landing_referrer.html";
+const char kCreateIframeElementURL[] =
+    "/safe_browsing/download_protection/navigation_observer/"
+    "create_iframe_element.html";
 
 class DownloadItemCreatedObserver : public DownloadManager::Observer {
  public:
@@ -2492,4 +2495,15 @@
   EXPECT_EQ(1U, nav_list->Size());
 }
 
+IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest,
+                       CreateIframeElementGetsReferrerChain) {
+  GURL initial_url = embedded_test_server()->GetURL(kCreateIframeElementURL);
+  ui_test_utils::NavigateToURL(browser(), initial_url);
+  ClickTestLink("do_download", 1, initial_url);
+
+  ReferrerChain referrer_chain;
+  IdentifyReferrerChainForDownload(GetDownload(), &referrer_chain);
+  ASSERT_EQ(2, referrer_chain.size());
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc
index d9be41f..23547e2 100644
--- a/chrome/browser/sync/test/integration/bookmarks_helper.cc
+++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -367,10 +367,8 @@
     return false;
 
   // Compare only the 1x bitmaps as only those are synced.
-  SkBitmap bitmap_a = image_a.AsImageSkia().GetRepresentation(
-      1.0f).sk_bitmap();
-  SkBitmap bitmap_b = image_b.AsImageSkia().GetRepresentation(
-      1.0f).sk_bitmap();
+  SkBitmap bitmap_a = image_a.AsImageSkia().GetRepresentation(1.0f).GetBitmap();
+  SkBitmap bitmap_b = image_b.AsImageSkia().GetRepresentation(1.0f).GetBitmap();
   return FaviconRawBitmapsMatch(bitmap_a, bitmap_b);
 }
 
diff --git a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
index 4700641..b69d699 100644
--- a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "extensions/browser/extension_system.h"
 
@@ -124,10 +125,13 @@
   app_list::AppListSyncableService* service =
       app_list::AppListSyncableServiceFactory::GetForProfile(verifier());
 
-  // Default apps: chrome + web store + internal apps.
+  // Default apps: chrome + web store + internal apps + number of default page
+  // breaks.
   const size_t kNumDefaultApps =
-      2u + app_list::GetNumberOfInternalAppsShowInLauncherForTest(
-               /*apps_name=*/nullptr, GetProfile(0));
+      2u +
+      app_list::GetNumberOfInternalAppsShowInLauncherForTest(
+          /*apps_name=*/nullptr, GetProfile(0)) +
+      app_list::kDefaultPageBreakAppIdsLength;
   ASSERT_EQ(kNumApps + kNumDefaultApps, service->GetNumSyncItemsForTest());
 
   ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
diff --git a/chrome/browser/sync/test/integration/sync_app_list_helper.cc b/chrome/browser/sync/test/integration/sync_app_list_helper.cc
index 647afcc..cf6f9e33 100644
--- a/chrome/browser/sync/test/integration/sync_app_list_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_app_list_helper.cc
@@ -42,6 +42,15 @@
   for (auto* profile : test_->GetAllProfiles()) {
     extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
         true /* extensions_enabled */);
+    if (test_->use_verifier() && profile == test_->verifier()) {
+      // The default page break items are only installed for first-time users.
+      // The verifier() profile doesn't get initialized with remote sync data,
+      // and hence the default page breaks are not installed for it. We have to
+      // install them manually to avoid a mismatch when comparing the verifier()
+      // against other client profiles.
+      app_list::AppListSyncableServiceFactory::GetForProfile(profile)
+          ->InstallDefaultPageBreaksForTest();
+    }
   }
 
   setup_completed_ = true;
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
index e86a34ca..3933454 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -363,7 +363,7 @@
 
   FileSystemURL url_for_sync = CreateSyncableFileSystemURLForSync(
       file_system_context, url);
-  FileSystemOperation::StatusCallback operation_callback = base::Bind(
+  FileSystemOperation::StatusCallback operation_callback = base::BindOnce(
       &LocalFileSyncContext::DidApplyRemoteChange, this, url, callback);
 
   DCHECK_EQ(FileChange::FILE_CHANGE_ADD_OR_UPDATE, change.change());
@@ -375,7 +375,7 @@
           storage::VirtualPath::DirName(dir_path) == dir_path) {
         // Copying into the root directory.
         file_system_context->operation_runner()->CopyInForeignFile(
-            local_path, url_for_sync, operation_callback);
+            local_path, url_for_sync, std::move(operation_callback));
       } else {
         FileSystemURL dir_url = file_system_context->CreateCrackedFileSystemURL(
             url_for_sync.origin(),
@@ -383,16 +383,16 @@
             storage::VirtualPath::DirName(url_for_sync.virtual_path()));
         file_system_context->operation_runner()->CreateDirectory(
             dir_url, false /* exclusive */, true /* recursive */,
-            base::Bind(&LocalFileSyncContext::DidCreateDirectoryForCopyIn, this,
-                       base::RetainedRef(file_system_context), local_path, url,
-                       operation_callback));
+            base::BindOnce(&LocalFileSyncContext::DidCreateDirectoryForCopyIn,
+                           this, base::RetainedRef(file_system_context),
+                           local_path, url, std::move(operation_callback)));
       }
       break;
     }
     case SYNC_FILE_TYPE_DIRECTORY:
       file_system_context->operation_runner()->CreateDirectory(
           url_for_sync, false /* exclusive */, true /* recursive */,
-          operation_callback);
+          std::move(operation_callback));
       break;
     case SYNC_FILE_TYPE_UNKNOWN:
       NOTREACHED() << "File type unknown for ADD_OR_UPDATE change";
@@ -1037,17 +1037,17 @@
     FileSystemContext* file_system_context,
     const base::FilePath& local_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error) {
   if (error != base::File::FILE_OK) {
-    callback.Run(error);
+    std::move(callback).Run(error);
     return;
   }
 
   FileSystemURL url_for_sync = CreateSyncableFileSystemURLForSync(
       file_system_context, dest_url);
   file_system_context->operation_runner()->CopyInForeignFile(
-      local_path, url_for_sync, callback);
+      local_path, url_for_sync, std::move(callback));
 }
 
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.h b/chrome/browser/sync_file_system/local/local_file_sync_context.h
index b2bd629..83fe0f7 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.h
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.h
@@ -210,7 +210,7 @@
   void OnWriteEnabled(const storage::FileSystemURL& url) override;
 
  private:
-  using StatusCallback = base::Callback<void(base::File::Error result)>;
+  using StatusCallback = base::OnceCallback<void(base::File::Error result)>;
   using StatusCallbackQueue = base::circular_deque<SyncStatusCallback>;
   using FileSystemURLQueue = base::circular_deque<storage::FileSystemURL>;
   friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
@@ -324,7 +324,7 @@
       storage::FileSystemContext* file_system_context,
       const base::FilePath& local_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback,
+      StatusCallback callback,
       base::File::Error error);
 
   const base::FilePath local_base_path_;
diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
index 56658e32..88af0591 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
@@ -384,10 +384,12 @@
   EXPECT_EQ(1, callback_count_);
 
   // Now the file must have been created and have the same content as temp_path.
+  // TODO(mek): AdaptCallbackForRepeating is needed here because
+  // CannedSyncableFileSystem hasn't switched to OnceCallback yet.
   ResetCallbackStatus();
   file_system_.DoVerifyFile(
       URL(kFile), kTestData,
-      ExpectStatus(FROM_HERE, File::FILE_OK));
+      base::AdaptCallbackForRepeating(ExpectStatus(FROM_HERE, File::FILE_OK)));
   content::RunAllTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 }
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
index d89215f4..83349bda3 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
@@ -75,18 +75,17 @@
 
 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
 
-void SyncableFileSystemOperation::CreateFile(
-    const FileSystemURL& url,
-    bool exclusive,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::CreateFile(const FileSystemURL& url,
+                                             bool exclusive,
+                                             StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::CreateFile,
@@ -95,19 +94,18 @@
   operation_runner_->PostOperationTask(std::move(task));
 }
 
-void SyncableFileSystemOperation::CreateDirectory(
-    const FileSystemURL& url,
-    bool exclusive,
-    bool recursive,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::CreateDirectory(const FileSystemURL& url,
+                                                  bool exclusive,
+                                                  bool recursive,
+                                                  StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::CreateDirectory,
@@ -122,15 +120,15 @@
     CopyOrMoveOption option,
     ErrorBehavior error_behavior,
     const CopyProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(dest_url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::Copy, base::Unretained(impl_.get()),
@@ -139,20 +137,19 @@
   operation_runner_->PostOperationTask(std::move(task));
 }
 
-void SyncableFileSystemOperation::Move(
-    const FileSystemURL& src_url,
-    const FileSystemURL& dest_url,
-    CopyOrMoveOption option,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::Move(const FileSystemURL& src_url,
+                                       const FileSystemURL& dest_url,
+                                       CopyOrMoveOption option,
+                                       StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(src_url);
   target_paths_.push_back(dest_url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::Move, base::Unretained(impl_.get()),
@@ -161,26 +158,23 @@
   operation_runner_->PostOperationTask(std::move(task));
 }
 
-void SyncableFileSystemOperation::DirectoryExists(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::DirectoryExists(const FileSystemURL& url,
+                                                  StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->DirectoryExists(url, callback);
+  impl_->DirectoryExists(url, std::move(callback));
 }
 
-void SyncableFileSystemOperation::FileExists(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::FileExists(const FileSystemURL& url,
+                                             StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->FileExists(url, callback);
+  impl_->FileExists(url, std::move(callback));
 }
 
-void SyncableFileSystemOperation::GetMetadata(
-    const FileSystemURL& url,
-    int fields,
-    const GetMetadataCallback& callback) {
+void SyncableFileSystemOperation::GetMetadata(const FileSystemURL& url,
+                                              int fields,
+                                              GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->GetMetadata(url, fields, callback);
+  impl_->GetMetadata(url, fields, std::move(callback));
 }
 
 void SyncableFileSystemOperation::ReadDirectory(
@@ -193,17 +187,17 @@
   impl_->ReadDirectory(url, callback);
 }
 
-void SyncableFileSystemOperation::Remove(
-    const FileSystemURL& url, bool recursive,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::Remove(const FileSystemURL& url,
+                                         bool recursive,
+                                         StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::Remove, base::Unretained(impl_.get()),
@@ -212,7 +206,7 @@
   operation_runner_->PostOperationTask(std::move(task));
 }
 
-void SyncableFileSystemOperation::Write(
+void SyncableFileSystemOperation::WriteBlob(
     const FileSystemURL& url,
     std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
     std::unique_ptr<storage::BlobReader> blob_reader,
@@ -224,27 +218,49 @@
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(url);
-  completion_callback_ = base::Bind(&WriteCallbackAdapter, callback);
+  completion_callback_ = base::BindOnce(&WriteCallbackAdapter, callback);
+  std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
+      weak_factory_.GetWeakPtr(),
+      base::Bind(
+          &FileSystemOperation::WriteBlob, base::Unretained(impl_.get()), url,
+          base::Passed(&writer_delegate), base::Passed(&blob_reader),
+          base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(), callback))));
+  operation_runner_->PostOperationTask(std::move(task));
+}
+
+void SyncableFileSystemOperation::Write(
+    const FileSystemURL& url,
+    std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
+    mojo::ScopedDataPipeConsumerHandle data_pipe,
+    const WriteCallback& callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  if (!operation_runner_.get()) {
+    callback.Run(base::File::FILE_ERROR_NOT_FOUND, 0, true);
+    return;
+  }
+  DCHECK(operation_runner_.get());
+  target_paths_.push_back(url);
+  completion_callback_ = base::BindOnce(&WriteCallbackAdapter, callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(
           &FileSystemOperation::Write, base::Unretained(impl_.get()), url,
-          base::Passed(&writer_delegate), base::Passed(&blob_reader),
+          base::Passed(&writer_delegate), base::Passed(&data_pipe),
           base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(), callback))));
   operation_runner_->PostOperationTask(std::move(task));
 }
 
 void SyncableFileSystemOperation::Truncate(const FileSystemURL& url,
                                            int64_t length,
-                                           const StatusCallback& callback) {
+                                           StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::Truncate, base::Unretained(impl_.get()),
@@ -257,22 +273,21 @@
     const FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->TouchFile(url, last_access_time, last_modified_time, callback);
+  impl_->TouchFile(url, last_access_time, last_modified_time,
+                   std::move(callback));
 }
 
-void SyncableFileSystemOperation::OpenFile(
-    const FileSystemURL& url,
-    int file_flags,
-    const OpenFileCallback& callback) {
+void SyncableFileSystemOperation::OpenFile(const FileSystemURL& url,
+                                           int file_flags,
+                                           OpenFileCallback callback) {
   NOTREACHED();
 }
 
-void SyncableFileSystemOperation::Cancel(
-    const StatusCallback& cancel_callback) {
+void SyncableFileSystemOperation::Cancel(StatusCallback cancel_callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->Cancel(cancel_callback);
+  impl_->Cancel(std::move(cancel_callback));
 }
 
 void SyncableFileSystemOperation::CreateSnapshotFile(
@@ -285,15 +300,15 @@
 void SyncableFileSystemOperation::CopyInForeignFile(
     const base::FilePath& src_local_disk_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!operation_runner_.get()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   DCHECK(operation_runner_.get());
   target_paths_.push_back(dest_url);
-  completion_callback_ = callback;
+  completion_callback_ = std::move(callback);
   std::unique_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
       weak_factory_.GetWeakPtr(),
       base::Bind(&FileSystemOperation::CopyInForeignFile,
@@ -302,18 +317,16 @@
   operation_runner_->PostOperationTask(std::move(task));
 }
 
-void SyncableFileSystemOperation::RemoveFile(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::RemoveFile(const FileSystemURL& url,
+                                             StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->RemoveFile(url, callback);
+  impl_->RemoveFile(url, std::move(callback));
 }
 
-void SyncableFileSystemOperation::RemoveDirectory(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::RemoveDirectory(const FileSystemURL& url,
+                                                  StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->RemoveDirectory(url, callback);
+  impl_->RemoveDirectory(url, std::move(callback));
 }
 
 void SyncableFileSystemOperation::CopyFileLocal(
@@ -321,18 +334,18 @@
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
     const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->CopyFileLocal(src_url, dest_url, option, progress_callback, callback);
+  impl_->CopyFileLocal(src_url, dest_url, option, progress_callback,
+                       std::move(callback));
 }
 
-void SyncableFileSystemOperation::MoveFileLocal(
-    const FileSystemURL& src_url,
-    const FileSystemURL& dest_url,
-    CopyOrMoveOption option,
-    const StatusCallback& callback) {
+void SyncableFileSystemOperation::MoveFileLocal(const FileSystemURL& src_url,
+                                                const FileSystemURL& dest_url,
+                                                CopyOrMoveOption option,
+                                                StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  impl_->MoveFileLocal(src_url, dest_url, option, callback);
+  impl_->MoveFileLocal(src_url, dest_url, option, std::move(callback));
 }
 
 base::File::Error SyncableFileSystemOperation::SyncGetPlatformPath(
@@ -366,7 +379,7 @@
   DCHECK(!completion_callback_.is_null());
   if (operation_runner_.get())
     operation_runner_->OnOperationCompleted(target_paths_);
-  completion_callback_.Run(status);
+  std::move(completion_callback_).Run(status);
 }
 
 void SyncableFileSystemOperation::DidWrite(const WriteCallback& callback,
@@ -385,7 +398,7 @@
 
 void SyncableFileSystemOperation::OnCancelled() {
   DCHECK(!completion_callback_.is_null());
-  completion_callback_.Run(base::File::FILE_ERROR_ABORT);
+  std::move(completion_callback_).Run(base::File::FILE_ERROR_ABORT);
 }
 
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
index 2f284910..05449cf 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
+++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
@@ -34,66 +34,70 @@
   // storage::FileSystemOperation overrides.
   void CreateFile(const storage::FileSystemURL& url,
                   bool exclusive,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void CreateDirectory(const storage::FileSystemURL& url,
                        bool exclusive,
                        bool recursive,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void Copy(const storage::FileSystemURL& src_url,
             const storage::FileSystemURL& dest_url,
             CopyOrMoveOption option,
             ErrorBehavior error_behavior,
             const CopyProgressCallback& progress_callback,
-            const StatusCallback& callback) override;
+            StatusCallback callback) override;
   void Move(const storage::FileSystemURL& src_url,
             const storage::FileSystemURL& dest_url,
             CopyOrMoveOption option,
-            const StatusCallback& callback) override;
+            StatusCallback callback) override;
   void DirectoryExists(const storage::FileSystemURL& url,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void FileExists(const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void GetMetadata(const storage::FileSystemURL& url,
                    int fields,
-                   const GetMetadataCallback& callback) override;
+                   GetMetadataCallback callback) override;
   void ReadDirectory(const storage::FileSystemURL& url,
                      const ReadDirectoryCallback& callback) override;
   void Remove(const storage::FileSystemURL& url,
               bool recursive,
-              const StatusCallback& callback) override;
+              StatusCallback callback) override;
+  void WriteBlob(const storage::FileSystemURL& url,
+                 std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
+                 std::unique_ptr<storage::BlobReader> blob_reader,
+                 const WriteCallback& callback) override;
   void Write(const storage::FileSystemURL& url,
              std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
-             std::unique_ptr<storage::BlobReader> blob_reader,
+             mojo::ScopedDataPipeConsumerHandle data_pipe,
              const WriteCallback& callback) override;
   void Truncate(const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void TouchFile(const storage::FileSystemURL& url,
                  const base::Time& last_access_time,
                  const base::Time& last_modified_time,
-                 const StatusCallback& callback) override;
+                 StatusCallback callback) override;
   void OpenFile(const storage::FileSystemURL& url,
                 int file_flags,
-                const OpenFileCallback& callback) override;
-  void Cancel(const StatusCallback& cancel_callback) override;
+                OpenFileCallback callback) override;
+  void Cancel(StatusCallback cancel_callback) override;
   void CreateSnapshotFile(const storage::FileSystemURL& path,
                           SnapshotFileCallback callback) override;
   void CopyInForeignFile(const base::FilePath& src_local_disk_path,
                          const storage::FileSystemURL& dest_url,
-                         const StatusCallback& callback) override;
+                         StatusCallback callback) override;
   void RemoveFile(const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void RemoveDirectory(const storage::FileSystemURL& url,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void CopyFileLocal(const storage::FileSystemURL& src_url,
                      const storage::FileSystemURL& dest_url,
                      CopyOrMoveOption option,
                      const CopyFileProgressCallback& progress_callback,
-                     const StatusCallback& callback) override;
+                     StatusCallback callback) override;
   void MoveFileLocal(const storage::FileSystemURL& src_url,
                      const storage::FileSystemURL& dest_url,
                      CopyOrMoveOption option,
-                     const StatusCallback& callback) override;
+                     StatusCallback callback) override;
   base::File::Error SyncGetPlatformPath(const storage::FileSystemURL& url,
                                         base::FilePath* platform_path) override;
 
diff --git a/chrome/browser/task_manager/providers/web_contents/subframe_task.cc b/chrome/browser/task_manager/providers/web_contents/subframe_task.cc
index 7b0200e..130d562 100644
--- a/chrome/browser/task_manager/providers/web_contents/subframe_task.cc
+++ b/chrome/browser/task_manager/providers/web_contents/subframe_task.cc
@@ -56,15 +56,6 @@
 base::string16 SubframeTask::GetTitle() {
   DCHECK(site_instance_);
 
-  if (site_instance_->IsDefaultSubframeSiteInstance()) {
-    base::string16 main_task_title =
-        main_task_->GetTitleFromWebContents(main_task_->web_contents());
-    int message_id = site_instance_->GetBrowserContext()->IsOffTheRecord()
-                         ? IDS_TASK_MANAGER_ISOLATED_INCOGNITO_SUBFRAMES_PREFIX
-                         : IDS_TASK_MANAGER_ISOLATED_SUBFRAMES_PREFIX;
-    return l10n_util::GetStringFUTF16(message_id, main_task_title);
-  }
-
   // By default, subframe rows display the site, like this:
   //     "Subframe: http://example.com/"
   const GURL& site_url = site_instance_->GetSiteURL();
diff --git a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
index efdba24..0211fb02 100644
--- a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
+++ b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
@@ -43,11 +43,6 @@
                                     base::UTF8ToUTF16(title));
 }
 
-base::string16 PrefixExpectedTDIRowTitle(const std::string& title) {
-  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_ISOLATED_SUBFRAMES_PREFIX,
-                                    base::UTF8ToUTF16(title));
-}
-
 }  // namespace
 
 // A test for OOPIFs and how they show up in the task manager as
@@ -198,77 +193,4 @@
               unresponsive_task == subframe_task_2);
 }
 
-// A test for top document isolation and how subframes show up in the task
-// manager as SubframeTasks.
-class SubframeTaskTDIBrowserTest : public InProcessBrowserTest {
- public:
-  SubframeTaskTDIBrowserTest() {}
-  ~SubframeTaskTDIBrowserTest() override {}
-
-  void SetUpOnMainThread() override {
-    scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
-    host_resolver()->AddRule("*", "127.0.0.1");
-    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
-    content::SetupCrossSiteRedirector(embedded_test_server());
-    embedded_test_server()->StartAcceptingConnections();
-  }
-
-  void NavigateTo(const char* page_url) const {
-    ui_test_utils::NavigateToURL(browser(),
-                                 embedded_test_server()->GetURL(page_url));
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(SubframeTaskTDIBrowserTest);
-};
-
-// Makes sure that subframe row gets updated with the new title when the main
-// frame's title changes.
-IN_PROC_BROWSER_TEST_F(SubframeTaskTDIBrowserTest,
-                       SubframeRowGetsUpdatedParentPageTitle) {
-  if (content::AreAllSitesIsolatedForTesting()) {
-    // If full site isolation is turned on, it supersedes top document
-    // isolation, so bail if it is.
-    return;
-  }
-
-  MockWebContentsTaskManager task_manager;
-  EXPECT_TRUE(task_manager.tasks().empty());
-  task_manager.StartObserving();
-
-  // Currently only the about:blank page.
-  ASSERT_EQ(1U, task_manager.tasks().size());
-  const Task* about_blank_task = task_manager.tasks().front();
-  EXPECT_EQ(Task::RENDERER, about_blank_task->GetType());
-  EXPECT_EQ(PrefixExpectedTabTitle("about:blank"), about_blank_task->title());
-
-  // Start with a known title, make sure everything starts correctly.
-  NavigateTo(kCrossSitePageUrl);
-
-  ASSERT_EQ(2U, task_manager.tasks().size());
-  const Task* main_task = task_manager.tasks()[0];
-  const Task* tdi_task = task_manager.tasks()[1];
-  EXPECT_EQ(Task::RENDERER, main_task->GetType());
-  EXPECT_EQ(Task::RENDERER, tdi_task->GetType());
-  std::string main_title = "cross-site iframe test";
-  EXPECT_EQ(PrefixExpectedTabTitle(main_title), main_task->title());
-  EXPECT_EQ(PrefixExpectedTDIRowTitle(main_title), tdi_task->title());
-
-  // Change the title on the main page, and make sure the TDI row reflects it.
-  std::string new_title = "new title";
-  std::string script = "document.title = '" + new_title + "'";
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  content::TitleWatcher title_watcher(web_contents,
-                                      base::UTF8ToUTF16(new_title));
-  EXPECT_TRUE(ExecuteScript(web_contents, script));
-  base::string16 actual_title = title_watcher.WaitAndGetTitle();
-  EXPECT_EQ(new_title, base::UTF16ToUTF8(actual_title));
-
-  EXPECT_EQ(PrefixExpectedTabTitle(new_title), main_task->title());
-  EXPECT_EQ(PrefixExpectedTDIRowTitle(new_title), tdi_task->title());
-}
-
 }  // namespace task_manager
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 8c2420ba..b604e3f 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -380,8 +380,7 @@
       return source_.GetRepresentation(scale);
     const gfx::ImageSkiaRep& rep_100p = source_.GetRepresentation(1.0f);
     SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap(
-        rep_100p.sk_bitmap(),
-        ui::SCALE_FACTOR_100P,
+        rep_100p.GetBitmap(), ui::SCALE_FACTOR_100P,
         ui::GetSupportedScaleFactor(scale));
     return gfx::ImageSkiaRep(scaled_bitmap, scale);
   }
@@ -1604,7 +1603,7 @@
     for (ImageSkiaReps::iterator rep_it = image_reps.begin();
          rep_it != image_reps.end(); ++rep_it) {
       std::vector<unsigned char> bitmap_data;
-      if (!gfx::PNGCodec::EncodeBGRASkBitmap(rep_it->sk_bitmap(), false,
+      if (!gfx::PNGCodec::EncodeBGRASkBitmap(rep_it->GetBitmap(), false,
                                              &bitmap_data)) {
         NOTREACHED() << "Image file for resource " << it->first
                      << " could not be encoded.";
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index 51a21b6..b91e626 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -376,25 +376,25 @@
   // Scale 100%.
   const gfx::ImageSkiaRep& rep1 = image_skia->GetRepresentation(1.0f);
   ASSERT_FALSE(rep1.is_null());
-  EXPECT_EQ(80, rep1.sk_bitmap().width());
+  EXPECT_EQ(80, rep1.GetBitmap().width());
   // Bitmap height will be cropped at 60 - kTallestTabHeight + 19.
-  EXPECT_EQ(60, rep1.sk_bitmap().height());
-  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor(4, 4));
-  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor(8, 8));
-  EXPECT_EQ(SkColorSetRGB(0, 241, 237), rep1.sk_bitmap().getColor(16, 16));
-  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor(24, 24));
-  EXPECT_EQ(SkColorSetRGB(0, 241, 237), rep1.sk_bitmap().getColor(32, 32));
+  EXPECT_EQ(60, rep1.GetBitmap().height());
+  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.GetBitmap().getColor(4, 4));
+  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.GetBitmap().getColor(8, 8));
+  EXPECT_EQ(SkColorSetRGB(0, 241, 237), rep1.GetBitmap().getColor(16, 16));
+  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.GetBitmap().getColor(24, 24));
+  EXPECT_EQ(SkColorSetRGB(0, 241, 237), rep1.GetBitmap().getColor(32, 32));
   // Scale 200%.
   const gfx::ImageSkiaRep& rep2 = image_skia->GetRepresentation(2.0f);
   ASSERT_FALSE(rep2.is_null());
-  EXPECT_EQ(160, rep2.sk_bitmap().width());
+  EXPECT_EQ(160, rep2.GetBitmap().width());
   // Cropped height will be 2 * 60.
-  EXPECT_EQ(120, rep2.sk_bitmap().height());
-  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.sk_bitmap().getColor(4, 4));
-  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor(8, 8));
-  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor(16, 16));
-  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor(24, 24));
-  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.sk_bitmap().getColor(32, 32));
+  EXPECT_EQ(120, rep2.GetBitmap().height());
+  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.GetBitmap().getColor(4, 4));
+  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.GetBitmap().getColor(8, 8));
+  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.GetBitmap().getColor(16, 16));
+  EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.GetBitmap().getColor(24, 24));
+  EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.GetBitmap().getColor(32, 32));
 
   // TODO(sschmitz): I plan to remove the following (to the end of the fct)
   // Reason: this test may be brittle. It depends on details of how we scale
@@ -414,18 +414,18 @@
   // Scale 100%.
   const gfx::ImageSkiaRep& rep3 = image_skia->GetRepresentation(1.0f);
   ASSERT_FALSE(rep3.is_null());
-  EXPECT_EQ(80, rep3.sk_bitmap().width());
+  EXPECT_EQ(80, rep3.GetBitmap().width());
   // Bitmap height will be cropped at 60 - kTallestTabHeight + 19.
-  EXPECT_EQ(60, rep3.sk_bitmap().height());
+  EXPECT_EQ(60, rep3.GetBitmap().height());
   // We take samples of colors and locations along the diagonal whenever
   // the color changes. Note these colors are slightly different from
   // the input PNG file due to input processing.
   std::vector<std::pair<int, SkColor>> normal;
   int xy = 0;
-  SkColor color = rep3.sk_bitmap().getColor(xy, xy);
+  SkColor color = rep3.GetBitmap().getColor(xy, xy);
   normal.push_back(std::make_pair(xy, color));
   for (int xy = 0; xy < 40; ++xy) {
-    SkColor next_color = rep3.sk_bitmap().getColor(xy, xy);
+    SkColor next_color = rep3.GetBitmap().getColor(xy, xy);
     if (next_color != color) {
       color = next_color;
       normal.push_back(std::make_pair(xy, color));
@@ -435,15 +435,15 @@
   // Scale 200%.
   const gfx::ImageSkiaRep& rep4 = image_skia->GetRepresentation(2.0f);
   ASSERT_FALSE(rep4.is_null());
-  EXPECT_EQ(160, rep4.sk_bitmap().width());
+  EXPECT_EQ(160, rep4.GetBitmap().width());
   // Cropped height will be 2 * 60.
-  EXPECT_EQ(120, rep4.sk_bitmap().height());
+  EXPECT_EQ(120, rep4.GetBitmap().height());
   // We expect the same colors and at locations scaled by 2
   // since this bitmap was scaled by 2.
   for (size_t i = 0; i < normal.size(); ++i) {
     int xy = 2 * normal[i].first;
     SkColor color = normal[i].second;
-    EXPECT_EQ(color, rep4.sk_bitmap().getColor(xy, xy));
+    EXPECT_EQ(color, rep4.GetBitmap().getColor(xy, xy));
   }
 }
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 5e86d16f..3cf5bda 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1948,6 +1948,13 @@
       "webui/welcome/welcome_handler.h",
       "webui/welcome/welcome_ui.cc",
       "webui/welcome/welcome_ui.h",
+      # TODO(scottchen): nux/set_as_default_handler is here because it depends
+      #     on settings_default_browser_handler, but that deps currently can't
+      #     be added in nux/BUILD.gn due to circular dependency.
+      #     Should move back to nux/BUILD.gn once settings's build config is in
+      #     a shareable location (e.g. ui/webui/settings/BUILD.gn).
+      "webui/welcome/nux/set_as_default_handler.cc",
+      "webui/welcome/nux/set_as_default_handler.h",
     ]
 
     # TODO(scottchen): Remove if-check once nux files are non-exclusive
@@ -1957,7 +1964,6 @@
         "//chrome/browser/ui/webui/welcome/nux:constants",
         "//chrome/browser/ui/webui/welcome/nux:email_feature",
         "//chrome/browser/ui/webui/welcome/nux:google_apps_feature",
-        "//chrome/browser/ui/webui/welcome/nux:set_as_default_feature",
       ]
     }
 
@@ -3318,6 +3324,10 @@
         "app_list/internal_app/internal_app_metadata.h",
         "app_list/internal_app/internal_app_model_builder.cc",
         "app_list/internal_app/internal_app_model_builder.h",
+        "app_list/page_break_app_item.cc",
+        "app_list/page_break_app_item.h",
+        "app_list/page_break_constants.cc",
+        "app_list/page_break_constants.h",
         "app_list/search/arc_app_result.cc",
         "app_list/search/arc_app_result.h",
         "app_list/search/crostini_app_result.cc",
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index 8725fd62..599d0477 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -30,6 +30,8 @@
 #include "chrome/browser/ui/app_list/extension_app_item.h"
 #include "chrome/browser/ui/app_list/extension_app_model_builder.h"
 #include "chrome/browser/ui/app_list/internal_app/internal_app_model_builder.h"
+#include "chrome/browser/ui/app_list/page_break_app_item.h"
+#include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
@@ -743,6 +745,10 @@
 
 // AppListSyncableService syncer::SyncableService
 
+void AppListSyncableService::InstallDefaultPageBreaksForTest() {
+  InstallDefaultPageBreaks();
+}
+
 syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing(
     syncer::ModelType type,
     const syncer::SyncDataList& initial_sync_data,
@@ -752,6 +758,16 @@
   DCHECK(sync_processor.get());
   DCHECK(error_handler.get());
 
+  const bool first_time_user = initial_sync_data.empty();
+  if (first_time_user) {
+    // Post a task to avoid adding the default page break items which can cause
+    // sync changes during sync startup.
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AppListSyncableService::InstallDefaultPageBreaks,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
   HandleUpdateStarted();
 
   // Reset local state and recreate from sync info.
@@ -983,12 +999,12 @@
       return;
     }
     case sync_pb::AppListSpecifics::TYPE_PAGE_BREAK: {
-      std::unique_ptr<ChromeAppListItem> page_break_item =
-          std::make_unique<ChromeAppListItem>(profile_, sync_item->item_id,
-                                              model_updater_.get());
-      page_break_item->SetPosition(sync_item->item_ordinal);
-      page_break_item->SetIsPageBreak(true);
-      model_updater_->AddItem(std::move(page_break_item));
+      // This is can be either a default page break item that was installed by
+      // default for new users, or a non-default page-break item that was added
+      // by the user. the ctor of PageBreakAppItem will update the newly-created
+      // item from its |sync_item|.
+      model_updater_->AddItem(std::make_unique<PageBreakAppItem>(
+          profile_, model_updater_.get(), sync_item, sync_item->item_id));
       return;
     }
   }
@@ -1192,4 +1208,23 @@
   }
 }
 
+void AppListSyncableService::InstallDefaultPageBreaks() {
+  for (size_t i = 0; i < app_list::kDefaultPageBreakAppIdsLength; ++i) {
+    auto* const id = app_list::kDefaultPageBreakAppIds[i];
+    auto* sync_item = GetSyncItem(id);
+    if (sync_item) {
+      // The user may have cleared their sync from
+      // https://chrome.google.com/sync, so it may appear here that it's a new
+      // user, while in fact on this device, it's not. We don't want to recreate
+      // and re-add an already existing default page break item.
+      continue;
+    }
+
+    auto page_break_item = std::make_unique<PageBreakAppItem>(
+        profile(), model_updater_.get(), nullptr /* sync_item */, id);
+    page_break_item->SetName("__default_page_break__");
+    AddItem(std::move(page_break_item));
+  }
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h
index 270dce26..d3d5167 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.h
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -148,6 +148,8 @@
     return oem_folder_name_;
   }
 
+  void InstallDefaultPageBreaksForTest();
+
   const SyncItemMap& sync_items() const { return sync_items_; }
 
   // syncer::SyncableService
@@ -263,6 +265,10 @@
   // level item list.
   void PruneRedundantPageBreakItems();
 
+  // Installs the default page break items. This is only called for first time
+  // users.
+  void InstallDefaultPageBreaks();
+
   Profile* profile_;
   extensions::ExtensionSystem* extension_system_;
   std::unique_ptr<AppListModelUpdater> model_updater_;
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
index 9049e8f..bae8a59a 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
+
 #include "ash/public/cpp/app_list/app_list_config.h"
+#include "ash/public/cpp/app_list/internal_app_id_constants.h"
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/string_number_conversions.h"
@@ -12,6 +14,7 @@
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
+#include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
@@ -319,6 +322,67 @@
   EXPECT_EQ("ordinal", GetSyncItem(kItemId2)->item_ordinal.ToDebugString());
   EXPECT_EQ("pinordinal",
             GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString());
+
+  // Default page breaks are not installed for non-first time users that don't
+  // have them in their sync.
+  EXPECT_FALSE(GetSyncItem(app_list::kDefaultPageBreak1));
+}
+
+TEST_F(AppListSyncableServiceTest, ExistingDefaultPageBreak) {
+  // Non-first time users have items in their remote sync data.
+  syncer::SyncDataList sync_list;
+  sync_list.push_back(CreateAppRemoteData(
+      app_list::kDefaultPageBreak1, "page_break_1", "", "ordinal", "pinordinal",
+      sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  // Existing page break item in remote sync will be added, and its data will be
+  // updated with the item's remote sync data.
+  auto* page_break_sync_item = GetSyncItem(app_list::kDefaultPageBreak1);
+  ASSERT_TRUE(page_break_sync_item);
+  EXPECT_EQ(page_break_sync_item->item_type,
+            sync_pb::AppListSpecifics::TYPE_PAGE_BREAK);
+  EXPECT_EQ("page_break_1", page_break_sync_item->item_name);
+  EXPECT_EQ("", page_break_sync_item->parent_id);
+  EXPECT_EQ("ordinal", page_break_sync_item->item_ordinal.ToDebugString());
+  EXPECT_EQ("pinordinal",
+            page_break_sync_item->item_pin_ordinal.ToDebugString());
+}
+
+TEST_F(AppListSyncableServiceTest, DefaultPageBreakFirstTimeUser) {
+  // Empty sync list simulates a first time user.
+  syncer::SyncDataList sync_list;
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  auto* page_break_sync_item = GetSyncItem(app_list::kDefaultPageBreak1);
+  ASSERT_TRUE(page_break_sync_item);
+  EXPECT_EQ(page_break_sync_item->item_type,
+            sync_pb::AppListSpecifics::TYPE_PAGE_BREAK);
+
+  // Since internal apps are added by default, we'll use the camera and the
+  // settings apps to test the ordering.
+  auto* settings_app_sync_item = GetSyncItem(app_list::kInternalAppIdSettings);
+  auto* camera_app_sync_item = GetSyncItem(app_list::kInternalAppIdCamera);
+  ASSERT_TRUE(settings_app_sync_item);
+  ASSERT_TRUE(camera_app_sync_item);
+
+  // The default page break should be between the camera app, and the settings
+  // app; i.e. the camera app is in the first page, and the settings app is in
+  // the second page.
+  EXPECT_TRUE(page_break_sync_item->item_ordinal.LessThan(
+      settings_app_sync_item->item_ordinal));
+  EXPECT_TRUE(page_break_sync_item->item_ordinal.GreaterThan(
+      camera_app_sync_item->item_ordinal));
 }
 
 TEST_F(AppListSyncableServiceTest, InitialMerge_BadData) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index 691b026..4681e70 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -1653,8 +1653,8 @@
   // referenced app icon.
   content::RunAllTasksUntilIdle();
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.0f).sk_bitmap(),
-      delegate.image().GetRepresentation(1.0f).sk_bitmap()));
+      app_icon.GetRepresentation(1.0f).GetBitmap(),
+      delegate.image().GetRepresentation(1.0f).GetBitmap()));
 
   content::RunAllTasksUntilIdle();
   const size_t shortcut_request_count =
@@ -1679,8 +1679,8 @@
   // Validate that fetched shortcut icon for absent shortcut contains referenced
   // app icon.
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.0f).sk_bitmap(),
-      delegate.image().GetRepresentation(1.0f).sk_bitmap()));
+      app_icon.GetRepresentation(1.0f).GetBitmap(),
+      delegate.image().GetRepresentation(1.0f).GetBitmap()));
 }
 
 // Test that icon is correctly updated for suspended/non-suspended app.
@@ -1717,8 +1717,8 @@
 
   // We should have different icons.
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_normal_icon.GetRepresentation(1.0f).sk_bitmap(),
-      delegate.image().GetRepresentation(1.0f).sk_bitmap()));
+      app_normal_icon.GetRepresentation(1.0f).GetBitmap(),
+      delegate.image().GetRepresentation(1.0f).GetBitmap()));
 
   // Now switch back to normal mode.
   app.suspended = false;
@@ -1729,8 +1729,8 @@
 
   // Icon should be restored to normal
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
-      app_normal_icon.GetRepresentation(1.0f).sk_bitmap(),
-      delegate.image().GetRepresentation(1.0f).sk_bitmap()));
+      app_normal_icon.GetRepresentation(1.0f).GetBitmap(),
+      delegate.image().GetRepresentation(1.0f).GetBitmap()));
 }
 
 // If the cached icon file is corrupted, we expect send request to ARC for a new
@@ -1961,33 +1961,33 @@
   EXPECT_TRUE(app_icon.HasRepresentation(1.25f));
 
   // Keep default images for reference.
-  const SkBitmap bitmap_1_0 = app_icon.GetRepresentation(1.0f).sk_bitmap();
-  const SkBitmap bitmap_1_15 = app_icon.GetRepresentation(1.15f).sk_bitmap();
-  const SkBitmap bitmap_1_25 = app_icon.GetRepresentation(1.25f).sk_bitmap();
-  const SkBitmap bitmap_2_0 = app_icon.GetRepresentation(2.0f).sk_bitmap();
+  const SkBitmap bitmap_1_0 = app_icon.GetRepresentation(1.0f).GetBitmap();
+  const SkBitmap bitmap_1_15 = app_icon.GetRepresentation(1.15f).GetBitmap();
+  const SkBitmap bitmap_1_25 = app_icon.GetRepresentation(1.25f).GetBitmap();
+  const SkBitmap bitmap_2_0 = app_icon.GetRepresentation(2.0f).GetBitmap();
 
   delegate.WaitForIconUpdates(1);
 
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.0f).sk_bitmap(), bitmap_1_0));
+      app_icon.GetRepresentation(1.0f).GetBitmap(), bitmap_1_0));
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.15f).sk_bitmap(), bitmap_1_15));
+      app_icon.GetRepresentation(1.15f).GetBitmap(), bitmap_1_15));
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.25f).sk_bitmap(), bitmap_1_25));
+      app_icon.GetRepresentation(1.25f).GetBitmap(), bitmap_1_25));
   EXPECT_TRUE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(2.0f).sk_bitmap(), bitmap_2_0));
+      app_icon.GetRepresentation(2.0f).GetBitmap(), bitmap_2_0));
 
   // Send icon image for 200P. 2.0 and 1.25 should be updated.
   delegate.WaitForIconUpdates(1);
 
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.0f).sk_bitmap(), bitmap_1_0));
+      app_icon.GetRepresentation(1.0f).GetBitmap(), bitmap_1_0));
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.15f).sk_bitmap(), bitmap_1_15));
+      app_icon.GetRepresentation(1.15f).GetBitmap(), bitmap_1_15));
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(1.25f).sk_bitmap(), bitmap_1_25));
+      app_icon.GetRepresentation(1.25f).GetBitmap(), bitmap_1_25));
   EXPECT_FALSE(gfx::test::AreBitmapsEqual(
-      app_icon.GetRepresentation(2.0f).sk_bitmap(), bitmap_2_0));
+      app_icon.GetRepresentation(2.0f).GetBitmap(), bitmap_2_0));
 }
 
 TEST_P(ArcAppModelBuilderTest, AppLauncher) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 701edd4..804554e1 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -181,6 +181,9 @@
 
 }  // namespace
 
+const char kGoogleDuo[] = "djkcbcmkefiiphjkonbeknmcgiheajce";
+const char kInfinitePainter[] = "afihfgfghkmdmggakhkgnfhlikhdpima";
+const char kLightRoom[] = "fpegfnbgomakooccabncdaelhfppceni";
 const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei";
 const char kPlayBooksAppId[] = "cafegjnmmjpfibnlddppihpnkbkgicbg";
 const char kPlayGamesAppId[] = "nplnnjkbeijcggmpdcecpabgbjgeiedc";
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h
index 00ccb9b0c..ffa3af2a 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -23,6 +23,9 @@
 
 namespace arc {
 
+extern const char kGoogleDuo[];
+extern const char kInfinitePainter[];
+extern const char kLightRoom[];
 extern const char kPlayStoreAppId[];
 extern const char kPlayBooksAppId[];
 extern const char kPlayGamesAppId[];
diff --git a/chrome/browser/ui/app_list/md_icon_normalizer.cc b/chrome/browser/ui/app_list/md_icon_normalizer.cc
index db47140..5305a77f 100644
--- a/chrome/browser/ui/app_list/md_icon_normalizer.cc
+++ b/chrome/browser/ui/app_list/md_icon_normalizer.cc
@@ -227,7 +227,7 @@
   // First pass over representations, collect transformation parameters.
   std::vector<std::pair<gfx::Size, gfx::Size>> params;
   for (gfx::ImageSkiaRep rep : icon_out->image_reps()) {
-    const SkBitmap& bitmap = rep.sk_bitmap();
+    const SkBitmap& bitmap = rep.GetBitmap();
 
     gfx::Size required_size_px(
         static_cast<int>(required_size_dip.width() * rep.scale() + 0.5),
@@ -251,7 +251,7 @@
   gfx::ImageSkia transformed;
   int i = 0;
   for (gfx::ImageSkiaRep rep : icon_out->image_reps()) {
-    SkBitmap bitmap = rep.sk_bitmap();
+    SkBitmap bitmap = rep.GetBitmap();
     auto param = params[i++];
     MaybeResizeAndPad(param.first, param.second, &bitmap);
     transformed.AddRepresentation(gfx::ImageSkiaRep(bitmap, rep.scale()));
diff --git a/chrome/browser/ui/app_list/page_break_app_item.cc b/chrome/browser/ui/app_list/page_break_app_item.cc
new file mode 100644
index 0000000..459496c2
--- /dev/null
+++ b/chrome/browser/ui/app_list/page_break_app_item.cc
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/app_list/page_break_app_item.h"
+
+// static
+const char PageBreakAppItem::kItemType[] = "DefaultPageBreak";
+
+PageBreakAppItem::PageBreakAppItem(
+    Profile* profile,
+    AppListModelUpdater* model_updater,
+    const app_list::AppListSyncableService::SyncItem* sync_item,
+    const std::string& app_id)
+    : ChromeAppListItem(profile, app_id) {
+  SetIsPageBreak(true);
+
+  if (sync_item) {
+    DCHECK_EQ(sync_item->item_type, sync_pb::AppListSpecifics::TYPE_PAGE_BREAK);
+    if (sync_item->item_ordinal.IsValid()) {
+      UpdateFromSync(sync_item);
+      return;
+    }
+  }
+
+  SetDefaultPositionIfApplicable(model_updater);
+}
+
+PageBreakAppItem::~PageBreakAppItem() = default;
+
+// ChromeAppListItem:
+void PageBreakAppItem::Activate(int event_flags) {
+  NOTREACHED();
+}
+
+const char* PageBreakAppItem::GetItemType() const {
+  return kItemType;
+}
diff --git a/chrome/browser/ui/app_list/page_break_app_item.h b/chrome/browser/ui/app_list/page_break_app_item.h
new file mode 100644
index 0000000..03686c7
--- /dev/null
+++ b/chrome/browser/ui/app_list/page_break_app_item.h
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_APP_ITEM_H_
+#define CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_APP_ITEM_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
+
+// Represents a page break item in the app list.
+class PageBreakAppItem : public ChromeAppListItem {
+ public:
+  static const char kItemType[];
+
+  // If a page break item with ID |app_id| exists in the local sync items as
+  // |sync_item| (i.e. non-null), then this newly created item will be updated
+  // from |sync_item|.
+  PageBreakAppItem(Profile* profile,
+                   AppListModelUpdater* model_updater,
+                   const app_list::AppListSyncableService::SyncItem* sync_item,
+                   const std::string& app_id);
+  ~PageBreakAppItem() override;
+
+  // ChromeAppListItem:
+  void Activate(int event_flags) override;
+  const char* GetItemType() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PageBreakAppItem);
+};
+
+#endif  // CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_APP_ITEM_H_
diff --git a/chrome/browser/ui/app_list/page_break_constants.cc b/chrome/browser/ui/app_list/page_break_constants.cc
new file mode 100644
index 0000000..de876e3
--- /dev/null
+++ b/chrome/browser/ui/app_list/page_break_constants.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/app_list/page_break_constants.h"
+
+#include "base/stl_util.h"
+
+namespace app_list {
+
+// Generated as:
+// crx_file::id_util::GenerateId("org.chromium.default_page_break_1").
+const char kDefaultPageBreak1[] = "fdipebbchlhkdibfjgbfalhceahammim";
+
+const char* const kDefaultPageBreakAppIds[] = {
+    kDefaultPageBreak1,
+};
+
+const size_t kDefaultPageBreakAppIdsLength =
+    base::size(kDefaultPageBreakAppIds);
+
+// Returns true if |item_id| is of a default-installed page break item.
+bool IsDefaultPageBreakItem(const std::string& item_id) {
+  return base::ContainsValue(kDefaultPageBreakAppIds, item_id);
+}
+
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/page_break_constants.h b/chrome/browser/ui/app_list/page_break_constants.h
new file mode 100644
index 0000000..0850f5c
--- /dev/null
+++ b/chrome/browser/ui/app_list/page_break_constants.h
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_CONSTANTS_H_
+#define CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_CONSTANTS_H_
+
+#include <string>
+
+namespace app_list {
+
+extern const char kDefaultPageBreak1[];
+
+// List of default page break app list items that are added by default for first
+// time users. These items are added in a particular order to in
+// default_app_order.cc.
+extern const char* const kDefaultPageBreakAppIds[];
+
+extern const size_t kDefaultPageBreakAppIdsLength;
+
+// Returns true if |item_id| is of a default-installed page break item.
+bool IsDefaultPageBreakItem(const std::string& item_id);
+
+}  // namespace app_list
+
+#endif  // CHROME_BROWSER_UI_APP_LIST_PAGE_BREAK_CONSTANTS_H_
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
index 46a3a23..45e8c8ed 100644
--- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
+++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
@@ -121,8 +121,8 @@
 bool IsEqual(const gfx::ImageSkia& expected_image,
              const gfx::ImageSkia& result_image) {
   return gfx::test::AreBitmapsEqual(
-      expected_image.GetRepresentation(1.0).sk_bitmap(),
-      result_image.GetRepresentation(1.0).sk_bitmap());
+      expected_image.GetRepresentation(1.0).GetBitmap(),
+      result_image.GetRepresentation(1.0).GetBitmap());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/ash/assistant/web_contents_manager.cc b/chrome/browser/ui/ash/assistant/web_contents_manager.cc
index 4ed81ca..1334f56 100644
--- a/chrome/browser/ui/ash/assistant/web_contents_manager.cc
+++ b/chrome/browser/ui/ash/assistant/web_contents_manager.cc
@@ -52,6 +52,13 @@
   }
 
   ~ManagedWebContents() override {
+    // We may be destroying this instance before |callback_| was signaled that
+    // contents were ready for embedding. In such cases we still need to run the
+    // callback as it is an error to drop response callbacks which still
+    // correspond to an open interface pipe.
+    if (callback_)
+      std::move(callback_).Run(base::nullopt);
+
     web_contents_->SetDelegate(nullptr);
     Observe(nullptr);
 
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
index cc6ceae..f4791e8 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -10,7 +10,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/extensions/api/automation_internal/automation_event_router.h"
 #include "chrome/common/extensions/chrome_extension_messages.h"
-#include "content/public/browser/ax_event_notification_details.h"
 #include "content/public/browser/render_frame_host.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_enum_util.h"
diff --git a/chrome/browser/ui/aura/accessibility/ax_tree_source_aura.cc b/chrome/browser/ui/aura/accessibility/ax_tree_source_aura.cc
index a8ff294..f842185 100644
--- a/chrome/browser/ui/aura/accessibility/ax_tree_source_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/ax_tree_source_aura.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/ui/aura/accessibility/ax_tree_source_aura.h"
 
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
 #include "ui/accessibility/ax_tree_id.h"
 #include "ui/views/accessibility/ax_aura_obj_wrapper.h"
 #include "ui/views/accessibility/ax_view_obj_wrapper.h"
@@ -30,19 +28,8 @@
 void AXTreeSourceAura::SerializeNode(views::AXAuraObjWrapper* node,
                                      ui::AXNodeData* out_data) const {
   AXTreeSourceViews::SerializeNode(node, out_data);
-
-  if (out_data->role == ax::mojom::Role::kWebView) {
-    views::View* view = static_cast<views::AXViewObjWrapper*>(node)->view();
-    content::WebContents* contents =
-        static_cast<views::WebView*>(view)->GetWebContents();
-    content::RenderFrameHost* rfh = contents->GetMainFrame();
-    if (rfh) {
-      ui::AXTreeID ax_tree_id = rfh->GetAXTreeID();
-      out_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
-                                   ax_tree_id);
-    }
-  } else if (out_data->role == ax::mojom::Role::kWindow ||
-             out_data->role == ax::mojom::Role::kDialog) {
+  if (out_data->role == ax::mojom::Role::kWindow ||
+      out_data->role == ax::mojom::Role::kDialog) {
     // Add clips children flag by default to these roles.
     out_data->AddBoolAttribute(ax::mojom::BoolAttribute::kClipsChildren, true);
   }
diff --git a/chrome/browser/ui/cocoa/browser_window_factory_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_factory_cocoa.mm
index c10564a..20d15cd 100644
--- a/chrome/browser/ui/cocoa/browser_window_factory_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_factory_cocoa.mm
@@ -17,12 +17,3 @@
       [[BrowserWindowController alloc] initWithBrowser:browser];
   return [controller browserWindow];
 }
-
-#if !BUILDFLAG(MAC_VIEWS_BROWSER)
-// Cocoa-only builds always use Cocoa browser windows.
-// static
-BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser,
-                                                  bool user_gesture) {
-  return CreateBrowserWindowCocoa(browser, user_gesture);
-}
-#endif
diff --git a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm
index d5c7cf3..a6780f7 100644
--- a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm
+++ b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm
@@ -23,22 +23,7 @@
 #include "ui/base/ui_base_features.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
 
-namespace {
-
-enum class UiMode {
-  VIEWS,
-};
-
-std::string UiModeToString(const ::testing::TestParamInfo<UiMode>& info) {
-  return "Views";
-}
-
-}  // namespace
-
-// TODO(crbug.com/630357): Remove parameterized testing for this class.
-class PermissionBubbleInteractiveUITest
-    : public InProcessBrowserTest,
-      public ::testing::WithParamInterface<UiMode> {
+class PermissionBubbleInteractiveUITest : public InProcessBrowserTest {
  public:
   PermissionBubbleInteractiveUITest() {}
 
@@ -100,9 +85,7 @@
 };
 
 // There is only one tab. Cmd+w will close it along with the browser window.
-// TDOO(thakis): Reenable this once this test tests views.
-IN_PROC_BROWSER_TEST_P(PermissionBubbleInteractiveUITest,
-                       DISABLED_CmdWClosesWindow) {
+IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, CmdWClosesWindow) {
   base::scoped_nsobject<NSWindow> browser_window(
       browser()->window()->GetNativeWindow(), base::scoped_policy::RETAIN);
   EXPECT_TRUE([browser_window isVisible]);
@@ -120,9 +103,7 @@
 
 // Add a tab, ensure we can switch away and back using Cmd+Alt+Left/Right and
 // curly braces.
-// Disabled. See https://crbug.com/845389 - this regressed somewhere between
-// r545258 and r559030, but it may be obsolete soon.
-IN_PROC_BROWSER_TEST_P(PermissionBubbleInteractiveUITest, DISABLED_SwitchTabs) {
+IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, SwitchTabs) {
   NSWindow* browser_window = browser()->window()->GetNativeWindow();
 
   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
@@ -180,8 +161,3 @@
   EnsureWindowActive(browser_window, "switch away with curly brace");
   EXPECT_FALSE(test_api_->GetPromptWindow());
 }
-
-INSTANTIATE_TEST_CASE_P(,
-                        PermissionBubbleInteractiveUITest,
-                        ::testing::Values(UiMode::VIEWS),
-                        &UiModeToString);
diff --git a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
index 169ae90..2f7fccde 100644
--- a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
@@ -18,7 +18,6 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #import "ui/base/cocoa/focus_tracker.h"
-#include "ui/base/ui_features.h"
 
 ChromeWebContentsViewDelegateMac::ChromeWebContentsViewDelegateMac(
     content::WebContents* web_contents)
@@ -145,12 +144,3 @@
   content::RenderWidgetHostView* rwhv = GetActiveRenderWidgetHostView();
   return rwhv ? [rwhv->GetNativeView() window] : nil;
 }
-
-#if !BUILDFLAG(MAC_VIEWS_BROWSER)
-
-content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
-    content::WebContents* web_contents) {
-  return new ChromeWebContentsViewDelegateMac(web_contents);
-}
-
-#endif  // MAC_VIEWS_BROWSER
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 6f075341..104651d1 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -1528,8 +1528,7 @@
           } )";
 
 // This set of tests verifies the hosted app process model behavior in various
-// isolation modes. They can be run by default, with --site-per-process, or
-// with --top-document-isolation. In each mode, they contain an isolated origin.
+// isolation modes.
 //
 // Relevant frames in the tests:
 // - |app| - app.site.com/frame_tree/cross_origin_but_same_site_frames.html
@@ -1566,13 +1565,6 @@
     host_resolver()->AddRule("*", "127.0.0.1");
     embedded_test_server()->StartAcceptingConnections();
 
-    // TODO(alexmos): This should also be true for TDI, if
-    // base::FeatureList::IsEnabled(features::kTopDocumentIsolation) is true.
-    // However, we can't do that yet, because
-    // ChromeContentBrowserClientExtensionsPart::
-    // ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation() returns
-    // true for all hosted apps and hence forces even cross-site subframes to
-    // be kept in the app process.
     should_swap_for_cross_site_ = content::AreAllSitesIsolatedForTesting();
 
     process_map_ = extensions::ProcessMap::Get(browser()->profile());
diff --git a/chrome/browser/ui/extensions/icon_with_badge_image_source.cc b/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
index 895eac3..d3c8759b 100644
--- a/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
+++ b/chrome/browser/ui/extensions/icon_with_badge_image_source.cc
@@ -33,7 +33,7 @@
                                     float target_scale) {
   int width_px = target_width_dp * target_scale;
   return gfx::ImageSkiaRep(
-      skia::ImageOperations::Resize(rep.sk_bitmap(),
+      skia::ImageOperations::Resize(rep.GetBitmap(),
                                     skia::ImageOperations::RESIZE_BEST,
                                     width_px, width_px),
       target_scale);
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index b9880aa..1980a20 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -1118,7 +1118,7 @@
 // The only exception is if there is a global pasteboard (for example on Mac).
 // http://crbug.com/30006
 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, PreferPreviousSearch) {
-#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+#if defined(OS_MACOSX)
   if (!views_mode_controller::IsViewsBrowserCocoa()) {
     // TODO(http://crbug.com/843878): Remove the interactive UI test
     // FindBarPlatformHelperMacInteractiveUITest.PreferPreviousSearch
@@ -1476,7 +1476,7 @@
   if (!find_bar->HasGlobalFindPasteboard())
     return;
 
-#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+#if defined(OS_MACOSX)
   if (!views_mode_controller::IsViewsBrowserCocoa()) {
     // TODO(http://crbug.com/843878): Remove the interactive UI test
     // FindBarPlatformHelperMacInteractiveUITest.GlobalPasteBoardClearMatches
@@ -1566,7 +1566,7 @@
 // Find text in regular window, send IDC_FIND_NEXT to incognito. It should
 // search for the first phrase.
 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, IncognitoFindNextShared) {
-#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+#if defined(OS_MACOSX)
   if (!views_mode_controller::IsViewsBrowserCocoa()) {
     // TODO(http://crbug.com/843878): Remove the interactive UI test
     // FindBarPlatformHelperMacInteractiveUITest.IncognitoFindNextShared
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc
index e232a7c..f137c1a 100644
--- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc
+++ b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc
@@ -532,6 +532,11 @@
 }
 
 void SelectFileDialogImplGTK::OnFileChooserDestroy(GtkWidget* dialog) {
+  // There might be a case that |dialog| is already deleted
+  // in SelectFileDialogImplGTK::FileSelected.
+  // See https://crbug.com/880073.
+  if (!dialog)
+    return;
   // |parent| can be nullptr when closing the host window
   // while opening the file-picker.
   aura::Window* parent = dialogs_[dialog]->parent;
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.cc b/chrome/browser/ui/media_router/media_router_ui_base.cc
index bf08987..ab6db59bc 100644
--- a/chrome/browser/ui/media_router/media_router_ui_base.cc
+++ b/chrome/browser/ui/media_router/media_router_ui_base.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/media/router/media_router_metrics.h"
 #include "chrome/browser/media/router/media_routes_observer.h"
 #include "chrome/browser/media/router/presentation/presentation_service_delegate_impl.h"
+#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -39,12 +40,8 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/icu/source/i18n/unicode/coll.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "url/origin.h"
-
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
 #include "ui/display/display.h"
-#endif
+#include "url/origin.h"
 
 namespace media_router {
 namespace {
@@ -290,7 +287,6 @@
 }
 
 std::vector<MediaSinkWithCastModes> MediaRouterUIBase::GetEnabledSinks() const {
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   if (!display_observer_)
     return sinks_;
 
@@ -308,9 +304,6 @@
       enabled_sinks.push_back(sink);
   }
   return enabled_sinks;
-#else
-  return sinks_;
-#endif
 }
 
 std::string MediaRouterUIBase::GetTruncatedPresentationRequestSourceName()
@@ -466,11 +459,9 @@
   // information at initialization.
   OnRoutesUpdated(GetMediaRouter()->GetCurrentRoutes(),
                   std::vector<MediaRoute::Id>());
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   display_observer_ = WebContentsDisplayObserver::Create(
       initiator_, base::BindRepeating(&MediaRouterUIBase::UpdateSinks,
                                       base::Unretained(this)));
-#endif
 }
 
 void MediaRouterUIBase::OnDefaultPresentationChanged(
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.h b/chrome/browser/ui/media_router/media_router_ui_base.h
index 07e716e..424c3a0 100644
--- a/chrome/browser/ui/media_router/media_router_ui_base.h
+++ b/chrome/browser/ui/media_router/media_router_ui_base.h
@@ -23,15 +23,11 @@
 #include "chrome/browser/ui/media_router/media_router_ui_helper.h"
 #include "chrome/browser/ui/media_router/media_sink_with_cast_modes.h"
 #include "chrome/browser/ui/media_router/query_result_manager.h"
+#include "chrome/browser/ui/webui/media_router/web_contents_display_observer.h"
 #include "chrome/common/media_router/issue.h"
 #include "chrome/common/media_router/media_source.h"
-#include "ui/base/ui_features.h"
 #include "url/gurl.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/webui/media_router/web_contents_display_observer.h"
-#endif
-
 namespace content {
 struct PresentationRequest;
 class WebContents;
@@ -129,13 +125,11 @@
   const std::vector<MediaRoute>& routes() const { return routes_; }
   content::WebContents* initiator() const { return initiator_; }
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   // Used in tests for wired display presentations.
   void set_display_observer_for_test(
       std::unique_ptr<WebContentsDisplayObserver> display_observer) {
     display_observer_ = std::move(display_observer);
   }
-#endif
 
  protected:
   struct RouteRequest {
@@ -359,12 +353,10 @@
 
   std::unique_ptr<IssuesObserver> issues_observer_;
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   // Keeps track of which display the initiator WebContents is on. This is used
   // to make sure we don't show a wired display presentation over the
   // controlling window.
   std::unique_ptr<WebContentsDisplayObserver> display_observer_;
-#endif
 
   // NOTE: Weak pointers must be invalidated before all other member variables.
   // Therefore |weak_factory_| must be placed at the end.
diff --git a/chrome/browser/ui/views/chrome_typography.cc b/chrome/browser/ui/views/chrome_typography.cc
index f758552..465c280 100644
--- a/chrome/browser/ui/views/chrome_typography.cc
+++ b/chrome/browser/ui/views/chrome_typography.cc
@@ -9,12 +9,8 @@
 #include "ui/base/default_style.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/platform_font.h"
 
-// Mac doesn't use LocationBarView (yet).
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-
 int GetFontSizeDeltaBoundedByAvailableHeight(int available_height,
                                              int desired_font_size) {
   int size_delta = desired_font_size - gfx::PlatformFont::kDefaultBaseFontSize;
@@ -43,8 +39,6 @@
          user_or_locale_delta;
 }
 
-#endif  // OS_MACOSX || MAC_VIEWS_BROWSER
-
 void ApplyCommonFontStyles(int context,
                            int style,
                            int* size_delta,
@@ -61,7 +55,6 @@
       *size_delta = toolbar_button_delta;
       break;
     }
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
     case CONTEXT_OMNIBOX_PRIMARY:
     case CONTEXT_OMNIBOX_DEEMPHASIZED: {
       constexpr int kDesiredFontSizeRegular = 14;
@@ -92,7 +85,6 @@
       *size_delta = omnibox_decoration_delta;
       break;
     }
-#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
 #if defined(OS_WIN)
     case CONTEXT_WINDOWS10_NATIVE:
       // Adjusts default font size up to match Win10 modern UI.
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
index 65b1323..f72498d 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -22,7 +22,6 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_features.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/insets.h"
@@ -40,7 +39,6 @@
 
 ToolbarActionView* GetExtensionAnchorView(const std::string& extension_id,
                                           gfx::NativeWindow window) {
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   BrowserView* browser_view =
       BrowserView::GetBrowserViewForNativeWindow(window);
   if (!browser_view)
@@ -49,10 +47,6 @@
                                           ->GetBrowserActionsContainer()
                                           ->GetViewForId(extension_id);
   return reference_view && reference_view->visible() ? reference_view : nullptr;
-#else
-  // Anchoring is not supported when using Cocoa.
-  return nullptr;
-#endif  // !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 }
 
 class ExtensionUninstallDialogDelegateView;
@@ -292,8 +286,6 @@
 
 }  // namespace
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-
 // static
 extensions::ExtensionUninstallDialog*
 extensions::ExtensionUninstallDialog::Create(Profile* profile,
@@ -302,8 +294,6 @@
   return CreateViews(profile, parent, delegate);
 }
 
-#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
-
 // static
 extensions::ExtensionUninstallDialog*
 extensions::ExtensionUninstallDialog::CreateViews(Profile* profile,
diff --git a/chrome/browser/ui/views/external_protocol_dialog.cc b/chrome/browser/ui/views/external_protocol_dialog.cc
index 09f9f6d..e6e71d47 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.cc
+++ b/chrome/browser/ui/views/external_protocol_dialog.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "content/public/browser/web_contents.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/text_elider.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/label.h"
@@ -25,9 +24,6 @@
 
 using content::WebContents;
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-// This should be kept in sync with RunExternalProtocolDialogViews in
-// external_protocol_dialog_views_mac.mm.
 // static
 void ExternalProtocolHandler::RunExternalProtocolDialog(
     const GURL& url, int render_process_host_id, int routing_id,
@@ -44,7 +40,6 @@
   new ExternalProtocolDialog(std::move(delegate), render_process_host_id,
                              routing_id);
 }
-#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
 
 ExternalProtocolDialog::~ExternalProtocolDialog() {}
 
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 0cc8f7e..fa0ff31 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -31,7 +31,10 @@
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/collected_cookies_views.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/hover_button.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/page_info/chosen_object_view.h"
 #include "chrome/browser/ui/views/page_info/permission_selector_row.h"
 #include "chrome/common/url_constants.h"
@@ -45,7 +48,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/insets.h"
@@ -68,12 +70,6 @@
 #include "ui/views/widget/widget_observer.h"
 #include "url/gurl.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
-#endif
-
 #if defined(SAFE_BROWSING_DB_LOCAL)
 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
 #endif
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
index 4acbfe5..8713c700a 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -21,7 +21,6 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
@@ -194,9 +193,7 @@
           .get()));
 }
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 AccountChooserPrompt* CreateAccountChooserPromptView(
     PasswordDialogController* controller, content::WebContents* web_contents) {
   return new AccountChooserDialogView(controller, web_contents);
 }
-#endif
diff --git a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
index 0e76d0f..e4ef262c 100644
--- a/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/auto_signin_first_run_dialog_view.cc
@@ -12,7 +12,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_features.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/fill_layout.h"
@@ -108,9 +107,7 @@
   AddChildView(text.release());
 }
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 AutoSigninFirstRunPrompt* CreateAutoSigninPromptView(
     PasswordDialogController* controller, content::WebContents* web_contents) {
   return new AutoSigninFirstRunDialogView(controller, web_contents);
 }
-#endif
diff --git a/chrome/browser/ui/views/passwords/password_auto_sign_in_view.cc b/chrome/browser/ui/views/passwords/password_auto_sign_in_view.cc
index 686c4ec..f1a371eb 100644
--- a/chrome/browser/ui/views/passwords/password_auto_sign_in_view.cc
+++ b/chrome/browser/ui/views/passwords/password_auto_sign_in_view.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/passwords/password_dialog_prompts.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
@@ -17,10 +18,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/layout/fill_layout.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#endif
-
 int PasswordAutoSignInView::auto_signin_toast_timeout_ = 3;
 
 PasswordAutoSignInView::~PasswordAutoSignInView() = default;
diff --git a/chrome/browser/ui/views/passwords/password_bubble_view_base.cc b/chrome/browser/ui/views/passwords/password_bubble_view_base.cc
index 072d44a..94081d6 100644
--- a/chrome/browser/ui/views/passwords/password_bubble_view_base.cc
+++ b/chrome/browser/ui/views/passwords/password_bubble_view_base.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
 #include "chrome/browser/ui/views/passwords/password_auto_sign_in_view.h"
@@ -14,16 +15,10 @@
 #include "chrome/browser/ui/views/passwords/password_pending_view.h"
 #include "chrome/browser/ui/views/passwords/password_save_confirmation_view.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#endif
-
 // static
 PasswordBubbleViewBase* PasswordBubbleViewBase::g_manage_passwords_bubble_ =
     nullptr;
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-
 // static
 void PasswordBubbleViewBase::ShowBubble(content::WebContents* web_contents,
                                         DisplayReason reason) {
@@ -63,8 +58,6 @@
   g_manage_passwords_bubble_->ShowForReason(reason);
 }
 
-#endif  // !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-
 // static
 PasswordBubbleViewBase* PasswordBubbleViewBase::CreateBubble(
     content::WebContents* web_contents,
diff --git a/chrome/browser/ui/views/passwords/password_bubble_view_base.h b/chrome/browser/ui/views/passwords/password_bubble_view_base.h
index cac3bcab..ab9e2ef 100644
--- a/chrome/browser/ui/views/passwords/password_bubble_view_base.h
+++ b/chrome/browser/ui/views/passwords/password_bubble_view_base.h
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
-#include "ui/base/ui_features.h"
 
 namespace content {
 class WebContents;
@@ -31,12 +30,10 @@
     return g_manage_passwords_bubble_;
   }
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   // Shows an appropriate bubble on the toolkit-views Browser window containing
   // |web_contents|.
   static void ShowBubble(content::WebContents* web_contents,
                          DisplayReason reason);
-#endif
   // Creates and returns the passwords manager bubble UI appropriate for the
   // current password_manager::ui::State value for the provided |web_contents|.
   static PasswordBubbleViewBase* CreateBubble(
diff --git a/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
index e610542d..97b0ba26 100644
--- a/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
@@ -344,7 +344,7 @@
       "    phone: 'PHONE ERROR'"
       "  }"
       "}",
-      DialogEvent::CONTACT_INFO_EDITOR_OPENED);
+      DialogEvent::CONTACT_INFO_EDITOR_OPENED, dialog_view());
 
   EXPECT_EQ(base::ASCIIToUTF16("EMAIL ERROR"),
             GetErrorLabelForType(autofill::EMAIL_ADDRESS));
@@ -381,7 +381,7 @@
       "    phone: 'PHONE ERROR'"
       "  }"
       "}",
-      DialogEvent::CONTACT_INFO_EDITOR_OPENED);
+      DialogEvent::CONTACT_INFO_EDITOR_OPENED, dialog_view());
 
   EXPECT_EQ(base::ASCIIToUTF16("EMAIL ERROR"),
             GetErrorLabelForType(autofill::EMAIL_ADDRESS));
@@ -411,7 +411,8 @@
       "    name: 'NAME ERROR',"
       "    phone: 'PHONE ERROR'"
       "  }"
-      "}");
+      "}",
+      dialog_view());
 
   const int kErrorLabelOffset =
       static_cast<int>(DialogViewID::ERROR_LABEL_OFFSET);
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc b/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc
index 1da36bc3..97b14877 100644
--- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc
+++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc
@@ -638,10 +638,13 @@
 }
 
 void PaymentRequestBrowserTestBase::RetryPaymentRequest(
-    const std::string& validation_errors) {
-  ResetEventWaiterForSequence(
-      {DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::SPEC_DONE_UPDATING,
-       DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED});
+    const std::string& validation_errors,
+    PaymentRequestDialogView* dialog_view) {
+  EXPECT_EQ(2U, dialog_view->view_stack_for_testing()->size());
+  ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_HIDDEN,
+                               DialogEvent::SPEC_DONE_UPDATING,
+                               DialogEvent::PROCESSING_SPINNER_HIDDEN,
+                               DialogEvent::BACK_TO_PAYMENT_SHEET_NAVIGATION});
 
   ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(),
                                      "retry(" + validation_errors + ");"));
@@ -651,11 +654,13 @@
 
 void PaymentRequestBrowserTestBase::RetryPaymentRequest(
     const std::string& validation_errors,
-    const DialogEvent& dialog_event) {
+    const DialogEvent& dialog_event,
+    PaymentRequestDialogView* dialog_view) {
+  EXPECT_EQ(2U, dialog_view->view_stack_for_testing()->size());
   ResetEventWaiterForSequence(
       {DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::SPEC_DONE_UPDATING,
-       DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED,
-       dialog_event});
+       DialogEvent::PROCESSING_SPINNER_HIDDEN,
+       DialogEvent::BACK_TO_PAYMENT_SHEET_NAVIGATION, dialog_event});
 
   ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(),
                                      "retry(" + validation_errors + ");"));
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
index 43b9a5c..09dfb02 100644
--- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
+++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
@@ -209,9 +209,11 @@
   void PayWithCreditCardAndWait(const base::string16& cvc,
                                 PaymentRequestDialogView* dialog_view);
   void PayWithCreditCard(const base::string16& cvc);
-  void RetryPaymentRequest(const std::string& validation_errors);
   void RetryPaymentRequest(const std::string& validation_errors,
-                           const DialogEvent& dialog_event);
+                           PaymentRequestDialogView* dialog_view);
+  void RetryPaymentRequest(const std::string& validation_errors,
+                           const DialogEvent& dialog_event,
+                           PaymentRequestDialogView* dialog_view);
 
   // Getting/setting the |value| in the textfield of a given |type|.
   base::string16 GetEditorTextfieldValue(autofill::ServerFieldType type);
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
index 2230ad9..b6d7c21 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -189,7 +189,7 @@
 
 void PaymentRequestDialogView::RetryDialog() {
   HideProcessingSpinner();
-  ShowInitialPaymentSheet();
+  GoBackToPaymentSheet();
 
   if (request_->spec()->has_shipping_address_error()) {
     autofill::AutofillProfile* profile =
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
index 74e26cde..e5545ca1 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc
@@ -1286,7 +1286,7 @@
       "    city: 'CITY ERROR'"
       "  }"
       "}",
-      DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED);
+      DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED, dialog_view());
 
   EXPECT_EQ(base::ASCIIToUTF16("ADDRESS LINE ERROR"),
             GetErrorLabelForType(autofill::ADDRESS_HOME_STREET_ADDRESS));
@@ -1322,7 +1322,7 @@
       "    city: 'CITY ERROR'"
       "  }"
       "}",
-      DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED);
+      DialogEvent::SHIPPING_ADDRESS_EDITOR_OPENED, dialog_view());
 
   EXPECT_EQ(base::ASCIIToUTF16("ADDRESS LINE ERROR"),
             GetErrorLabelForType(autofill::ADDRESS_HOME_STREET_ADDRESS));
@@ -1349,7 +1349,8 @@
       "    addressLine: 'ADDRESS LINE ERROR',"
       "    city: 'CITY ERROR'"
       "  }"
-      "}");
+      "}",
+      dialog_view());
 
   const int kErrorLabelOffset =
       static_cast<int>(DialogViewID::ERROR_LABEL_OFFSET);
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index c97290a..7dafa03d 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -751,6 +751,7 @@
     dice_accounts_menu_->Show(sender, sync_to_another_account_button_);
   } else if (sender == signout_button_) {
     SignOutAllWebAccounts();
+    base::RecordAction(base::UserMetricsAction("Signin_Signout_FromUserMenu"));
   } else {
     // Either one of the "other profiles", or one of the profile accounts
     // buttons was pressed.
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc
index 69d6bf72..a5dcee2 100644
--- a/chrome/browser/ui/views/simple_message_box_views.cc
+++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -21,7 +21,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/message_box_view.h"
 #include "ui/views/widget/widget.h"
@@ -277,7 +276,6 @@
 
 namespace chrome {
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 void ShowWarningMessageBox(gfx::NativeWindow parent,
                            const base::string16& title,
                            const base::string16& message) {
@@ -322,6 +320,4 @@
                                      yes_text, no_text, base::string16());
 }
 
-#endif  // !OS_MACOSX || BUILDFLAG(MAC_VIEWS_BROWSER)
-
 }  // namespace chrome
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index fca29e0f..694dad3 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
+#include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/constrained_window/constrained_window_views.h"
@@ -26,7 +27,6 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_features.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/native_widget_types.h"
@@ -44,10 +44,6 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_client_view.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
-#endif
-
 ProfileSigninConfirmationDialogViews::ProfileSigninConfirmationDialogViews(
     Browser* browser,
     const std::string& username,
@@ -68,7 +64,6 @@
     Profile* profile,
     const std::string& username,
     std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) {
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   // Hides the new avatar bubble if it is currently shown. The new avatar bubble
   // should be automatically closed when it loses focus. However on windows the
   // profile signin confirmation dialog is not modal yet thus it does not take
@@ -77,7 +72,6 @@
   // TODO(guohui): removes the workaround once the profile confirmation dialog
   // is fixed.
   ProfileChooserView::Hide();
-#endif
 
   ProfileSigninConfirmationDialogViews* dialog =
       new ProfileSigninConfirmationDialogViews(browser, username,
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
index 07d8134..d113eba 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
@@ -8,7 +8,6 @@
 #include "chrome/browser/ui/views/sad_tab_view.h"
 #include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h"
 #include "content/public/browser/web_contents.h"
-#include "ui/base/ui_features.h"
 #include "ui/views/widget/widget.h"
 
 ChromeWebContentsViewDelegateViewsMac::ChromeWebContentsViewDelegateViewsMac(
@@ -50,11 +49,7 @@
   return GetFocusHelper()->TakeFocus(reverse);
 }
 
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
-
 content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
     content::WebContents* web_contents) {
   return new ChromeWebContentsViewDelegateViewsMac(web_contents);
 }
-
-#endif  // MAC_VIEWS_BROWSER
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc
index fe20379..3ede94a 100644
--- a/chrome/browser/ui/views/toolbar/app_menu.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -399,7 +399,7 @@
 
   gfx::ImageSkiaRep GetImageForScale(float scale) override {
     const gfx::ImageSkiaRep& rep = image_.GetRepresentation(scale);
-    SkBitmap bitmap = rep.sk_bitmap();
+    SkBitmap bitmap = rep.GetBitmap();
     SkBitmap white;
     white.allocN32Pixels(bitmap.width(), bitmap.height());
     white.eraseARGB(0, 0, 0, 0);
diff --git a/chrome/browser/ui/views_mode_controller.cc b/chrome/browser/ui/views_mode_controller.cc
index ffe958a..289e8ca2 100644
--- a/chrome/browser/ui/views_mode_controller.cc
+++ b/chrome/browser/ui/views_mode_controller.cc
@@ -7,7 +7,7 @@
 #include "base/feature_list.h"
 #include "ui/base/ui_base_features.h"
 
-#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+#if defined(OS_MACOSX)
 
 namespace views_mode_controller {
 
diff --git a/chrome/browser/ui/views_mode_controller.h b/chrome/browser/ui/views_mode_controller.h
index f9833125..ccbb148b 100644
--- a/chrome/browser/ui/views_mode_controller.h
+++ b/chrome/browser/ui/views_mode_controller.h
@@ -7,9 +7,8 @@
 
 #include "build/build_config.h"
 #include "build/buildflag.h"
-#include "ui/base/ui_features.h"
 
-#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+#if defined(OS_MACOSX)
 
 namespace views_mode_controller {
 
diff --git a/chrome/browser/ui/webui/chromeos/user_image_source.cc b/chrome/browser/ui/webui/chromeos/user_image_source.cc
index dc12be0..1702ebc2 100644
--- a/chrome/browser/ui/webui/chromeos/user_image_source.cc
+++ b/chrome/browser/ui/webui/chromeos/user_image_source.cc
@@ -80,7 +80,7 @@
       ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
   float scale = ui::GetScaleForScaleFactor(scale_factor);
   scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes);
-  gfx::PNGCodec::EncodeBGRASkBitmap(image->GetRepresentation(scale).sk_bitmap(),
+  gfx::PNGCodec::EncodeBGRASkBitmap(image->GetRepresentation(scale).GetBitmap(),
                                     false /* discard transparency */,
                                     &data->data());
   return data;
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc
index da3b8a6..a7d16dd 100644
--- a/chrome/browser/ui/webui/fileicon_source.cc
+++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -103,8 +103,7 @@
   if (icon) {
     scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
     gfx::PNGCodec::EncodeBGRASkBitmap(
-        icon->ToImageSkia()->GetRepresentation(scale_factor).sk_bitmap(),
-        false,
+        icon->ToImageSkia()->GetRepresentation(scale_factor).GetBitmap(), false,
         &icon_data->data());
 
     callback.Run(icon_data.get());
@@ -154,10 +153,10 @@
   if (icon) {
     scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes);
     gfx::PNGCodec::EncodeBGRASkBitmap(
-        icon->ToImageSkia()->GetRepresentation(
-            details.scale_factor).sk_bitmap(),
-        false,
-        &icon_data->data());
+        icon->ToImageSkia()
+            ->GetRepresentation(details.scale_factor)
+            .GetBitmap(),
+        false, &icon_data->data());
 
     details.callback.Run(icon_data.get());
   } else {
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 6d51033..d37ffb06 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -330,6 +330,8 @@
       threat_type = safe_browsing::SB_THREAT_TYPE_URL_PHISHING;
     } else if (type_param == "unwanted") {
       threat_type = safe_browsing::SB_THREAT_TYPE_URL_UNWANTED;
+    } else if (type_param == "billing") {
+      threat_type = safe_browsing::SB_THREAT_TYPE_BILLING;
     } else if (type_param == "giant") {
       threat_type = safe_browsing::SB_THREAT_TYPE_URL_MALWARE;
       is_giant_webview = true;
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
index 22fdd471..0543042cb 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
@@ -124,6 +124,12 @@
       "Security error");
 }
 
+IN_PROC_BROWSER_TEST_F(InterstitialUITest, BillingInterstitialQuiet) {
+  TestInterstitial(
+      GURL("chrome://interstitials/quietsafebrowsing?type=billing"),
+      "Security error");
+}
+
 IN_PROC_BROWSER_TEST_F(InterstitialUITest, ClientsideMalwareInterstitial) {
   TestInterstitial(
       GURL("chrome://interstitials/safebrowsing?type=clientside_malware"),
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc
index eb30f9b..5c6001c2 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/media_router_metrics.h"
 #include "chrome/browser/media/router/media_sinks_observer.h"
+#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -52,14 +53,10 @@
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/display/display.h"
 #include "ui/web_dialogs/web_dialog_delegate.h"
 #include "url/origin.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
-#include "ui/display/display.h"
-#endif
-
 namespace media_router {
 
 MediaRouterUI::MediaRouterUI(content::WebUI* web_ui)
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
index 6847cd7..4db9b29 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_unittest.cc
@@ -11,12 +11,14 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/media/router/media_router_factory.h"
+#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
 #include "chrome/browser/media/router/test/media_router_mojo_test.h"
 #include "chrome/browser/media/router/test/mock_media_router.h"
 #include "chrome/browser/media/router/test/test_helper.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/media_router/media_router_ui_helper.h"
 #include "chrome/browser/ui/webui/media_router/media_router_webui_message_handler.h"
+#include "chrome/browser/ui/webui/media_router/web_contents_display_observer.h"
 #include "chrome/common/media_router/media_route.h"
 #include "chrome/common/media_router/media_source_helper.h"
 #include "chrome/common/media_router/mojo/media_router.mojom.h"
@@ -33,12 +35,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
-
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/media/router/providers/wired_display/wired_display_media_route_provider.h"
-#include "chrome/browser/ui/webui/media_router/web_contents_display_observer.h"
 #include "ui/display/display.h"
-#endif
 
 using content::WebContents;
 using testing::_;
@@ -82,7 +79,6 @@
   MOCK_METHOD1(OpenFileDialog, void(Browser* browser));
 };
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 class TestWebContentsDisplayObserver : public WebContentsDisplayObserver {
  public:
   explicit TestWebContentsDisplayObserver(const display::Display& display)
@@ -98,7 +94,6 @@
  private:
   display::Display display_;
 };
-#endif  // !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 
 class PresentationRequestCallbacks {
  public:
@@ -801,7 +796,6 @@
   media_router_ui_.reset();
 }
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 // A wired display sink should not be on the sinks list when the dialog is on
 // that display, to prevent showing a fullscreen presentation window over the
 // controlling window.
@@ -862,6 +856,5 @@
   display_observer->set_display(display2);
   media_router_ui_->UpdateSinks();
 }
-#endif  // !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 
 }  // namespace media_router
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index b002a3f3..1c7cc2d 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -523,9 +523,18 @@
                                  Profile* profile) {
   LocalizedString localized_strings[] = {
       {"clearTimeRange", IDS_SETTINGS_CLEAR_PERIOD_TITLE},
+      {"clearBrowsingDataWithSync", IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC},
+      {"clearBrowsingDataWithSyncError",
+       IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_ERROR},
+      {"clearBrowsingDataWithSyncPassphraseError",
+       IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_PASSPHRASE_ERROR},
+      {"clearBrowsingDataWithSyncPaused",
+       IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_PAUSED},
       {"clearBrowsingHistory", IDS_SETTINGS_CLEAR_BROWSING_HISTORY},
       {"clearBrowsingHistorySummary",
        IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY},
+      {"clearBrowsingHistorySummarySignedIn",
+       IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNC_ERROR},
       {"clearDownloadHistory", IDS_SETTINGS_CLEAR_DOWNLOAD_HISTORY},
       {"clearCache", IDS_SETTINGS_CLEAR_CACHE},
       {"clearCookies", IDS_SETTINGS_CLEAR_COOKIES},
@@ -551,11 +560,6 @@
   };
 
   html_source->AddString(
-      "clearBrowsingHistorySummarySignedIn",
-      l10n_util::GetStringFUTF16(
-          IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SIGNED_IN,
-          base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData)));
-  html_source->AddString(
       "clearBrowsingHistorySummarySynced",
       l10n_util::GetStringFUTF16(
           IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED,
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index fa6dd8d8..769ed65e 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -244,7 +244,7 @@
       std::make_unique<chromeos::settings::InternetHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<TtsHandler>());
 #else
-  AddSettingsPageUIHandler(std::make_unique<DefaultBrowserHandler>(web_ui));
+  AddSettingsPageUIHandler(std::make_unique<DefaultBrowserHandler>());
   AddSettingsPageUIHandler(std::make_unique<ManageProfileHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<SystemHandler>());
 #endif
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
index 8805b9b..8c34895 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -30,9 +30,7 @@
 
 }  // namespace
 
-DefaultBrowserHandler::DefaultBrowserHandler(content::WebUI* webui)
-    : weak_ptr_factory_(this) {
-}
+DefaultBrowserHandler::DefaultBrowserHandler() : weak_ptr_factory_(this) {}
 
 DefaultBrowserHandler::~DefaultBrowserHandler() {}
 
@@ -74,9 +72,8 @@
 
 void DefaultBrowserHandler::SetAsDefaultBrowser(const base::ListValue* args) {
   CHECK(!DefaultBrowserIsDisabledByPolicy());
-
-  base::RecordAction(base::UserMetricsAction("Options_SetAsDefaultBrowser"));
-  UMA_HISTOGRAM_COUNTS_1M("Settings.StartSetAsDefault", true);
+  AllowJavascript();
+  RecordSetAsDefaultUMA();
 
   default_browser_worker_->StartSetAsDefault();
 
@@ -85,6 +82,11 @@
   ResetDefaultBrowserPrompt(Profile::FromWebUI(web_ui()));
 }
 
+void DefaultBrowserHandler::RecordSetAsDefaultUMA() {
+  base::RecordAction(base::UserMetricsAction("Options_SetAsDefaultBrowser"));
+  UMA_HISTOGRAM_COUNTS("Settings.StartSetAsDefault", true);
+}
+
 void DefaultBrowserHandler::OnDefaultBrowserWorkerFinished(
     shell_integration::DefaultWebClientState state) {
   if (state == shell_integration::IS_DEFAULT) {
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
index cc2f4ec..81337dc 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
@@ -27,7 +27,7 @@
 // settings code to change the default browser settings.
 class DefaultBrowserHandler : public SettingsPageUIHandler {
  public:
-  explicit DefaultBrowserHandler(content::WebUI* webui);
+  DefaultBrowserHandler();
   ~DefaultBrowserHandler() override;
 
   // SettingsPageUIHandler implementation.
@@ -35,6 +35,10 @@
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
 
+ protected:
+  // Subclasses should override this method.
+  virtual void RecordSetAsDefaultUMA();
+
  private:
   // Called from WebUI to request the current state.
   void RequestDefaultBrowserState(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index 921e6dd..57f91e6 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -51,7 +51,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale);
   gfx::PNGCodec::EncodeBGRASkBitmap(
-      rep.sk_bitmap(), false /* discard transparency */, &data->data());
+      rep.GetBitmap(), false /* discard transparency */, &data->data());
 }
 
 void ProcessResourceOnUiThread(int resource_id,
diff --git a/chrome/browser/ui/webui/welcome/nux/BUILD.gn b/chrome/browser/ui/webui/welcome/nux/BUILD.gn
index 5aae5db..718b6efc 100644
--- a/chrome/browser/ui/webui/welcome/nux/BUILD.gn
+++ b/chrome/browser/ui/webui/welcome/nux/BUILD.gn
@@ -4,94 +4,69 @@
 
 import("//build/config/chrome_build.gni")
 
-if (is_win && is_chrome_branded) {
-  static_library("set_as_default_feature") {
-    sources = [
-      "set_as_default_handler.cc",
-      "set_as_default_handler.h",
-    ]
+source_set("constants") {
+  sources = [
+    "constants.cc",
+    "constants.h",
+  ]
 
-    public_deps = [
-      "//base",
-      "//net",
-      "//url",
-    ]
+  public_deps = [
+    "//base",
+  ]
+}
 
-    deps = [
-      "//chrome/app:generated_resources",
-      "//chrome/browser:resources",
-      "//components/resources",
-      "//components/strings",
-      "//components/variations",
-      "//content/public/browser",
-      "//ui/base",
-    ]
-  }
+static_library("email_feature") {
+  sources = [
+    "email_handler.cc",
+    "email_handler.h",
+  ]
 
-  source_set("constants") {
-    sources = [
-      "constants.cc",
-      "constants.h",
-    ]
+  public_deps = [
+    "//base",
+    "//net",
+    "//url",
+  ]
 
-    public_deps = [
-      "//base",
-    ]
-  }
+  deps = [
+    "//chrome/app:generated_resources",
+    "//chrome/browser:resources",
+    "//components/bookmarks/browser",
+    "//components/bookmarks/common",
+    "//components/favicon/core",
+    "//components/pref_registry",
+    "//components/prefs",
+    "//components/resources",
+    "//components/strings",
+    "//components/variations",
+    "//content/public/browser",
+    "//ui/base",
+  ]
+}
 
-  static_library("email_feature") {
-    sources = [
-      "email_handler.cc",
-      "email_handler.h",
-    ]
+static_library("google_apps_feature") {
+  sources = [
+    "google_apps_handler.cc",
+    "google_apps_handler.h",
+  ]
 
-    public_deps = [
-      "//base",
-      "//net",
-      "//url",
-    ]
+  public_deps = [
+    "//base",
+    "//net",
+    "//url",
+  ]
 
-    deps = [
-      "//chrome/app:generated_resources",
-      "//chrome/browser:resources",
-      "//components/bookmarks/browser",
-      "//components/bookmarks/common",
-      "//components/favicon/core",
-      "//components/pref_registry",
-      "//components/prefs",
-      "//components/resources",
-      "//components/strings",
-      "//components/variations",
-      "//content/public/browser",
-      "//ui/base",
-    ]
-  }
-
-  static_library("google_apps_feature") {
-    sources = [
-      "google_apps_handler.cc",
-      "google_apps_handler.h",
-    ]
-
-    public_deps = [
-      "//base",
-      "//net",
-      "//url",
-    ]
-
-    deps = [
-      "//chrome/app:generated_resources",
-      "//chrome/browser:resources",
-      "//components/bookmarks/browser",
-      "//components/bookmarks/common",
-      "//components/favicon/core",
-      "//components/pref_registry",
-      "//components/prefs",
-      "//components/resources",
-      "//components/strings",
-      "//components/variations",
-      "//content/public/browser",
-      "//ui/base",
-    ]
-  }
+  deps = [
+    "//chrome/app:generated_resources",
+    "//chrome/browser:resources",
+    "//components/bookmarks/browser",
+    "//components/bookmarks/common",
+    "//components/favicon/core",
+    "//components/pref_registry",
+    "//components/prefs",
+    "//components/resources",
+    "//components/strings",
+    "//components/variations",
+    "//content/public/browser",
+    "//ui/base",
+  ]
 }
diff --git a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
index d153e238..88ea473b 100644
--- a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
+++ b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
@@ -4,28 +4,24 @@
 
 #include "chrome/browser/ui/webui/welcome/nux/set_as_default_handler.h"
 
-#include "base/bind.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/grit/components_resources.h"
-#include "components/grit/components_scaled_resources.h"
 #include "components/strings/grit/components_strings.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
-#include "ui/base/resource/resource_bundle.h"
 
 namespace nux {
 
-SetAsDefaultHandler::SetAsDefaultHandler() {}
+SetAsDefaultHandler::SetAsDefaultHandler()
+    : settings::DefaultBrowserHandler() {}
 
 SetAsDefaultHandler::~SetAsDefaultHandler() {}
 
-void SetAsDefaultHandler::RegisterMessages() {}
+void SetAsDefaultHandler::RecordSetAsDefaultUMA() {
+  // TODO(scottchen): Add UMA tracking.
+}
 
 void SetAsDefaultHandler::AddSources(content::WebUIDataSource* html_source) {
   // Localized strings.
diff --git a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.h b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.h
index cb15edae..9621e65 100644
--- a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.h
+++ b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.h
@@ -6,8 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_WELCOME_NUX_SET_AS_DEFAULT_HANDLER_H_
 
 #include "base/macros.h"
-#include "base/values.h"
-#include "content/public/browser/web_ui_message_handler.h"
+#include "chrome/browser/ui/webui/settings/settings_default_browser_handler.h"
 
 namespace content {
 class WebUIDataSource;
@@ -15,17 +14,17 @@
 
 namespace nux {
 
-class SetAsDefaultHandler : public content::WebUIMessageHandler {
+class SetAsDefaultHandler : public settings::DefaultBrowserHandler {
  public:
   SetAsDefaultHandler();
   ~SetAsDefaultHandler() override;
 
-  // WebUIMessageHandler:
-  void RegisterMessages() override;
-
   // Adds webui sources.
   static void AddSources(content::WebUIDataSource* html_source);
 
+ protected:
+  void RecordSetAsDefaultUMA() override;
+
   DISALLOW_COPY_AND_ASSIGN(SetAsDefaultHandler);
 };
 
diff --git a/chrome/browser/vr/service/isolated_device_provider.cc b/chrome/browser/vr/service/isolated_device_provider.cc
index 2ca3095..47f7943 100644
--- a/chrome/browser/vr/service/isolated_device_provider.cc
+++ b/chrome/browser/vr/service/isolated_device_provider.cc
@@ -24,6 +24,9 @@
       device::mojom::kVrIsolatedServiceName,
       mojo::MakeRequest(&device_provider_));
 
+  device_provider_.set_connection_error_handler(base::BindOnce(
+      &IsolatedVRDeviceProvider::OnServerError, base::Unretained(this)));
+
   device::mojom::IsolatedXRRuntimeProviderClientPtr client;
   binding_.Bind(mojo::MakeRequest(&client));
   device_provider_->RequestDevices(std::move(client));
@@ -43,22 +46,40 @@
     device::mojom::VRDisplayInfoPtr display_info) {
   device::mojom::XRDeviceId id = display_info->id;
   add_device_callback_.Run(id, std::move(display_info), std::move(device));
-
 #if BUILDFLAG(ENABLE_OPENVR) || BUILDFLAG(ENABLE_OCULUS_VR)
   registered_gamepads_.insert(id);
   device::IsolatedGamepadDataFetcher::Factory::AddGamepad(
       id, std::move(gamepad_factory));
 #endif
+  added_devices_.insert(id);
 }
 
 void IsolatedVRDeviceProvider::OnDeviceRemoved(device::mojom::XRDeviceId id) {
   remove_device_callback_.Run(id);
+  added_devices_.erase(id);
 
 #if BUILDFLAG(ENABLE_OPENVR) || BUILDFLAG(ENABLE_OCULUS_VR)
   device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id);
 #endif
 }
 
+void IsolatedVRDeviceProvider::OnServerError() {
+  // An error occurred - any devices we have added are now disconnected and
+  // should be removed.
+  for (auto id : added_devices_) {
+    remove_device_callback_.Run(id);
+  }
+  added_devices_.clear();
+
+  // At this point, XRRuntimeManager may be blocked waiting for us to return
+  // that we've enumerated all runtimes/devices.  If we lost the connection to
+  // the service, we won't ever get devices, so report we are done now.
+  // This will unblock WebXR/WebVR promises so they can reject indicating we
+  // never found devices.
+  if (!initialized_)
+    OnDevicesEnumerated();
+}
+
 void IsolatedVRDeviceProvider::OnDevicesEnumerated() {
   initialized_ = true;
   std::move(initialization_complete_).Run();
diff --git a/chrome/browser/vr/service/isolated_device_provider.h b/chrome/browser/vr/service/isolated_device_provider.h
index ad059d19..5d91bd1c 100644
--- a/chrome/browser/vr/service/isolated_device_provider.h
+++ b/chrome/browser/vr/service/isolated_device_provider.h
@@ -39,6 +39,7 @@
       device::mojom::VRDisplayInfoPtr display_info) override;
   void OnDeviceRemoved(device::mojom::XRDeviceId id) override;
   void OnDevicesEnumerated() override;
+  void OnServerError();
 
   bool initialized_ = false;
   device::mojom::IsolatedXRRuntimeProviderPtr device_provider_;
@@ -51,6 +52,7 @@
       remove_device_callback_;
   base::OnceClosure initialization_complete_;
   std::set<device::mojom::XRDeviceId> registered_gamepads_;
+  std::set<device::mojom::XRDeviceId> added_devices_;
   mojo::Binding<device::mojom::IsolatedXRRuntimeProviderClient> binding_;
 };
 
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 46119cf..0f6fd2c 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -72,8 +72,11 @@
 
 AuthenticatorRequestDialogModel::AuthenticatorReference::AuthenticatorReference(
     base::StringPiece authenticator_id,
+    base::StringPiece16 authenticator_display_name,
     device::FidoTransportProtocol transport)
-    : authenticator_id(authenticator_id), transport(transport) {}
+    : authenticator_id(authenticator_id),
+      authenticator_display_name(authenticator_display_name),
+      transport(transport) {}
 AuthenticatorRequestDialogModel::AuthenticatorReference::AuthenticatorReference(
     AuthenticatorReference&& data) = default;
 AuthenticatorRequestDialogModel::AuthenticatorReference&
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index 18311d5..70e42e9 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -10,6 +10,7 @@
 
 #include "base/observer_list.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/webauthn/authenticator_transport.h"
 #include "chrome/browser/webauthn/transport_list_model.h"
@@ -72,11 +73,13 @@
     kCableActivate,
   };
 
-  // Encapsulates information about authenticators that have been found but are
-  // in inactive state because we want to dispatch the requests after receiving
-  // confirmation from the user via the WebAuthN UI flow.
+  // Encapsulates information about authenticators that have been found and
+  // whose request is controlled by the UI embedder because we want to dispatch
+  // the requests after receiving confirmation from the user via the WebAuthN UI
+  // flow.
   struct AuthenticatorReference {
     AuthenticatorReference(base::StringPiece device_id,
+                           base::StringPiece16 authenticator_display_name,
                            device::FidoTransportProtocol transport);
     AuthenticatorReference(AuthenticatorReference&& data);
     AuthenticatorReference& operator=(AuthenticatorReference&& other);
@@ -84,6 +87,7 @@
     ~AuthenticatorReference();
 
     std::string authenticator_id;
+    base::string16 authenticator_display_name;
     device::FidoTransportProtocol transport;
     bool dispatched = false;
   };
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
index 209d1dd..b6500ac 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -474,7 +474,9 @@
       &num_called));
   model.saved_authenticators().emplace_back(
       AuthenticatorRequestDialogModel::AuthenticatorReference(
-          "authenticator", AuthenticatorTransport::kInternal));
+          "authenticator" /* authenticator_id */,
+          base::string16() /* authenticator_display_name */,
+          AuthenticatorTransport::kInternal));
 
   model.StartFlow(std::move(transports_info), base::nullopt);
   EXPECT_EQ(AuthenticatorRequestDialogModel::Step::kTransportSelection,
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 67123fc..859a37a 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -300,7 +300,8 @@
     return;
 
   weak_dialog_model_->saved_authenticators().emplace_back(
-      authenticator.GetId(), authenticator.AuthenticatorTransport());
+      authenticator.GetId(), authenticator.GetDisplayName(),
+      authenticator.AuthenticatorTransport());
 }
 
 void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorRemoved(
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index f1ec10f2..63aeb0f 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -131,7 +131,7 @@
       gfx::ImageSkiaRep image_skia_rep = image_skia.GetRepresentation(scale);
       if (!image_skia_rep.is_null()) {
         image_family.Add(
-            gfx::Image::CreateFrom1xBitmap(image_skia_rep.sk_bitmap()));
+            gfx::Image::CreateFrom1xBitmap(image_skia_rep.GetBitmap()));
       }
     }
   }
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index d6cb69e..d93b738 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -99,7 +99,7 @@
 // Registers Widevine CDM if Widevine is enabled, the Widevine CDM is
 // bundled and not a component. When the Widevine CDM is a component, it is
 // registered in widevine_cdm_component_installer.cc.
-#if BUILDFLAG(SHOULD_BUNDLE_WIDEVINE_CDM) && !BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
+#if BUILDFLAG(BUNDLE_WIDEVINE_CDM) && !BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
 #define REGISTER_BUNDLED_WIDEVINE_CDM
 #include "third_party/widevine/cdm/widevine_cdm_common.h"  // nogncheck
 // TODO(crbug.com/663554): Needed for WIDEVINE_CDM_VERSION_STRING. Support
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index 4ac4a30..cec51216 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -12,8 +12,9 @@
 import("//build/util/version.gni")
 import("//chrome/process_version_rc_template.gni")  # For branding_file_path.
 import("//components/nacl/features.gni")
+import("//third_party/widevine/cdm/widevine.gni")
 
-if (current_cpu == "x86" || current_cpu == "x64") {
+if (bundle_widevine_cdm) {
   import("//media/cdm/library_cdm/cdm_paths.gni")
 }
 
@@ -48,8 +49,7 @@
   }
 }
 
-# The widevine BUILD.gn only produces shared libraries for x86 and x64
-if (is_chrome_branded && (current_cpu == "x86" || current_cpu == "x64")) {
+if (bundle_widevine_cdm) {
   packaging_files_shlibs +=
       [ "$root_out_dir/$widevine_cdm_path/libwidevinecdm.so" ]
 }
@@ -364,7 +364,7 @@
       "//ppapi/native_client:irt",
     ]
   }
-  if (current_cpu == "x86" || current_cpu == "x64") {
+  if (bundle_widevine_cdm) {
     public_deps += [ "//third_party/widevine/cdm" ]
   }
   if (!is_chromeos) {
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index 6d40d99..bd1695f 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -272,6 +272,8 @@
                              IDR_MEDIA_ROUTER_BINDINGS_JS);
   source_map->RegisterSource("mojo/public/mojom/base/time.mojom",
                              IDR_MOJO_TIME_MOJOM_JS);
+  source_map->RegisterSource("mojo/public/mojom/base/unguessable_token.mojom",
+                             IDR_MOJO_UNGUESSABLE_TOKEN_MOJOM_JS);
   source_map->RegisterSource("net/interfaces/ip_address.mojom",
                              IDR_MOJO_IP_ADDRESS_MOJOM_JS);
   source_map->RegisterSource("net/interfaces/ip_endpoint.mojom",
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js
index bde1e21..624bf02 100644
--- a/chrome/renderer/resources/extensions/media_router_bindings.js
+++ b/chrome/renderer/resources/extensions/media_router_bindings.js
@@ -20,6 +20,7 @@
 loadScript('media/mojo/interfaces/mirror_service_remoting.mojom');
 loadScript('media/mojo/interfaces/remoting_common.mojom');
 loadScript('mojo/public/mojom/base/time.mojom');
+loadScript('mojo/public/mojom/base/unguessable_token.mojom');
 loadScript('net/interfaces/ip_address.mojom');
 loadScript('net/interfaces/ip_endpoint.mojom');
 loadScript('url/mojom/origin.mojom');
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index e738202..9d8f81b 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -91,6 +91,7 @@
         <include name="IDR_MIRRORING_SESSION_OBSERVER_MOJOM_JS" file="${mojom_root}\components\mirroring\mojom\session_observer.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MIRRORING_SESSION_PARAMETERS_JS" file="${mojom_root}\components\mirroring\mojom\session_parameters.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MOJO_TIME_MOJOM_JS" file="${mojom_root}\mojo\public\mojom\base\time.mojom.js" use_base_dir="false" type="BINDATA" />
+        <include name="IDR_MOJO_UNGUESSABLE_TOKEN_MOJOM_JS" file="${mojom_root}\mojo\public\mojom\base\unguessable_token.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MOJO_IP_ADDRESS_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_address.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_MOJO_IP_ENDPOINT_MOJOM_JS" file="${mojom_root}\net\interfaces\ip_endpoint.mojom.js" use_base_dir="false" type="BINDATA" />
         <include name="IDR_ORIGIN_MOJOM_JS" file="${mojom_root}\url\mojom\origin.mojom.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/services/isolated_xr_device/manifest.json b/chrome/services/isolated_xr_device/manifest.json
index 4f1080e..613250f1 100644
--- a/chrome/services/isolated_xr_device/manifest.json
+++ b/chrome/services/isolated_xr_device/manifest.json
@@ -1,7 +1,7 @@
 {
   "name": "xr_device_service",
   "display_name": "XR Isolated Device Service",
-  "sandbox_type": "none",
+  "sandbox_type": "xr_compositing",
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
diff --git a/chrome/test/chromedriver/log_replay/client_replay.py b/chrome/test/chromedriver/log_replay/client_replay.py
index 7ab3a2d6..2837c60 100755
--- a/chrome/test/chromedriver/log_replay/client_replay.py
+++ b/chrome/test/chromedriver/log_replay/client_replay.py
@@ -70,8 +70,6 @@
 # this data throughout chromedriver code (see e.g. http_handler.cc)
 _COMMANDS = {
     "AcceptAlert": (Method.POST, "/session/:sessionId/alert/accept"),
-    "Activate": (Method.POST, "/session/:sessionId/ime/activate"),
-    "Activated": (Method.GET, "/session/:sessionId/ime/activated"),
     "AddCookie": (Method.POST, "/session/:sessionId/cookie"),
     "ClearElement": (Method.POST, "/session/:sessionId/element/:id/clear"),
     "ClearLocalStorage": (Method.DELETE, "/session/:sessionId/local_storage"),
@@ -80,7 +78,6 @@
     "Click": (Method.POST, "/session/:sessionId/click"),
     "ClickElement": (Method.POST, "/session/:sessionId/element/:id/click"),
     "CloseWindow": (Method.DELETE, "/session/:sessionId/window"),
-    "Deactivate": (Method.POST, "/session/:sessionId/ime/deactivate"),
     "DeleteActions": (Method.DELETE, "/session/:sessionId/actions"),
     "DeleteAllCookies": (Method.DELETE, "/session/:sessionId/cookie"),
     "DeleteCookie": (Method.DELETE, "/session/:sessionId/cookie/:name"),
@@ -90,13 +87,11 @@
     (Method.DELETE, "/session/:sessionId/orientation"),
     "DismissAlert": (Method.POST, "/session/:sessionId/dismiss_alert"),
     "DoubleClick": (Method.POST, "/session/:sessionId/doubleclick"),
-    "Drag": (Method.POST, "/session/:sessionId/element/:id/drag"),
     "ElementScreenshot":
     (Method.GET, "/session/:sessionId/element/:id/screenshot"),
     "ExecuteAsyncScript": (Method.POST, "/session/:sessionId/execute_async"),
     "ExecuteCDP": (Method.POST, "/session/:sessionId/goog/cdp/execute"),
     "ExecuteScript": (Method.POST, "/session/:sessionId/execute/sync"),
-    "ExecuteSql": (Method.POST, "/session/:sessionId/execute_sql"),
     "FindChildElement":
     (Method.POST, "/session/:sessionId/element/:id/element"),
     "FindChildElements":
@@ -106,12 +101,7 @@
     "Freeze": (Method.POST, "/session/:sessionId/goog/page/freeze"),
     "FullscreenWindow": (Method.POST, "/session/:sessionId/window/fullscreen"),
     "GetActiveElement": (Method.POST, "/session/:sessionId/element/active"),
-    "GetActiveEngine": (Method.GET, "/session/:sessionId/ime/active_engine"),
     "GetAlertMessage": (Method.GET, "/session/:sessionId/alert_text"),
-    "GetAvailableEngines":
-    (Method.GET, "/session/:sessionId/ime/available_engines"),
-    "GetBrowserConnection":
-    (Method.GET, "/session/:sessionId/browser_connection"),
     "GetCookies": (Method.GET, "/session/:sessionId/cookie"),
     "GetElementAttribute":
     (Method.GET, "/session/:sessionId/element/:id/attribute/:name"),
@@ -180,7 +170,6 @@
     (Method.GET, "/session/:sessionId/element/:id/selected"),
     "IsLoading": (Method.GET, "/session/:sessionId/is_loading"),
     "LaunchApp": (Method.POST, "/session/:sessionId/chromium/launch_app"),
-    "Logs": (Method.POST, "Logs"),
     "MaximizeWindow": (Method.POST, "/session/:sessionId/window/maximize"),
     "MinimizeWindow": (Method.POST, "/session/:sessionId/window/minimize"),
     "MouseDown": (Method.POST, "/session/:sessionId/buttondown"),
@@ -201,8 +190,6 @@
     (Method.POST, "/session/:sessionId/chromium/send_command_and_get_result"),
     "SetAlertPrompt": (Method.POST, "/session/:sessionId/alert_text"),
     "SetAutoReporting": (Method.POST, "/session/:sessionId/autoreport"),
-    "SetBrowserConnection":
-    (Method.POST, "/session/:sessionId/browser_connection"),
     "SetGeolocation": (Method.POST, "/session/:sessionId/location"),
     "SetImplicitWait":
     (Method.POST, "/session/:sessionId/timeouts/implicit_wait"),
@@ -237,8 +224,7 @@
     "TouchUp": (Method.POST, "/session/:sessionId/touch/up"),
     "Type": (Method.POST, "/session/:sessionId/keys"),
     "TypeElement": (Method.POST, "/session/:sessionId/element/:id/value"),
-    "UploadFile": (Method.POST, "/session/:sessionId/file"),
-    "Visible": (Method.POST, "/session/:sessionId/visible")
+    "UploadFile": (Method.POST, "/session/:sessionId/file")
 }
 
 MULTI_SESSION_COMMANDS = ["GetSessions"]
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 3bbe45be..a4f71b38f 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -449,21 +449,6 @@
       CommandMapping(
           kPost, "session/:sessionId/keys",
           WrapToCommand("Type", base::Bind(&ExecuteSendKeysToActiveElement))),
-      CommandMapping(kGet, "session/:sessionId/ime/available_engines",
-                     WrapToCommand("GetAvailableEngines",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(kGet, "session/:sessionId/ime/active_engine",
-                     WrapToCommand("GetActiveEngine",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(
-          kGet, "session/:sessionId/ime/activated",
-          WrapToCommand("Activated", base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(kPost, "session/:sessionId/ime/deactivate",
-                     WrapToCommand("Deactivate",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(
-          kPost, "session/:sessionId/ime/activate",
-          WrapToCommand("Activate", base::Bind(&ExecuteUnimplementedCommand))),
       CommandMapping(kPost, "session/:sessionId/touch/click",
                      WrapToCommand("Tap", base::Bind(&ExecuteTouchSingleTap))),
       CommandMapping(kPost, "session/:sessionId/touch/down",
@@ -505,12 +490,6 @@
           kGet, "session/:sessionId/chromium/heap_snapshot",
           WrapToCommand("HeapSnapshot", base::Bind(&ExecuteTakeHeapSnapshot))),
       CommandMapping(
-          kPost, "session/:sessionId/visible",
-          WrapToCommand("Visible", base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(
-          kGet, "session/:sessionId/visible",
-          WrapToCommand("Visible", base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(
           kPost, "session/:sessionId/file",
           WrapToCommand("UploadFile", base::Bind(&ExecuteUploadFile))),
       CommandMapping(kGet, "session/:sessionId/element/:id/value",
@@ -519,14 +498,6 @@
       CommandMapping(
           kPost, "session/:sessionId/element/:id/hover",
           WrapToCommand("HoverElement", base::Bind(&ExecuteHoverOverElement))),
-      CommandMapping(
-          kPost, "session/:sessionId/element/:id/drag",
-          WrapToCommand("Drag", base::Bind(&ExecuteUnimplementedCommand))),
-
-      CommandMapping(kPost, "session/:sessionId/execute_sql",
-                     WrapToCommand("ExecuteSql",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
-
       CommandMapping(kGet, "session/:sessionId/network_connection",
                      WrapToCommand("GetNetworkConnection",
                                    base::Bind(&ExecuteGetNetworkConnection))),
@@ -540,21 +511,11 @@
           kDelete, "session/:sessionId/chromium/network_conditions",
           WrapToCommand("DeleteNetworkConditions",
                         base::Bind(&ExecuteDeleteNetworkConditions))),
-
-      CommandMapping(kGet, "session/:sessionId/browser_connection",
-                     WrapToCommand("GetBrowserConnection",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(kPost, "session/:sessionId/browser_connection",
-                     WrapToCommand("SetBrowserConnection",
-                                   base::Bind(&ExecuteUnimplementedCommand))),
       CommandMapping(
           kDelete, "session/:sessionId/orientation",
           WrapToCommand("DeleteScreenOrientation",
                         base::Bind(&ExecuteDeleteScreenOrientation))),
       CommandMapping(
-          kPost, "Logs",
-          WrapToCommand("Logs", base::Bind(&ExecuteUnimplementedCommand))),
-      CommandMapping(
           kGet, kShutdownPath,
           base::Bind(&ExecuteQuitAll,
                      WrapToCommand("QuitAll", base::Bind(&ExecuteQuit, true)),
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/manifest.json b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/manifest.json
new file mode 100644
index 0000000..1c6c530
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/manifest.json
@@ -0,0 +1,6 @@
+{
+  "name": "Service worker with chrome.runtime.onInstalled event",
+  "version": "1.0",
+  "manifest_version": 2,
+  "background": {"service_worker_script": "service_worker_background.js"}
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/service_worker_background.js
new file mode 100644
index 0000000..f0530cad
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/events_on_installed/service_worker_background.js
@@ -0,0 +1,7 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.runtime.onInstalled.addListener(function() {
+  chrome.test.succeed();
+});
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/manifest.json b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/manifest.json
new file mode 100644
index 0000000..22c77fd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/manifest.json
@@ -0,0 +1,7 @@
+{
+  "name": "Service Worker based background script",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "Tests onStartup event from SW based extension",
+  "background": {"service_worker_script": "service_worker_background.js"}
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/service_worker_background.js
new file mode 100644
index 0000000..7366696
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/on_startup_event/service_worker_background.js
@@ -0,0 +1,9 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.runtime.onStartup.addListener(() => {
+  chrome.test.sendMessage('onStartup event');
+});
+
+chrome.test.succeed();
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/create_iframe_element.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/create_iframe_element.html
new file mode 100644
index 0000000..fe7b233
--- /dev/null
+++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/create_iframe_element.html
@@ -0,0 +1,23 @@
+<html>
+  <head>
+    <script>
+      function clickLink(linkId) {
+        var node = document.getElementById(linkId);
+        if (node != null) {
+          // Click and open link in the same tab.
+          node.click();
+        }
+      }
+
+      function runTest() {
+        var download_url = "../signed.exe";
+        var ifrm = document.createElement("iframe");
+        ifrm.setAttribute("src", download_url);
+        document.body.appendChild(ifrm);
+      }
+    </script>
+  </head>
+  <body>
+    <a id="do_download" onclick="runTest()">Click for download</div>
+  </body>
+</html>
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js
index 88b22a37..4329ac8 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.js
+++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -3,6 +3,15 @@
 // found in the LICENSE file.
 
 cr.define('settings_privacy_page', function() {
+  /**
+   * @param {!Element} element
+   * @param {boolean} displayed
+   */
+  function assertVisible(element, displayed) {
+    assertEquals(
+        displayed, window.getComputedStyle(element)['display'] != 'none');
+  }
+
   /** @implements {settings.ClearBrowsingDataBrowserProxy} */
   class TestClearBrowsingDataBrowserProxy extends TestBrowserProxy {
     constructor() {
@@ -154,6 +163,7 @@
         PolymerTest.clearBody();
         element = document.createElement('settings-clear-browsing-data-dialog');
         element.set('prefs', getClearBrowsingDataPrefs());
+        element.syncStatus = {signedIn: true, hasError: false};
         document.body.appendChild(element);
         return testBrowserProxy.whenCalled('initialize');
       });
@@ -323,6 +333,67 @@
           assertTrue(element.$$('#downloadCheckbox').hidden);
         });
       });
+
+      test('ClearBrowsingDataSyncAccountInfo', function() {
+        assertTrue(element.$$('#clearBrowsingDataDialog').open);
+
+        // Not syncing: the footer is hidden.
+        element.syncStatus = {
+          signedIn: false,
+          hasError: false,
+        };
+        Polymer.dom.flush();
+        assertTrue(element.$$('#clearBrowsingDataDialog [slot=footer]').hidden);
+
+        // Syncing: the footer is shown, with the normal sync info.
+        element.syncStatus = {
+          signedIn: true,
+          hasError: false,
+        };
+        Polymer.dom.flush();
+        assertFalse(
+            element.$$('#clearBrowsingDataDialog [slot=footer]').hidden);
+        assertVisible(element.$$('#sync-info'), true);
+        assertFalse(!!element.$$('#sync-paused-info'));
+        assertFalse(!!element.$$('#sync-passphrase-error-info'));
+        assertFalse(!!element.$$('#sync-other-error-info'));
+
+        // Sync is paused.
+        element.syncStatus = {
+          signedIn: true,
+          hasError: true,
+          statusAction: settings.StatusAction.REAUTHENTICATE
+        };
+        Polymer.dom.flush();
+        assertVisible(element.$$('#sync-paused-info'), true);
+        assertVisible(element.$$('#sync-info'), false);
+        assertFalse(!!element.$$('#sync-passphrase-error-info'));
+        assertFalse(!!element.$$('#sync-other-error-info'));
+
+        // Sync passphrase error.
+        element.syncStatus = {
+          signedIn: true,
+          hasError: true,
+          statusAction: settings.StatusAction.ENTER_PASSPHRASE
+        };
+        Polymer.dom.flush();
+        assertVisible(element.$$('#sync-passphrase-error-info'), true);
+        assertVisible(element.$$('#sync-info'), false);
+        assertVisible(element.$$('#sync-paused-info'), false);
+        assertFalse(!!element.$$('#sync-other-error-info'));
+
+        // Other sync error.
+        element.syncStatus = {
+          signedIn: true,
+          hasError: true,
+          statusAction: settings.StatusAction.NO_ACTION
+        };
+        Polymer.dom.flush();
+        assertVisible(element.$$('#sync-other-error-info'), true);
+        assertVisible(element.$$('#sync-info'), false);
+        assertVisible(element.$$('#sync-paused-info'), false);
+        assertVisible(element.$$('#sync-passphrase-error-info'), false);
+      });
     });
   }
 
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js
index 1179e6e..b0cec4be 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.js
+++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -364,5 +364,31 @@
       assertVisible(testElement.$$('#turn-off'), false);
       assertVisible(testElement.$$('#sync-paused-button'), false);
     });
+
+    test('hide buttons', function() {
+      testElement.hideButtons = true;
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'bar@bar.com',
+        statusAction: settings.StatusAction.NO_ACTION,
+        hasError: false,
+        hasUnrecoverableError: false,
+        disabled: false,
+      };
+
+      assertVisible(testElement.$$('#turn-off'), false);
+      assertVisible(testElement.$$('#sync-paused-button'), false);
+
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'bar@bar.com',
+        hasError: true,
+        hasUnrecoverableError: false,
+        statusAction: settings.StatusAction.REAUTHENTICATE,
+        disabled: false,
+      };
+      assertVisible(testElement.$$('#turn-off'), false);
+      assertVisible(testElement.$$('#sync-paused-button'), false);
+    });
   });
 });
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl.cc b/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
index a32994d..193aac3 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl.cc
@@ -41,6 +41,9 @@
 
 }  // namespace
 
+// static
+constexpr int LeScanManagerImpl::kMaxScanResultEntries;
+
 class LeScanManagerImpl::ScanHandleImpl : public LeScanManager::ScanHandle {
  public:
   explicit ScanHandleImpl(LeScanManagerImpl* manager, int32_t id)
@@ -120,18 +123,34 @@
   scan_result.addr = scan_result_shlib.addr;
   scan_result.rssi = scan_result_shlib.rssi;
 
-  // Remove results with the same data as the current result to avoid duplicate
-  // messages in the queue
   auto& previous_scan_results = addr_to_scan_results_[scan_result.addr];
-  previous_scan_results.remove_if([&scan_result](const auto& previous_result) {
-    return previous_result.adv_data == scan_result.adv_data;
-  });
+  if (previous_scan_results.size() > 0) {
+    // Remove results with the same data as the current result to avoid
+    // duplicate messages in the queue
+    previous_scan_results.remove_if(
+        [&scan_result](const auto& previous_result) {
+          return previous_result.adv_data == scan_result.adv_data;
+        });
+
+    // Remove scan_result.addr to avoid duplicate addresses in
+    // recent_scan_result_addr_list_.
+    base::Erase(scan_result_addr_list_, scan_result.addr);
+  }
 
   previous_scan_results.push_front(scan_result);
   if (previous_scan_results.size() > kMaxMessagesInQueue) {
     previous_scan_results.pop_back();
   }
 
+  // Update recent_scan_result_addr_list_.
+  scan_result_addr_list_.push_front(scan_result.addr);
+  while (scan_result_addr_list_.size() > kMaxScanResultEntries) {
+    // Remove least recently used address in recent_scan_result_addr_list_.
+    auto least_recently_used_addr = scan_result_addr_list_.back();
+    scan_result_addr_list_.pop_back();
+    addr_to_scan_results_.erase(least_recently_used_addr);
+  }
+
   // Update observers.
   observers_->Notify(FROM_HERE, &Observer::OnNewScanResult, scan_result);
 }
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl.h b/chromecast/device/bluetooth/le/le_scan_manager_impl.h
index 7a60609..c0b454ba 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl.h
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl.h
@@ -5,6 +5,7 @@
 #ifndef CHROMECAST_DEVICE_BLUETOOTH_LE_LE_SCAN_MANAGER_IMPL_H_
 #define CHROMECAST_DEVICE_BLUETOOTH_LE_LE_SCAN_MANAGER_IMPL_H_
 
+#include <deque>
 #include <list>
 #include <map>
 #include <set>
@@ -28,6 +29,8 @@
   explicit LeScanManagerImpl(bluetooth_v2_shlib::LeScannerImpl* le_scanner);
   ~LeScanManagerImpl() override;
 
+  static constexpr int kMaxScanResultEntries = 1024;
+
   void Initialize(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
   void Finalize();
 
@@ -61,6 +64,10 @@
   std::map<bluetooth_v2_shlib::Addr, std::list<LeScanResult>>
       addr_to_scan_results_;
 
+  // List of addresses in scan results. Addresses are sorted from most recently
+  // used to least recently used.
+  std::deque<bluetooth_v2_shlib::Addr> scan_result_addr_list_;
+
   int32_t next_scan_handle_id_ = 0;
   std::set<int32_t> scan_handle_ids_;
 
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc b/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
index 0db63fb..3807c267 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
@@ -283,5 +283,41 @@
   ASSERT_EQ(1, result.rssi);
 }
 
+TEST_F(LeScanManagerTest, TestMaxScanResultEntries) {
+  EXPECT_CALL(mock_observer_, OnNewScanResult(_))
+      .Times(LeScanManagerImpl::kMaxScanResultEntries + 5);
+
+  // Add scan results with different addrs.
+  bluetooth_v2_shlib::LeScanner::ScanResult raw_scan_result;
+  for (int i = 0; i < LeScanManagerImpl::kMaxScanResultEntries + 5; ++i) {
+    uint8_t addr_bit0 = i & 0xFF;
+    uint8_t addr_bit1 = (i & 0xFF00) >> 8;
+    raw_scan_result.addr = {{addr_bit0, addr_bit1, 0xFF, 0xFF, 0xFF, 0xFF}};
+    raw_scan_result.adv_data = {0x03, 0x02, 0x44, 0x44};
+    raw_scan_result.rssi = -i;
+    delegate()->OnScanResult(raw_scan_result);
+  }
+
+  scoped_task_environment_.RunUntilIdle();
+
+  std::vector<LeScanResult> results;
+  // Get asynchronous scan results.
+  le_scan_manager_.GetScanResults(
+      base::BindOnce(&CopyResult<std::vector<LeScanResult>>, &results));
+
+  scoped_task_environment_.RunUntilIdle();
+
+  // First 5 addresses should have been kicked out.
+  ASSERT_EQ(1024u, results.size());
+  bluetooth_v2_shlib::Addr test_addr;
+  for (int i = 0; i < LeScanManagerImpl::kMaxScanResultEntries; ++i) {
+    uint8_t addr_bit0 = (i + 5) & 0xFF;
+    uint8_t addr_bit1 = ((i + 5) & 0xFF00) >> 8;
+    test_addr = {{addr_bit0, addr_bit1, 0xFF, 0xFF, 0xFF, 0xFF}};
+    EXPECT_EQ(test_addr, results[i].addr);
+    EXPECT_EQ(-(i + 5), results[i].rssi);
+  }
+}
+
 }  // namespace bluetooth
 }  // namespace chromecast
diff --git a/chromecast/media/cma/backend/fuchsia/BUILD.gn b/chromecast/media/cma/backend/fuchsia/BUILD.gn
index 5d2af30b..1e4d0646 100644
--- a/chromecast/media/cma/backend/fuchsia/BUILD.gn
+++ b/chromecast/media/cma/backend/fuchsia/BUILD.gn
@@ -40,7 +40,7 @@
     "//chromecast/public",
     "//chromecast/public/media",
     "//media",
-    "//third_party/fuchsia-sdk:media",
+    "//third_party/fuchsia-sdk/sdk:media",
   ]
 }
 
@@ -56,6 +56,6 @@
     ":cma_backend_support",
     "//base",
     "//testing/gtest",
-    "//third_party/fuchsia-sdk:media",
+    "//third_party/fuchsia-sdk/sdk:media",
   ]
 }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 5be9a0b53..b83892b 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-11110.0.0
\ No newline at end of file
+11118.0.0
\ No newline at end of file
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index 903451e3..50c33318 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -51,7 +51,7 @@
 constexpr char kTimerFireNotificationGroupId[] = "assistant/timer_fire";
 constexpr char kQueryDeeplinkPrefix[] = "googleassistant://send-query?q=";
 constexpr base::Feature kAssistantTimerNotificationFeature{
-    "ChromeOSAssistantTimerNotification", base::FEATURE_DISABLED_BY_DEFAULT};
+    "ChromeOSAssistantTimerNotification", base::FEATURE_ENABLED_BY_DEFAULT};
 
 constexpr float kDefaultSliderStep = 0.1f;
 }  // namespace
diff --git a/components/arc/OWNERS b/components/arc/OWNERS
index d7d81e7..1888633 100644
--- a/components/arc/OWNERS
+++ b/components/arc/OWNERS
@@ -1,4 +1,3 @@
 elijahtaylor@chromium.org
 hidehiko@chromium.org
-lhchavez@chromium.org
 yusukes@chromium.org
diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc
index 66f9097..3c047c9 100644
--- a/components/arc/intent_helper/activity_icon_loader.cc
+++ b/components/arc/intent_helper/activity_icon_loader.cc
@@ -86,7 +86,7 @@
     ui::ScaleFactor scale_factor) {
   float scale = ui::GetScaleForScaleFactor(scale_factor);
   std::vector<unsigned char> output;
-  gfx::PNGCodec::EncodeBGRASkBitmap(image.GetRepresentation(scale).sk_bitmap(),
+  gfx::PNGCodec::EncodeBGRASkBitmap(image.GetRepresentation(scale).GetBitmap(),
                                     false /* discard_transparency */, &output);
   std::string encoded;
   base::Base64Encode(
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 5c9328e05..b8b64b4a 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -328,6 +328,8 @@
     "test_autofill_external_delegate.h",
     "test_autofill_manager.cc",
     "test_autofill_manager.h",
+    "test_autofill_profile_validator.cc",
+    "test_autofill_profile_validator.h",
     "test_autofill_provider.cc",
     "test_autofill_provider.h",
     "test_credit_card_save_manager.cc",
@@ -376,6 +378,7 @@
     "//services/network/public/cpp",
     "//skia",
     "//testing/gtest",
+    "//third_party/libaddressinput:test_support",
     "//third_party/libaddressinput:util",
     "//ui/gfx:test_support",
     "//ui/gfx/geometry",
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 6962703..f78e4cf 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -291,7 +291,8 @@
   void SetUp() override {
     autofill_client_.SetPrefs(test::PrefServiceForTesting());
     personal_data_.Init(autofill_client_.GetDatabase(), nullptr,
-                        autofill_client_.GetPrefs(), nullptr, false);
+                        autofill_client_.GetPrefs(), nullptr,
+                        /*client_profile_validator=*/nullptr, false);
     personal_data_.SetPrefService(autofill_client_.GetPrefs());
     autofill_driver_ =
         std::make_unique<testing::NiceMock<MockAutofillDriver>>();
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index a026ce4..1c948787 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -2798,6 +2798,7 @@
                        /*account_database=*/nullptr,
                        autofill_client_.GetPrefs(),
                        /*identity_manager=*/nullptr,
+                       /*client_profile_validator=*/nullptr,
                        /*is_off_the_record=*/false);
   histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", true, 1);
 }
@@ -2810,6 +2811,7 @@
                        /*account_database=*/nullptr,
                        autofill_client_.GetPrefs(),
                        /*identity_manager=*/nullptr,
+                       /*client_profile_validator=*/nullptr,
                        /*is_off_the_record=*/false);
   histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", false, 1);
 }
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index 4eb7e51..94f9342 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -280,6 +280,8 @@
 
   server_id_ = profile.server_id();
   has_converted_ = profile.has_converted();
+  is_client_validity_states_updated_ =
+      profile.is_client_validity_states_updated();
   SetClientValidityFromBitfieldValue(profile.GetClientValidityBitfieldValue());
   server_validity_states_ = profile.GetServerValidityMap();
 
@@ -360,8 +362,11 @@
 void AutofillProfile::SetRawInfo(ServerFieldType type,
                                  const base::string16& value) {
   FormGroup* form_group = MutableFormGroupForType(AutofillType(type));
-  if (form_group)
+  if (form_group) {
+    is_client_validity_states_updated_ &=
+        !IsClientValidationSupportedForType(type);
     form_group->SetRawInfo(type, value);
+  }
 }
 
 void AutofillProfile::GetSupportedTypes(
@@ -434,8 +439,8 @@
 bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const {
   return guid() == profile.guid() &&
          language_code() == profile.language_code() &&
-         GetClientValidityBitfieldValue() ==
-             profile.GetClientValidityBitfieldValue() &&
+         is_client_validity_states_updated() ==
+             profile.is_client_validity_states_updated() &&
          Compare(profile) == 0;
 }
 
@@ -517,7 +522,6 @@
   // values.
   std::string language_code_value = language_code();
   std::string origin_value = origin();
-  int validity_bitfield_value = GetClientValidityBitfieldValue();
   base::string16 name_full_value = GetRawInfo(NAME_FULL);
 
   *this = profile;
@@ -526,8 +530,6 @@
     set_origin(origin_value);
   if (language_code().empty())
     set_language_code(language_code_value);
-  if (GetClientValidityBitfieldValue() == 0)
-    SetClientValidityFromBitfieldValue(validity_bitfield_value);
   if (!HasRawInfo(NAME_FULL))
     SetRawInfo(NAME_FULL, name_full_value);
 }
@@ -608,6 +610,8 @@
     modified = true;
   }
 
+  is_client_validity_states_updated_ &= !modified;
+
   return modified;
 }
 
@@ -954,6 +958,9 @@
   if (!form_group)
     return false;
 
+  is_client_validity_states_updated_ &=
+      !IsClientValidationSupportedForType(type.GetStorableType());
+
   base::string16 trimmed_value;
   base::TrimWhitespace(value, base::TRIM_ALL, &trimmed_value);
   return form_group->SetInfoImpl(type, trimmed_value, app_locale);
@@ -1087,8 +1094,8 @@
 bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
   return origin() == profile.origin() &&
          language_code() == profile.language_code() &&
-         GetClientValidityBitfieldValue() ==
-             profile.GetClientValidityBitfieldValue() &&
+         is_client_validity_states_updated() ==
+             profile.is_client_validity_states_updated() &&
          Compare(profile) == 0;
 }
 
diff --git a/components/autofill/core/browser/autofill_profile.h b/components/autofill/core/browser/autofill_profile.h
index 482878a..9dfa5e9 100644
--- a/components/autofill/core/browser/autofill_profile.h
+++ b/components/autofill/core/browser/autofill_profile.h
@@ -258,6 +258,14 @@
     return server_validity_states_;
   };
 
+  bool is_client_validity_states_updated() const {
+    return is_client_validity_states_updated_;
+  }
+  void set_is_client_validity_states_updated(
+      bool is_client_validity_states_updated) {
+    is_client_validity_states_updated_ = is_client_validity_states_updated;
+  }
+
  private:
   typedef std::vector<const FormGroup*> FormGroupList;
 
@@ -313,6 +321,10 @@
   // converted to a local profile.
   bool has_converted_;
 
+  // This flag denotes whether the client_validity_states_ are updated according
+  // to the changes in the autofill profile values.
+  bool is_client_validity_states_updated_ = false;
+
   // A map identifying what fields are valid according to server validation.
   std::map<ServerFieldType, ValidityState> server_validity_states_;
 
diff --git a/components/autofill/core/browser/autofill_profile_unittest.cc b/components/autofill/core/browser/autofill_profile_unittest.cc
index 75197d85..5da5238 100644
--- a/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -39,12 +39,14 @@
   return labels[0];
 }
 
-void SetupTestProfile(AutofillProfile& profile) {
+void SetupValidatedTestProfile(AutofillProfile& profile) {
   profile.set_guid(base::GenerateGUID());
   profile.set_origin(kSettingsOrigin);
   test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
                        "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5",
                        "Hollywood", "CA", "91601", "US", "12345678910");
+  profile.SetClientValidityFromBitfieldValue(1984);
+  profile.set_is_client_validity_states_updated(true);
 }
 
 std::vector<AutofillProfile*> ToRawPointerVector(
@@ -705,9 +707,25 @@
   EXPECT_FALSE(a->IsSubsetOf(*b, "en-US"));
 }
 
+TEST(AutofillProfileTest, SetRawInfo_UpdateValidityFlag) {
+  AutofillProfile a;
+  SetupValidatedTestProfile(a);
+  EXPECT_TRUE(a.is_client_validity_states_updated());
+
+  a.SetRawInfo(NAME_FULL, ASCIIToUTF16("Alice Munro"));
+  // NAME_FULL is NOT validated through the client API (not supported),
+  // therefore it should not change the validity flag.
+  EXPECT_TRUE(a.is_client_validity_states_updated());
+
+  a.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Ooz"));
+  // ADDRESS_HOME_CITY IS validated through the client API, therefore it should
+  // change the flag to false.
+  EXPECT_FALSE(a.is_client_validity_states_updated());
+}
+
 TEST(AutofillProfileTest, MergeDataFrom_DifferentProfile) {
   AutofillProfile a;
-  SetupTestProfile(a);
+  SetupValidatedTestProfile(a);
 
   // Create an identical profile except that the new profile:
   //   (1) Has a different origin,
@@ -726,6 +744,8 @@
   b.set_language_code("en");
 
   EXPECT_TRUE(a.MergeDataFrom(b, "en-US"));
+  // Merge has modified profile a, the validation is not updated.
+  EXPECT_FALSE(a.is_client_validity_states_updated());
   EXPECT_EQ(kSettingsOrigin, a.origin());
   EXPECT_EQ(ASCIIToUTF16("Unit 5, area 51"), a.GetRawInfo(ADDRESS_HOME_LINE2));
   EXPECT_EQ(ASCIIToUTF16("Fox"), a.GetRawInfo(COMPANY_NAME));
@@ -736,20 +756,27 @@
 
 TEST(AutofillProfileTest, MergeDataFrom_SameProfile) {
   AutofillProfile a;
-  SetupTestProfile(a);
+  SetupValidatedTestProfile(a);
 
   // The profile has no full name yet. Merge will add it.
   AutofillProfile b = a;
   b.set_guid(base::GenerateGUID());
   EXPECT_TRUE(a.MergeDataFrom(b, "en-US"));
+  // Merge has modified profile a, the validation is not updated.
+  EXPECT_FALSE(a.is_client_validity_states_updated());
   EXPECT_EQ(1u, a.use_count());
 
+  // pretend that the profile is re-validated.
+  a.set_is_client_validity_states_updated(true);
+
   // Now the profile is fully populated. Merging it again has no effect (except
   // for usage statistics).
   AutofillProfile c = a;
   c.set_guid(base::GenerateGUID());
   c.set_use_count(3);
   EXPECT_FALSE(a.MergeDataFrom(c, "en-US"));
+  // Merge has not modified anything, the validation should not changed.
+  EXPECT_TRUE(a.is_client_validity_states_updated());
   EXPECT_EQ(3u, a.use_count());
 }
 
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index 325c2db..107a5ae4 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -354,6 +354,7 @@
 
   profile.set_language_code("en");
   profile.SetClientValidityFromBitfieldValue(kValidityStateBitfield);
+  profile.set_is_client_validity_states_updated(true);
   profile.set_use_count(7);
   profile.set_use_date(base::Time::FromTimeT(54321));
 
@@ -376,6 +377,7 @@
 
   profile.set_language_code("en");
   profile.SetClientValidityFromBitfieldValue(kValidityStateBitfield);
+  profile.set_is_client_validity_states_updated(true);
   profile.set_use_count(14);
   profile.set_use_date(base::Time::FromTimeT(98765));
 
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
index 308acee..7e39b75 100644
--- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -105,7 +105,8 @@
   void SetUp() override {
     autofill_client_.SetPrefs(test::PrefServiceForTesting());
     personal_data_.Init(autofill_client_.GetDatabase(), nullptr,
-                        autofill_client_.GetPrefs(), nullptr, false);
+                        autofill_client_.GetPrefs(), nullptr,
+                        /*client_profile_validator=*/nullptr, false);
     personal_data_.SetSyncServiceForTest(&sync_service_);
     autofill_driver_.reset(new TestAutofillDriver());
     request_context_ = new net::TestURLRequestContextGetter(
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc
index 556fdb6ac..cedc101651 100644
--- a/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -119,7 +119,8 @@
     personal_data_manager_.reset(new PersonalDataManager("en"));
     personal_data_manager_->Init(
         scoped_refptr<AutofillWebDataService>(autofill_database_service_),
-        nullptr, prefs_.get(), nullptr, is_incognito);
+        nullptr, prefs_.get(), nullptr, /*client_profile_validator=*/nullptr,
+        is_incognito);
     personal_data_manager_->AddObserver(&personal_data_observer_);
     personal_data_manager_->OnSyncServiceInitialized(nullptr);
 
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index bcb6a8e..f1e4770 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -473,6 +473,7 @@
     scoped_refptr<AutofillWebDataService> account_database,
     PrefService* pref_service,
     identity::IdentityManager* identity_manager,
+    AutofillProfileValidator* client_profile_validator,
     bool is_off_the_record) {
   CountryNames::SetLocaleString(app_locale_);
   database_helper_->Init(profile_database, account_database);
@@ -500,6 +501,7 @@
   LoadCreditCards();
   LoadPaymentsCustomerData();
 
+  client_profile_validator_ = client_profile_validator;
   // Check if profile cleanup has already been performed this major version.
   is_autofill_profile_cleanup_pending_ =
       pref_service_->GetInteger(prefs::kAutofillLastVersionDeduped) >=
@@ -1184,6 +1186,26 @@
   }
 }
 
+void PersonalDataManager::OnValidated(AutofillProfile* profile) {
+  // We always set a value for country validity state.
+  DCHECK(profile->GetValidityState(ServerFieldType::ADDRESS_HOME_COUNTRY,
+                                   AutofillProfile::CLIENT) !=
+         AutofillProfile::UNVALIDATED);
+  profile->set_is_client_validity_states_updated(true);
+}
+
+void PersonalDataManager::UpdateClientValidityStates(
+    std::vector<AutofillProfile*>& profiles) {
+  if (!client_profile_validator_)
+    return;
+  for (auto* profile : profiles) {
+    if (!profile->is_client_validity_states_updated())
+      client_profile_validator_->StartProfileValidation(
+          profile, base::BindOnce(&PersonalDataManager::OnValidated,
+                                  base::Unretained(this)));
+  }
+}
+
 std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const {
   std::vector<AutofillProfile*> result;
   if (!IsAutofillProfileEnabled())
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index fc11533e..e49b7a52 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -20,6 +20,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/browser/account_info_getter.h"
 #include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_profile_validator.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
@@ -33,6 +34,8 @@
 #include "components/signin/core/browser/account_info.h"
 #include "components/sync/driver/sync_service_observer.h"
 #include "components/webdata/common/web_data_service_consumer.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
 
 class Browser;
 class PrefService;
@@ -85,6 +88,7 @@
             scoped_refptr<AutofillWebDataService> account_database,
             PrefService* pref_service,
             identity::IdentityManager* identity_manager,
+            AutofillProfileValidator* client_profile_validator,
             bool is_off_the_record);
 
   // KeyedService:
@@ -232,9 +236,14 @@
   // Returns the Payments customer data. Returns nullptr if no data is present.
   virtual PaymentsCustomerData* GetPaymentsCustomerData() const;
 
+  // Updates the validity states of |profiles| according to server validity map.
   void UpdateProfilesValidityMapsIfNeeded(
       std::vector<AutofillProfile*>& profiles);
 
+  // Updates the validity states of |profiles| according to client side
+  // validation API: |client_profile_validator_|.
+  void UpdateClientValidityStates(std::vector<AutofillProfile*>& profiles);
+
   // Returns the profiles to suggest to the user, ordered by frecency.
   std::vector<AutofillProfile*> GetProfilesToSuggest() const;
 
@@ -700,6 +709,9 @@
     profile_validities_need_update = true;
   };
 
+  // Called when the |profile| is validated by the AutofillProfileValidator.
+  void OnValidated(AutofillProfile* profile);
+
   const std::string app_locale_;
 
   // The default country code for new addresses.
@@ -716,6 +728,8 @@
   // |profile_validities_need_update| whenever this is changed.
   std::unique_ptr<UserProfileValidityMap> synced_profile_validity_;
 
+  AutofillProfileValidator* client_profile_validator_;
+
   // The identity manager that this instance uses. Must outlive this instance.
   identity::IdentityManager* identity_manager_ = nullptr;
 
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 13624e5..8dce199b 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -38,6 +38,7 @@
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/browser/test_autofill_profile_validator.h"
 #include "components/autofill/core/browser/test_sync_service.h"
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -177,7 +178,8 @@
         use_account_server_storage
             ? scoped_refptr<AutofillWebDataService>(account_database_service_)
             : nullptr,
-        prefs_.get(), identity_test_env_.identity_manager(), is_incognito);
+        prefs_.get(), identity_test_env_.identity_manager(),
+        TestAutofillProfileValidator::GetInstance(), is_incognito);
     personal_data_->AddObserver(&personal_data_observer_);
     sync_service_.SetIsAuthenticatedAccountPrimary(!use_account_server_storage);
     personal_data_->OnSyncServiceInitialized(&sync_service_);
@@ -6784,6 +6786,159 @@
   EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillProfile::VALID);
 }
 
+// Use the client side validation API to validate three PDM profiles. This one
+// doesn't test the upload process or saving to the database.
+TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) {
+  // Create three profiles and add them to personal_data_.
+  AutofillProfile valid_profile(test::GetFullValidProfileForCanada());
+  valid_profile.set_guid("00000000-0000-0000-0000-000000000001");
+  personal_data_->AddProfile(valid_profile);
+
+  AutofillProfile profile_invalid_phone_email(
+      test::GetFullValidProfileForChina());
+  profile_invalid_phone_email.SetRawInfo(
+      PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("invalid phone number!"));
+  profile_invalid_phone_email.SetRawInfo(EMAIL_ADDRESS,
+                                         base::UTF8ToUTF16("invalid email!"));
+  profile_invalid_phone_email.set_guid("00000000-0000-0000-0000-000000000002");
+  personal_data_->AddProfile(profile_invalid_phone_email);
+
+  AutofillProfile profile_invalid_province(base::GenerateGUID(),
+                                           test::kEmptyOrigin);
+  test::SetProfileInfo(&profile_invalid_province, "Alice", "", "Munro",
+                       "alice@munro.ca", "Fox", "123 Zoo St", "unit 5",
+                       "Montreal", "CA", "H3C 2A3", "CA", "15142343254");
+  profile_invalid_province.set_guid("00000000-0000-0000-0000-000000000003");
+  personal_data_->AddProfile(profile_invalid_province);
+
+  WaitForOnPersonalDataChanged();
+  ASSERT_EQ(3U, personal_data_->GetProfiles().size());
+
+  // Validate the profiles through the client validation API.
+  auto profiles = personal_data_->GetProfiles();
+  for (auto* profile : profiles)
+    ASSERT_FALSE(profile->is_client_validity_states_updated());
+  personal_data_->UpdateClientValidityStates(profiles);
+
+  ASSERT_EQ(3U, profiles.size());
+  // The profiles are ordered according to their guid.
+  // valid_profile:
+  ASSERT_EQ(valid_profile.guid(), profiles[0]->guid());
+  EXPECT_TRUE(profiles[0]->is_client_validity_states_updated());
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[0]->GetValidityState(ADDRESS_HOME_STATE,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::VALID,
+      profiles[0]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[0]->GetValidityState(ADDRESS_HOME_CITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::EMPTY,
+            profiles[0]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::VALID,
+      profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[0]->GetValidityState(PHONE_HOME_WHOLE_NUMBER,
+                                          AutofillProfile::CLIENT));
+
+  // profile_invalid_phone_email:
+  ASSERT_EQ(profile_invalid_phone_email.guid(), profiles[1]->guid());
+  EXPECT_TRUE(profiles[1]->is_client_validity_states_updated());
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[1]->GetValidityState(ADDRESS_HOME_COUNTRY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[1]->GetValidityState(ADDRESS_HOME_STATE,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::VALID,
+      profiles[1]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[1]->GetValidityState(ADDRESS_HOME_CITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[1]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::INVALID,
+      profiles[1]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::INVALID,
+            profiles[1]->GetValidityState(PHONE_HOME_WHOLE_NUMBER,
+                                          AutofillProfile::CLIENT));
+
+  ASSERT_EQ(profile_invalid_province.guid(), profiles[2]->guid());
+  EXPECT_TRUE(profiles[2]->is_client_validity_states_updated());
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[2]->GetValidityState(ADDRESS_HOME_COUNTRY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::INVALID,
+            profiles[2]->GetValidityState(ADDRESS_HOME_STATE,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::VALID,
+      profiles[2]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[2]->GetValidityState(ADDRESS_HOME_CITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::EMPTY,
+            profiles[2]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
+                                          AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillProfile::VALID,
+      profiles[2]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillProfile::VALID,
+            profiles[2]->GetValidityState(PHONE_HOME_WHOLE_NUMBER,
+                                          AutofillProfile::CLIENT));
+}
+
+// Check the validity update status for AutofillProfiles.
+TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_UpdatedFlag) {
+  // Create two profiles and add them to personal_data_.
+  AutofillProfile profile1(test::GetFullValidProfileForCanada());
+  personal_data_->AddProfile(profile1);
+
+  AutofillProfile profile2(test::GetFullValidProfileForChina());
+  personal_data_->AddProfile(profile2);
+
+  WaitForOnPersonalDataChanged();
+  ASSERT_EQ(2U, personal_data_->GetProfiles().size());
+
+  // Validate the profiles through the client validation API.
+  auto profiles = personal_data_->GetProfiles();
+  ASSERT_FALSE(profiles[0]->is_client_validity_states_updated());
+  ASSERT_FALSE(profiles[1]->is_client_validity_states_updated());
+
+  personal_data_->UpdateClientValidityStates(profiles);
+  ASSERT_EQ(2U, profiles.size());
+  EXPECT_TRUE(profiles[0]->is_client_validity_states_updated());
+  EXPECT_TRUE(profiles[1]->is_client_validity_states_updated());
+
+  *profiles[1] = *profiles[0];
+  ASSERT_TRUE(profiles[0]->is_client_validity_states_updated());
+  ASSERT_TRUE(profiles[1]->is_client_validity_states_updated());
+
+  profiles[1]->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16(""));
+  ASSERT_TRUE(profiles[0]->is_client_validity_states_updated());
+  ASSERT_FALSE(profiles[1]->is_client_validity_states_updated());
+
+  personal_data_->UpdateClientValidityStates(profiles);
+  ASSERT_TRUE(profiles[0]->is_client_validity_states_updated());
+  ASSERT_TRUE(profiles[1]->is_client_validity_states_updated());
+
+  profiles[1]->MergeDataFrom(*profiles[0], "en");
+  ASSERT_TRUE(profiles[0]->is_client_validity_states_updated());
+  ASSERT_FALSE(profiles[1]->is_client_validity_states_updated());
+
+  profiles[0]->SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Goli Boli"));
+  ASSERT_TRUE(profiles[0]->is_client_validity_states_updated());
+}
+
 TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) {
   const std::string kIdentityManagerAccountEmail = "identity_account@email.com";
   const std::string kSyncServiceAccountEmail = "active_sync_account@email.com";
diff --git a/components/autofill/core/browser/test_autofill_profile_validator.cc b/components/autofill/core/browser/test_autofill_profile_validator.cc
new file mode 100644
index 0000000..d3eba5d0
--- /dev/null
+++ b/components/autofill/core/browser/test_autofill_profile_validator.cc
@@ -0,0 +1,57 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_autofill_profile_validator.h"
+
+#include <memory>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
+#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
+
+namespace {
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+using ::i18n::addressinput::NullStorage;
+using ::i18n::addressinput::TestdataSource;
+
+}  // namespace
+
+namespace autofill {
+
+namespace {
+
+std::unique_ptr<::i18n::addressinput::Source> GetInputSource() {
+  base::FilePath file_path;
+  CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
+  file_path = file_path.Append(FILE_PATH_LITERAL("third_party"))
+                  .Append(FILE_PATH_LITERAL("libaddressinput"))
+                  .Append(FILE_PATH_LITERAL("src"))
+                  .Append(FILE_PATH_LITERAL("testdata"))
+                  .Append(FILE_PATH_LITERAL("countryinfo.txt"));
+  return std::make_unique<TestdataSource>(true, file_path.AsUTF8Unsafe());
+}
+
+std::unique_ptr<::i18n::addressinput::Storage> GetInputStorage() {
+  return std::unique_ptr<Storage>(new NullStorage);
+}
+
+}  // namespace
+
+// static
+AutofillProfileValidator* TestAutofillProfileValidator::GetInstance() {
+  static base::LazyInstance<TestAutofillProfileValidator>::DestructorAtExit
+      instance = LAZY_INSTANCE_INITIALIZER;
+  return &(instance.Get().autofill_profile_validator_);
+}
+
+TestAutofillProfileValidator::TestAutofillProfileValidator()
+    : autofill_profile_validator_(GetInputSource(), GetInputStorage()) {}
+
+TestAutofillProfileValidator::~TestAutofillProfileValidator() {}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_profile_validator.h b/components/autofill/core/browser/test_autofill_profile_validator.h
new file mode 100644
index 0000000..93b7eee
--- /dev/null
+++ b/components/autofill/core/browser/test_autofill_profile_validator.h
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_H_
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "components/autofill/core/browser/autofill_profile_validator.h"
+
+namespace autofill {
+
+// Singleton that owns a single AutofillProfileValidator instance.
+class TestAutofillProfileValidator {
+ public:
+  static AutofillProfileValidator* GetInstance();
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<TestAutofillProfileValidator>;
+
+  TestAutofillProfileValidator();
+  ~TestAutofillProfileValidator();
+
+  // The only instance that exists.
+  AutofillProfileValidator autofill_profile_validator_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAutofillProfileValidator);
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_H_
diff --git a/components/autofill_assistant/browser/actions/action.cc b/components/autofill_assistant/browser/actions/action.cc
index 7617be4..16a01f1 100644
--- a/components/autofill_assistant/browser/actions/action.cc
+++ b/components/autofill_assistant/browser/actions/action.cc
@@ -14,8 +14,8 @@
   // Safety check in case process action is run twice.
   *processed_action_proto_->mutable_action() = proto_;
   processed_action_proto_->set_status(
-      status ? ProcessedActionStatus::ACTION_APPLIED
-             : ProcessedActionStatus::OTHER_ACTION_STATUS);
+      status ? ProcessedActionStatusProto::ACTION_APPLIED
+             : ProcessedActionStatusProto::OTHER_ACTION_STATUS);
 }
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
index 722af2c..43a0579 100644
--- a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
@@ -135,7 +135,7 @@
     DirectCallback callback;
     action.ProcessAction(&mock_action_delegate_, callback.Get());
     return callback.GetResultOrDie()->status() ==
-           ProcessedActionStatus::ACTION_APPLIED;
+           ProcessedActionStatusProto::ACTION_APPLIED;
   }
 
   MockActionDelegate mock_action_delegate_;
diff --git a/components/autofill_assistant/browser/actions/navigate_action.h b/components/autofill_assistant/browser/actions/navigate_action.h
index f42c9f784..72114b8 100644
--- a/components/autofill_assistant/browser/actions/navigate_action.h
+++ b/components/autofill_assistant/browser/actions/navigate_action.h
@@ -11,7 +11,7 @@
 #include "components/autofill_assistant/browser/actions/action.h"
 
 namespace autofill_assistant {
-// An action to display a message.
+// An action to navigate to a given web page.
 class NavigateAction : public Action {
  public:
   explicit NavigateAction(const ActionProto& proto);
diff --git a/components/autofill_assistant/browser/actions/reset_action.h b/components/autofill_assistant/browser/actions/reset_action.h
index 1fb19af..564c2ad 100644
--- a/components/autofill_assistant/browser/actions/reset_action.h
+++ b/components/autofill_assistant/browser/actions/reset_action.h
@@ -11,7 +11,7 @@
 #include "components/autofill_assistant/browser/actions/action.h"
 
 namespace autofill_assistant {
-
+// An action to reset Autofill Assistant state.
 class ResetAction : public Action {
  public:
   explicit ResetAction(const ActionProto& proto);
diff --git a/components/autofill_assistant/browser/actions/stop_action.h b/components/autofill_assistant/browser/actions/stop_action.h
index de62b30..f51bce70 100644
--- a/components/autofill_assistant/browser/actions/stop_action.h
+++ b/components/autofill_assistant/browser/actions/stop_action.h
@@ -11,7 +11,7 @@
 #include "components/autofill_assistant/browser/actions/action.h"
 
 namespace autofill_assistant {
-
+// An action to stop Autofill Assistant.
 class StopAction : public Action {
  public:
   explicit StopAction(const ActionProto& proto);
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 37e0398..f7f1a97 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -207,7 +207,7 @@
     std::unique_ptr<ProcessedActionProto> processed_action_proto) {
   processed_actions_.emplace_back(*processed_action_proto);
   if (processed_actions_.back().status() !=
-      ProcessedActionStatus::ACTION_APPLIED) {
+      ProcessedActionStatusProto::ACTION_APPLIED) {
     // Report error immediately, interrupting action processing.
     GetNextActions();
     return;
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index de0cc72..a92b6bf 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -240,12 +240,12 @@
   // The action that was processed.
   optional ActionProto action = 1;
 
-  optional ProcessedActionStatus status = 2;
+  optional ProcessedActionStatusProto status = 2;
 
   optional PageContentProto page_content = 3;
 }
 
-enum ProcessedActionStatus {
+enum ProcessedActionStatusProto {
   UNKNOWN_ACTION_STATUS = 0;
   ELEMENT_RESOLUTION_FAILED = 1;
   ACTION_APPLIED = 2;
diff --git a/components/browser_sync/profile_sync_service_autofill_unittest.cc b/components/browser_sync/profile_sync_service_autofill_unittest.cc
index 25d529b..7b2c897a3 100644
--- a/components/browser_sync/profile_sync_service_autofill_unittest.cc
+++ b/components/browser_sync/profile_sync_service_autofill_unittest.cc
@@ -387,6 +387,7 @@
                                  /*account_database=*/nullptr,
                                  profile_sync_service_bundle()->pref_service(),
                                  /*identity_manager=*/nullptr,
+                                 /*client_profile_validator=*/nullptr,
                                  /*is_off_the_record=*/false);
 
     web_data_service_->StartSyncableService();
diff --git a/components/cdm/renderer/android_key_systems.cc b/components/cdm/renderer/android_key_systems.cc
index e5b802e..280be28 100644
--- a/components/cdm/renderer/android_key_systems.cc
+++ b/components/cdm/renderer/android_key_systems.cc
@@ -16,8 +16,6 @@
 #include "media/media_buildflags.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
-#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
-
 using media::EmeConfigRule;
 using media::EmeFeatureSupport;
 using media::EmeInitDataType;
diff --git a/components/download/internal/common/download_response_handler.cc b/components/download/internal/common/download_response_handler.cc
index a0080bd0..5921bf4 100644
--- a/components/download/internal/common/download_response_handler.cc
+++ b/components/download/internal/common/download_response_handler.cc
@@ -74,6 +74,7 @@
       download_source_(download_source),
       has_strong_validators_(false),
       is_partial_request_(save_info_->offset > 0),
+      completed_(false),
       abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE) {
   if (!is_parallel_request) {
     RecordDownloadCountWithSource(UNTHROTTLED_COUNT, download_source);
@@ -201,6 +202,10 @@
 
 void DownloadResponseHandler::OnComplete(
     const network::URLLoaderCompletionStatus& status) {
+  if (completed_)
+    return;
+
+  completed_ = true;
   DownloadInterruptReason reason = HandleRequestCompletionStatus(
       static_cast<net::Error>(status.error_code), has_strong_validators_,
       cert_status_, abort_reason_);
diff --git a/components/download/public/common/download_response_handler.h b/components/download/public/common/download_response_handler.h
index 0948745..f5de03c1 100644
--- a/components/download/public/common/download_response_handler.h
+++ b/components/download/public/common/download_response_handler.h
@@ -93,6 +93,7 @@
   bool has_strong_validators_;
   GURL origin_;
   bool is_partial_request_;
+  bool completed_;
 
   // The abort reason if this class decides to block the download.
   DownloadInterruptReason abort_reason_;
diff --git a/components/favicon/core/favicon_service_impl.cc b/components/favicon/core/favicon_service_impl.cc
index 5689d76..ac492c8 100644
--- a/components/favicon/core/favicon_service_impl.cc
+++ b/components/favicon/core/favicon_service_impl.cc
@@ -46,7 +46,7 @@
     // Don't save if the scale isn't one of supported favicon scales.
     if (!base::ContainsValue(favicon_scales, image_reps[i].scale()))
       continue;
-    bitmaps.push_back(image_reps[i].sk_bitmap());
+    bitmaps.push_back(image_reps[i].GetBitmap());
   }
   return bitmaps;
 }
diff --git a/components/favicon_base/favicon_util.cc b/components/favicon_base/favicon_util.cc
index e957bc4..c6d6c22 100644
--- a/components/favicon_base/favicon_util.cc
+++ b/components/favicon_base/favicon_util.cc
@@ -239,8 +239,7 @@
   for (size_t i = 0; i < resized_image_skia_reps.size(); ++i) {
     scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
     if (gfx::PNGCodec::EncodeBGRASkBitmap(
-            resized_image_skia_reps[i].sk_bitmap(),
-            false,
+            resized_image_skia_reps[i].GetBitmap(), false,
             &png_bytes->data())) {
       png_reps.push_back(
           gfx::ImagePNGRep(png_bytes, resized_image_skia_reps[i].scale()));
diff --git a/components/favicon_base/select_favicon_frames_unittest.cc b/components/favicon_base/select_favicon_frames_unittest.cc
index c6cf2d5b..f405230 100644
--- a/components/favicon_base/select_favicon_frames_unittest.cc
+++ b/components/favicon_base/select_favicon_frames_unittest.cc
@@ -53,8 +53,7 @@
 
 SkColor GetColor(const gfx::ImageSkia& image, float scale,
                  int x = -1, int y = -1) {
-  const SkBitmap& bitmap =
-      image.GetRepresentation(scale).sk_bitmap();
+  const SkBitmap& bitmap = image.GetRepresentation(scale).GetBitmap();
   if (x == -1)
     x = bitmap.width() / 2;
   if (y == -1)
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 10a81cc..96e6a6d 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -591,8 +591,14 @@
 
   // The autofill manager will be repopulated again when the credentials
   // are retrieved.
-  for (PasswordManagerDriver* driver : drivers)
-    driver->GetPasswordAutofillManager()->DeleteFillData();
+  for (PasswordManagerDriver* driver : drivers) {
+    // GetPasswordAutofillManager() is returning nullptr in iOS Chrome, since
+    // PasswordAutofillManager is not instantiated on iOS Chrome.
+    // See //ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
+    if (driver->GetPasswordAutofillManager()) {
+      driver->GetPasswordAutofillManager()->DeleteFillData();
+    }
+  }
 }
 
 void PasswordManager::DropFormManagers() {
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc
index 56d14987..d1b4d81 100644
--- a/components/payments/core/features.cc
+++ b/components/payments/core/features.cc
@@ -11,9 +11,6 @@
     "ReturnGooglePayInBasicCard", base::FEATURE_DISABLED_BY_DEFAULT};
 
 #if defined(OS_IOS)
-const base::Feature kWebPayments{"WebPayments",
-                                 base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kWebPaymentsNativeApps{"WebPaymentsNativeApps",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
diff --git a/components/payments/core/features.h b/components/payments/core/features.h
index 50e411e..45a85991 100644
--- a/components/payments/core/features.h
+++ b/components/payments/core/features.h
@@ -15,9 +15,6 @@
 extern const base::Feature kReturnGooglePayInBasicCard;
 
 #if defined(OS_IOS)
-// Used to control the state of the Payment Request API feature.
-extern const base::Feature kWebPayments;
-
 // Used to control the support for iOS third party apps as payment methods.
 extern const base::Feature kWebPaymentsNativeApps;
 #endif
diff --git a/components/previews/core/previews_experiments.cc b/components/previews/core/previews_experiments.cc
index 844069e..9447c98 100644
--- a/components/previews/core/previews_experiments.cc
+++ b/components/previews/core/previews_experiments.cc
@@ -229,6 +229,10 @@
   return base::FeatureList::IsEnabled(features::kPreviews);
 }
 
+bool IsPreviewsOmniboxUiEnabled() {
+  return base::FeatureList::IsEnabled(features::kAndroidOmniboxPreviewsBadge);
+}
+
 bool IsOfflinePreviewsEnabled() {
   return base::FeatureList::IsEnabled(features::kOfflinePreviews);
 }
diff --git a/components/previews/core/previews_experiments.h b/components/previews/core/previews_experiments.h
index 320e5a6..ef63d0b 100644
--- a/components/previews/core/previews_experiments.h
+++ b/components/previews/core/previews_experiments.h
@@ -123,6 +123,9 @@
 // Whether any previews are allowed. Acts as a kill-switch or holdback check.
 bool ArePreviewsAllowed();
 
+// Whether the Previews UI is in the omnibox instead of an infobar.
+bool IsPreviewsOmniboxUiEnabled();
+
 // Whether the preview type is enabled.
 bool IsOfflinePreviewsEnabled();
 bool IsClientLoFiEnabled();
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc
index e17a6d2..5643779 100644
--- a/components/safe_browsing/web_ui/safe_browsing_ui.cc
+++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -178,6 +178,7 @@
   if (webui_instances_.empty()) {
     ClearCSBRRsSent();
     ClearClientDownloadRequestsSent();
+    ClearClientDownloadResponsesReceived();
     ClearPGEvents();
     ClearPGPings();
     ClearLogMessages();
diff --git a/components/security_interstitials/core/browser/resources/list_of_interstitials.html b/components/security_interstitials/core/browser/resources/list_of_interstitials.html
index c724b31..dae9e63 100644
--- a/components/security_interstitials/core/browser/resources/list_of_interstitials.html
+++ b/components/security_interstitials/core/browser/resources/list_of_interstitials.html
@@ -90,6 +90,9 @@
       <a href="quietsafebrowsing?type=unwanted">Malicious Unwanted Software</a>
     </li>
     <li>
+      <a href="quietsafebrowsing?type=billing">Billing</a>
+    </li>
+    <li>
       <a href="quietsafebrowsing?type=giant">Giant</a>
     </li>
   </ul>
diff --git a/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc b/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
index cd06cb8..e8b9528 100644
--- a/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
+++ b/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
@@ -71,8 +71,7 @@
       PopulatePhishingLoadTimeData(load_time_data);
       break;
     case BaseSafeBrowsingErrorUI::SB_REASON_BILLING:
-      // This is not currently handled in WebView.
-      NOTREACHED();
+      PopulateBillingLoadTimeData(load_time_data);
       break;
   }
 
@@ -148,6 +147,16 @@
       l10n_util::GetStringUTF16(IDS_PHISHING_WEBVIEW_EXPLANATION_PARAGRAPH));
 }
 
+void SafeBrowsingQuietErrorUI::PopulateBillingLoadTimeData(
+    base::DictionaryValue* load_time_data) {
+  load_time_data->SetBoolean("phishing", false);
+  load_time_data->SetString(
+      "heading", l10n_util::GetStringUTF16(IDS_BILLING_WEBVIEW_HEADING));
+  load_time_data->SetString(
+      "explanationParagraph",
+      l10n_util::GetStringUTF16(IDS_BILLING_WEBVIEW_EXPLANATION_PARAGRAPH));
+}
+
 int SafeBrowsingQuietErrorUI::GetHTMLTemplateId() const {
   return IDR_SECURITY_INTERSTITIAL_QUIET_HTML;
 }
diff --git a/components/security_interstitials/core/safe_browsing_quiet_error_ui.h b/components/security_interstitials/core/safe_browsing_quiet_error_ui.h
index db2fe31..51861a2 100644
--- a/components/security_interstitials/core/safe_browsing_quiet_error_ui.h
+++ b/components/security_interstitials/core/safe_browsing_quiet_error_ui.h
@@ -50,6 +50,7 @@
   void PopulateMalwareLoadTimeData(base::DictionaryValue* load_time_data);
   void PopulateHarmfulLoadTimeData(base::DictionaryValue* load_time_data);
   void PopulatePhishingLoadTimeData(base::DictionaryValue* load_time_data);
+  void PopulateBillingLoadTimeData(base::DictionaryValue* load_time_data);
 
   bool is_giant_webview_;
 
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp
index 2b2ca8d..2be55d3 100644
--- a/components/security_interstitials_strings.grdp
+++ b/components/security_interstitials_strings.grdp
@@ -311,6 +311,12 @@
   <message name="IDS_HARMFUL_WEBVIEW_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page. Allows the user to proceed using a link.">
     This content might try to install deceptive apps that pretend to be something else or collect data that may be used to track you. <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>Show anyway<ph name="END_LINK">&lt;/a&gt;</ph>
   </message>
+  <message name="IDS_BILLING_WEBVIEW_HEADING" desc="Title of a security warning. Shown when the user wants to visit a site that may trick them into signing up for a recurring charge to their mobile phone plan. 'Potential' indicates likelihood. 'charges' refers to financial charges to user's mobile phone plan.">
+    Potential charges ahead.
+  </message>
+  <message name="IDS_BILLING_WEBVIEW_EXPLANATION_PARAGRAPH" desc="Body of a security warning. Shown when the user wants to visit a site that may trick them into signing up for a recurring charge to their mobile phone plan. 'charges' refers to financial charges to user's mobile phone plan. 'not obvious' means the site may, for example, include a pricing disclosure in hard-to-see text.">
+    These charges could be one-time or recurring and may not be obvious. <ph name="BEGIN_LINK">&lt;a href="#" id="proceed-link"&gt;</ph>Show anyway<ph name="END_LINK">&lt;/a&gt;</ph>
+  </message>
 
   <message name="IDS_CONNECTION_HELP_SHOW_MORE" desc="The button label to expand sections for the chrome://connection-help site. Paired with IDS_CONNECTION_HELP_SHOW_LESS">
     Show More
diff --git a/components/test/data/autofill/credit_card_upload_form_address_and_cc.html b/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
index 20db0a2..fef9707 100644
--- a/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
+++ b/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
@@ -27,6 +27,13 @@
     <input type="text" name="cc_year_exp" placeholder="YYYY" autocomplete="cc-exp-year"></div>
     <div>CVC: <input name="cc_cvc" autocomplete="cc-csc"></div>
     <hr>
+    Test Dropdown Field: <select id="test_dropdown">
+      <option value="dropdown_1">Test Option 1</option>
+      <option value="dropdown_2">Test Option 2</option>
+      <option value="dropdown_3">Test Option 3</option>
+      <option value="dropdown_4">Test Option 4</option>
+    </select>
+    <hr>
     <button id="fill_form" type="button">Fill entire form with default (MasterCard) values</button>
     <button id="fill_form_delay" type="button">Fill out the name field after 3 seconds</button>
     <button id="fill_invalid_cvc" type="button">Fill the CVC field with an invalid value</button>
diff --git a/content/browser/browsing_instance.cc b/content/browser/browsing_instance.cc
index 9b24ae58..07a6aa1 100644
--- a/content/browser/browsing_instance.cc
+++ b/content/browser/browsing_instance.cc
@@ -44,33 +44,10 @@
   return instance;
 }
 
-scoped_refptr<SiteInstanceImpl>
-BrowsingInstance::GetDefaultSubframeSiteInstance() {
-  // This should only be used for --top-document-isolation mode.
-  CHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
-  if (!default_subframe_site_instance_) {
-    SiteInstanceImpl* instance = new SiteInstanceImpl(this);
-    instance->set_process_reuse_policy(
-        SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS);
-
-    // TODO(nick): This is a hack for now.
-    instance->SetSite(GURL("http://web-subframes.invalid"));
-
-    default_subframe_site_instance_ = instance;
-  }
-
-  return base::WrapRefCounted(default_subframe_site_instance_);
-}
-
 void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) {
   DCHECK(site_instance->browsing_instance_.get() == this);
   DCHECK(site_instance->HasSite());
 
-  // Don't register the default subframe SiteInstance, to prevent it from being
-  // returned by GetSiteInstanceForURL.
-  if (default_subframe_site_instance_ == site_instance)
-    return;
-
   std::string site = site_instance->GetSiteURL().possibly_invalid_spec();
 
   // Only register if we don't have a SiteInstance for this site already.
@@ -98,8 +75,6 @@
     // Matches, so erase it.
     site_instance_map_.erase(i);
   }
-  if (default_subframe_site_instance_ == site_instance)
-    default_subframe_site_instance_ = nullptr;
 }
 
 BrowsingInstance::~BrowsingInstance() {
diff --git a/content/browser/browsing_instance.h b/content/browser/browsing_instance.h
index 2e17bf8..118f1781b 100644
--- a/content/browser/browsing_instance.h
+++ b/content/browser/browsing_instance.h
@@ -87,12 +87,6 @@
   // SiteInstance per site.
   scoped_refptr<SiteInstanceImpl> GetSiteInstanceForURL(const GURL& url);
 
-  // Returns a SiteInstance that should be used for subframes when an oopif is
-  // required, but a dedicated process is not. This SiteInstance will be created
-  // if it doesn't already exist. There is at most one of these per
-  // BrowsingInstance.
-  scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
-
   // Adds the given SiteInstance to our map, to ensure that we do not create
   // another SiteInstance for the same site.
   void RegisterSiteInstance(SiteInstanceImpl* site_instance);
@@ -131,8 +125,6 @@
   // Number of WebContentses currently using this BrowsingInstance.
   size_t active_contents_count_;
 
-  SiteInstanceImpl* default_subframe_site_instance_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(BrowsingInstance);
 };
 
diff --git a/content/browser/devtools/devtools_video_consumer.cc b/content/browser/devtools/devtools_video_consumer.cc
index f06866c3..1dd814c 100644
--- a/content/browser/devtools/devtools_video_consumer.cc
+++ b/content/browser/devtools/devtools_video_consumer.cc
@@ -57,7 +57,7 @@
   skbitmap.allocN32Pixels(frame->visible_rect().width(),
                           frame->visible_rect().height());
   cc::SkiaPaintCanvas canvas(skbitmap);
-  renderer.Copy(frame, &canvas, media::Context3D());
+  renderer.Copy(frame, &canvas, media::Context3D(), nullptr);
   return skbitmap;
 }
 
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc
index 5bf1859..0164e28 100644
--- a/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -175,6 +175,7 @@
   storage_partition_ =
       static_cast<StoragePartitionImpl*>(process_host->GetStoragePartition());
   DCHECK(storage_partition_);
+  browser_context_ = process_host->GetBrowserContext();
   context_ = static_cast<ServiceWorkerContextWrapper*>(
       storage_partition_->GetServiceWorkerContext());
 }
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index cecd091..6979a2f 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -6013,6 +6013,21 @@
   EXPECT_EQ(0, controller.GetCurrentEntryIndex());
 }
 
+// Make sure that a 304 response to a navigation aborts the navigation.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, NavigateTo304) {
+  // URL that just returns a blank page.
+  GURL initial_url = embedded_test_server()->GetURL("/set-header");
+  // URL that returns a response with a 304 status code.
+  GURL not_modified_url = embedded_test_server()->GetURL("/echo?status=304");
+
+  EXPECT_TRUE(NavigateToURL(shell(), initial_url));
+  EXPECT_EQ(initial_url, shell()->web_contents()->GetVisibleURL());
+
+  // The navigation should be aborted.
+  EXPECT_FALSE(NavigateToURL(shell(), not_modified_url));
+  EXPECT_EQ(initial_url, shell()->web_contents()->GetVisibleURL());
+}
+
 // Ensure that we do not corrupt a NavigationEntry's PageState if two forward
 // navigations compete in different frames.  See https://crbug.com/623319.
 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 1281c89..dffe5f9d 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1353,29 +1353,10 @@
       return SiteInstanceDescriptor(opener_frame->GetSiteInstance());
   }
 
-  if (!frame_tree_node_->IsMainFrame() &&
-      SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
-      !SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
-                                                         dest_url)) {
-    if (GetContentClient()
-            ->browser()
-            ->ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-                dest_url, current_instance)) {
-      return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance());
-    }
-
-    // This is a cross-site subframe of a non-isolated origin, so place this
-    // frame in the default subframe site instance.
-    return SiteInstanceDescriptor(
-        browser_context, dest_url,
-        SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME);
-  }
-
   // Keep subframes in the parent's SiteInstance unless a dedicated process is
   // required for either the parent or the subframe's destination URL.  This
   // isn't a strict invariant but rather a heuristic to avoid unnecessary
-  // OOPIFs; see https://crbug.com/711006.  Note that this shouldn't apply to
-  // TopDocumentIsolation, so do this after TDI checks above.
+  // OOPIFs; see https://crbug.com/711006.
   //
   // TODO(alexmos): Remove this check after fixing https://crbug.com/787576.
   if (!frame_tree_node_->IsMainFrame()) {
@@ -1476,13 +1457,6 @@
     return true;
   }
 
-  if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
-      (!frame_tree_node_->IsMainFrame() ||
-       rfh->GetSiteInstance()->IsDefaultSubframeSiteInstance())) {
-    // Always attempt a transfer in these cases.
-    return true;
-  }
-
   // If the destination URL is not same-site with current RenderFrameHost and
   // doesn't require a dedicated process (see above), but it is same-site with
   // the opener RenderFrameHost, attempt a transfer so that the destination URL
@@ -1515,9 +1489,6 @@
   if (descriptor.relation == SiteInstanceRelation::RELATED)
     return current_instance->GetRelatedSiteInstance(descriptor.dest_url);
 
-  if (descriptor.relation == SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME)
-    return current_instance->GetDefaultSubframeSiteInstance();
-
   // At this point we know an unrelated site instance must be returned. First
   // check if the candidate matches.
   if (candidate_instance &&
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index 499e3cd..0ce014d 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -495,8 +495,6 @@
     UNRELATED,
     // A SiteInstance in the same browsing instance as the current.
     RELATED,
-    // The default subframe SiteInstance for the current browsing instance.
-    RELATED_DEFAULT_SUBFRAME,
   };
 
   // Stores information regarding a SiteInstance targeted at a specific URL to
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 26f09ff..286b17e 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -69,6 +69,7 @@
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 #include "net/http/http_content_disposition.h"
 #include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
 #include "net/ssl/ssl_info.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/redirect_util.h"
@@ -1044,6 +1045,16 @@
               response_loader_binding_.Unbind());
     }
 
+    // 304 responses should abort the navigation, rather than display the page.
+    // This needs to be after the URLLoader has been moved to
+    // |url_loader_client_endpoints| in order to abort the request, to avoid
+    // receiving unexpected call.
+    if (head.headers &&
+        head.headers->response_code() == net::HTTP_NOT_MODIFIED) {
+      OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+      return;
+    }
+
     bool is_download;
     bool is_stream;
     // If there is not an explicit PreviewsState set on the request, turn
diff --git a/content/browser/process_internals/process_internals_handler_impl.cc b/content/browser/process_internals/process_internals_handler_impl.cc
index dbd0e579..b295109e 100644
--- a/content/browser/process_internals/process_internals_handler_impl.cc
+++ b/content/browser/process_internals/process_internals_handler_impl.cc
@@ -4,6 +4,10 @@
 
 #include "content/browser/process_internals/process_internals_handler_impl.h"
 
+#include <utility>
+#include <vector>
+
+#include "base/strings/string_piece.h"
 #include "content/browser/process_internals/process_internals.mojom.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_contents.h"
@@ -21,8 +25,6 @@
   std::vector<base::StringPiece> modes;
   if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
     modes.push_back("Site Per Process");
-  if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled())
-    modes.push_back("Top Document Isolation");
   if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
     modes.push_back("Isolate Origins");
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 96eb657..0e6b97a 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2606,8 +2606,6 @@
     std::string site_isolation_mode;
     if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
       site_isolation_mode += "spp ";
-    if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled())
-      site_isolation_mode += "tdi ";
     if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
       site_isolation_mode += "io ";
     if (site_isolation_mode.empty())
@@ -3959,12 +3957,6 @@
       render_process_host = GetSoleProcessHostForSite(
           browser_context, site_url, site_instance->lock_url());
       break;
-    case SiteInstanceImpl::ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS:
-      DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
-      DCHECK(!site_instance->is_for_service_worker());
-      render_process_host = GetDefaultSubframeProcessHost(
-          browser_context, site_instance, is_for_guests_only);
-      break;
     case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE:
       render_process_host =
           FindReusableProcessHostForSiteInstance(site_instance);
@@ -4499,23 +4491,6 @@
 }
 
 // static
-RenderProcessHost* RenderProcessHostImpl::GetDefaultSubframeProcessHost(
-    BrowserContext* browser_context,
-    SiteInstanceImpl* site_instance,
-    bool is_for_guests_only) {
-  DefaultSubframeProcessHostHolder* holder =
-      static_cast<DefaultSubframeProcessHostHolder*>(
-          browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey));
-  if (!holder) {
-    holder = new DefaultSubframeProcessHostHolder(browser_context);
-    browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey,
-                                 base::WrapUnique(holder));
-  }
-
-  return holder->GetProcessHost(site_instance, is_for_guests_only);
-}
-
-// static
 RenderProcessHost*
 RenderProcessHostImpl::FindReusableProcessHostForSiteInstance(
     SiteInstanceImpl* site_instance) {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 95c1a47..bba58ee 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -318,7 +318,6 @@
   // handles all cases.  These cases include:
   // - process-per-site: see
   //   RegisterSoleProcessHostForSite/GetSoleProcessHostForSite.
-  // - TDI: see GetDefaultSubframeProcessHost.
   // - REUSE_PENDING_OR_COMMITTED reuse policy (for ServiceWorkers and OOPIFs):
   //   see FindReusableProcessHostForSiteInstance.
   // - normal process reuse when over process limit:  see
@@ -578,12 +577,6 @@
                                base::TimeTicks start,
                                base::TimeTicks end);
 
-  // Returns the default subframe RenderProcessHost to use for |site_instance|.
-  static RenderProcessHost* GetDefaultSubframeProcessHost(
-      BrowserContext* browser_context,
-      SiteInstanceImpl* site_instance,
-      bool is_for_guests_only);
-
   // Get an existing RenderProcessHost associated with the given browser
   // context, if possible.  The renderer process is chosen randomly from
   // suitable renderers that share the same context and type (determined by the
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index ea110d0b..7c41d084 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -48,7 +48,8 @@
   response->status_code = 200;
   response->status_text = "OK";
   response->response_type = network::mojom::FetchResponseType::kDefault;
-  response_callback->OnResponse(std::move(response), base::TimeTicks::Now());
+  response_callback->OnResponse(
+      std::move(response), blink::mojom::ServiceWorkerFetchEventTiming::New());
   std::move(finish_callback)
       .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
            base::TimeTicks::Now());
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index f2ce807e..59bd5583 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -325,25 +325,27 @@
   }
 
   // Implements blink::mojom::ServiceWorkerFetchResponseCallback.
-  void OnResponse(blink::mojom::FetchAPIResponsePtr response,
-                  base::TimeTicks dispatch_event_time) override {
+  void OnResponse(
+      blink::mojom::FetchAPIResponsePtr response,
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
     HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                    std::move(response), nullptr /* body_as_stream */,
-                   FetchEventResult::kGotResponse, dispatch_event_time);
+                   FetchEventResult::kGotResponse, std::move(timing));
   }
   void OnResponseStream(
       blink::mojom::FetchAPIResponsePtr response,
       blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
-      base::TimeTicks dispatch_event_time) override {
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
     HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                    std::move(response), std::move(body_as_stream),
-                   FetchEventResult::kGotResponse, dispatch_event_time);
+                   FetchEventResult::kGotResponse, std::move(timing));
   }
-  void OnFallback(base::TimeTicks dispatch_event_time) override {
+  void OnFallback(
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override {
     HandleResponse(fetch_dispatcher_, version_, fetch_event_id_,
                    blink::mojom::FetchAPIResponse::New(),
                    nullptr /* body_as_stream */,
-                   FetchEventResult::kShouldFallback, dispatch_event_time);
+                   FetchEventResult::kShouldFallback, std::move(timing));
   }
 
  private:
@@ -356,10 +358,10 @@
       blink::mojom::FetchAPIResponsePtr response,
       blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
       FetchEventResult fetch_result,
-      base::TimeTicks dispatch_event_time) {
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
     if (!version->FinishRequest(fetch_event_id.value(),
                                 fetch_result == FetchEventResult::kGotResponse,
-                                dispatch_event_time))
+                                timing->dispatch_event_time))
       NOTREACHED() << "Should only receive one reply per event";
     // |fetch_dispatcher| is null if the URLRequest was killed.
     if (!fetch_dispatcher)
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index 9dfff649..6b10fecf 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -137,7 +137,8 @@
     response->status_text = response_head_.headers->GetStatusText();
     response->response_type = response_head_.response_type;
     response_callback_->OnResponseStream(
-        std::move(response), std::move(stream_handle), base::TimeTicks::Now());
+        std::move(response), std::move(stream_handle),
+        blink::mojom::ServiceWorkerFetchEventTiming::New());
     std::move(finish_callback_)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
              base::TimeTicks::Now());
@@ -239,8 +240,9 @@
   // providing the response to the fetch event.
   void DeferResponse() { response_mode_ = ResponseMode::kDeferredResponse; }
   void FinishRespondWith() {
-    response_callback_->OnResponse(OkResponse(nullptr /* blob_body */),
-                                   base::TimeTicks::Now());
+    response_callback_->OnResponse(
+        OkResponse(nullptr /* blob_body */),
+        blink::mojom::ServiceWorkerFetchEventTiming::New());
     response_callback_.FlushForTesting();
     std::move(finish_callback_)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
@@ -288,28 +290,32 @@
             std::move(response_callback), std::move(finish_callback));
         break;
       case ResponseMode::kBlob:
-        response_callback->OnResponse(OkResponse(std::move(blob_body_)),
-                                      base::TimeTicks::Now());
+        response_callback->OnResponse(
+            OkResponse(std::move(blob_body_)),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(finish_callback)
             .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
                  base::TimeTicks::Now());
         break;
       case ResponseMode::kStream:
-        response_callback->OnResponseStream(OkResponse(nullptr /* blob_body */),
-                                            std::move(stream_handle_),
-                                            base::TimeTicks::Now());
+        response_callback->OnResponseStream(
+            OkResponse(nullptr /* blob_body */), std::move(stream_handle_),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(finish_callback)
             .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
                  base::TimeTicks::Now());
         break;
       case ResponseMode::kFallbackResponse:
-        response_callback->OnFallback(base::TimeTicks::Now());
+        response_callback->OnFallback(
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(finish_callback)
             .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
                  base::TimeTicks::Now());
         break;
       case ResponseMode::kErrorResponse:
-        response_callback->OnResponse(ErrorResponse(), base::TimeTicks::Now());
+        response_callback->OnResponse(
+            ErrorResponse(),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(finish_callback)
             .Run(blink::mojom::ServiceWorkerEventStatus::REJECTED,
                  base::TimeTicks::Now());
@@ -343,13 +349,15 @@
         break;
       case ResponseMode::kEarlyResponse:
         finish_callback_ = std::move(finish_callback);
-        response_callback->OnResponse(OkResponse(nullptr /* blob_body */),
-                                      base::TimeTicks::Now());
+        response_callback->OnResponse(
+            OkResponse(nullptr /* blob_body */),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         // Now the caller must call FinishWaitUntil() to finish the event.
         break;
       case ResponseMode::kRedirect:
-        response_callback->OnResponse(RedirectResponse(redirected_url_.spec()),
-                                      base::TimeTicks::Now());
+        response_callback->OnResponse(
+            RedirectResponse(redirected_url_.spec()),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(finish_callback)
             .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
                  base::TimeTicks::Now());
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 0f7bd63..d448857 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -491,7 +491,8 @@
   }
 
   void Respond() {
-    response_callback_->OnResponse(MakeOkResponse(), base::TimeTicks::Now());
+    response_callback_->OnResponse(
+        MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
     std::move(finish_callback_)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
              base::TimeTicks::Now());
@@ -708,7 +709,8 @@
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
       override {
     context()->RemoveProviderHost(mock_render_process_id(), kProviderID);
-    response_callback->OnResponse(MakeOkResponse(), base::TimeTicks::Now());
+    response_callback->OnResponse(
+        MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
     std::move(finish_callback)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
              base::TimeTicks::Now());
@@ -795,7 +797,9 @@
     // Mojo, we give it a dummy value.
     auto dummy_request = mojo::MakeRequest(&response->blob->blob);
 
-    response_callback->OnResponse(std::move(response), base::TimeTicks::Now());
+    response_callback->OnResponse(
+        std::move(response),
+        blink::mojom::ServiceWorkerFetchEventTiming::New());
     std::move(finish_callback)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
              base::TimeTicks::Now());
@@ -890,7 +894,8 @@
     blink::mojom::FetchAPIResponsePtr response = MakeOkResponse();
     response->headers = MakeHeaders();
     response_callback->OnResponseStream(
-        std::move(response), std::move(stream_handle_), base::TimeTicks::Now());
+        std::move(response), std::move(stream_handle_),
+        blink::mojom::ServiceWorkerFetchEventTiming::New());
     std::move(finish_callback)
         .Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED,
              base::TimeTicks::Now());
@@ -1364,7 +1369,8 @@
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
       override {
     finish_callback_ = std::move(finish_callback);
-    response_callback->OnResponse(MakeOkResponse(), base::TimeTicks::Now());
+    response_callback->OnResponse(
+        MakeOkResponse(), blink::mojom::ServiceWorkerFetchEventTiming::New());
   }
 
  private:
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index 2f27e67..c3b4522 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -273,11 +273,6 @@
       origin_lock);
 }
 
-scoped_refptr<SiteInstanceImpl>
-SiteInstanceImpl::GetDefaultSubframeSiteInstance() {
-  return browsing_instance_->GetDefaultSubframeSiteInstance();
-}
-
 bool SiteInstanceImpl::RequiresDedicatedProcess() {
   if (!has_site_)
     return false;
@@ -285,11 +280,6 @@
   return DoesSiteRequireDedicatedProcess(GetBrowserContext(), site_);
 }
 
-bool SiteInstanceImpl::IsDefaultSubframeSiteInstance() const {
-  return process_reuse_policy_ ==
-         ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS;
-}
-
 void SiteInstanceImpl::IncrementActiveFrameCount() {
   active_frame_count_++;
 }
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 1fd745d..d72334b 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -64,7 +64,6 @@
   bool IsRelatedSiteInstance(const SiteInstance* instance) override;
   size_t GetRelatedActiveContentsCount() override;
   bool RequiresDedicatedProcess() override;
-  bool IsDefaultSubframeSiteInstance() const override;
 
   // The policy to apply when selecting a RenderProcessHost for the
   // SiteInstance. If no suitable RenderProcessHost for the SiteInstance exists
@@ -79,9 +78,6 @@
     // RenderProcessHost.
     PROCESS_PER_SITE,
 
-    // In this mode, subframes will be hosted in a designated RenderProcessHost.
-    USE_DEFAULT_SUBFRAME_PROCESS,
-
     // In this mode, the site will be rendered in a RenderProcessHost that is
     // already in use for the site, either for a pending navigation or a
     // committed navigation. If multiple such processes exist, ones that have
@@ -146,12 +142,6 @@
   // without resolving effective URLs.
   static GURL DetermineProcessLockURL(BrowserContext* context, const GURL& url);
 
-  // Returns the SiteInstance, related to this one, that should be used
-  // for subframes when an oopif is required, but a dedicated process is not.
-  // This SiteInstance will be created if it doesn't already exist. There is
-  // at most one of these per BrowsingInstance.
-  scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
-
   // Set the web site that this SiteInstance is rendering pages for.
   // This includes the scheme and registered domain, but not the port.  If the
   // URL does not have a valid registered domain, then the full hostname is
@@ -259,11 +249,6 @@
   // Used to restrict a process' origin access rights.
   void LockToOriginIfNeeded();
 
-  // This gets the render process to use for default subframe site instances.
-  RenderProcessHost* GetDefaultSubframeProcessHost(
-      BrowserContext* browser_context,
-      bool is_for_guests_only);
-
   // An object used to construct RenderProcessHosts.
   static const RenderProcessHostFactory* g_render_process_host_factory_;
 
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index 412ca32b..901f6502 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -872,55 +872,6 @@
   EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, https_bar_url, fs_bar_url));
 }
 
-TEST_F(SiteInstanceTest, DefaultSubframeSiteInstance) {
-  if (AreAllSitesIsolatedForTesting())
-    return;  // --top-document-isolation is not possible.
-
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kTopDocumentIsolation);
-
-  std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
-  scoped_refptr<SiteInstanceImpl> main_instance =
-      SiteInstanceImpl::Create(browser_context.get());
-  scoped_refptr<SiteInstanceImpl> subframe_instance =
-      main_instance->GetDefaultSubframeSiteInstance();
-  int subframe_instance_id = subframe_instance->GetId();
-
-  EXPECT_NE(main_instance, subframe_instance);
-  EXPECT_EQ(subframe_instance, main_instance->GetDefaultSubframeSiteInstance());
-  EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
-  EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
-
-  EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
-  EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
-  // Free the subframe instance.
-  subframe_instance = nullptr;
-  EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
-  EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
-  // Calling GetDefaultSubframeSiteInstance again should return a new
-  // SiteInstance with a different ID from the original.
-  subframe_instance = main_instance->GetDefaultSubframeSiteInstance();
-  EXPECT_NE(subframe_instance->GetId(), subframe_instance_id);
-  EXPECT_FALSE(main_instance->IsDefaultSubframeSiteInstance());
-  EXPECT_TRUE(subframe_instance->IsDefaultSubframeSiteInstance());
-  EXPECT_EQ(subframe_instance->GetDefaultSubframeSiteInstance(),
-            subframe_instance);
-  EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
-  EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
-  // Free the main instance.
-  main_instance = nullptr;
-  EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
-  EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-
-  // Free the subframe instance, which should free the browsing instance.
-  subframe_instance = nullptr;
-  EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
-  EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
-}
-
 TEST_F(SiteInstanceTest, IsolatedOrigins) {
   GURL foo_url("http://www.foo.com");
   GURL isolated_foo_url("http://isolated.foo.com");
diff --git a/content/browser/top_document_isolation_browsertest.cc b/content/browser/top_document_isolation_browsertest.cc
deleted file mode 100644
index 6f6e7be..0000000
--- a/content/browser/top_document_isolation_browsertest.cc
+++ /dev/null
@@ -1,616 +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 <string>
-
-#include "base/command_line.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/common/content_features.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_frame_navigation_observer.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils_internal.h"
-#include "net/dns/mock_host_resolver.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class TopDocumentIsolationTest : public ContentBrowserTest {
- public:
-  TopDocumentIsolationTest() {}
-
- protected:
-  std::string DepictFrameTree(FrameTreeNode* node) {
-    return visualizer_.DepictFrameTree(node);
-  }
-
-  void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
-    ContentBrowserTest::SetUp();
-  }
-
-  void SetUpOnMainThread() override {
-    host_resolver()->AddRule("*", "127.0.0.1");
-    SetupCrossSiteRedirector(embedded_test_server());
-    ASSERT_TRUE(embedded_test_server()->Start());
-  }
-
-  FrameTreeNode* root() {
-    return static_cast<WebContentsImpl*>(shell()->web_contents())
-        ->GetFrameTree()
-        ->root();
-  }
-
-  void GoBack() {
-    TestNavigationObserver back_load_observer(shell()->web_contents());
-    shell()->web_contents()->GetController().GoBack();
-    back_load_observer.Wait();
-  }
-
-  Shell* OpenPopup(FrameTreeNode* opener, const std::string& url) {
-    GURL gurl =
-        opener->current_frame_host()->GetLastCommittedURL().Resolve(url);
-    return content::OpenPopup(opener, gurl, "_blank");
-  }
-
-  void RendererInitiatedNavigateToURL(FrameTreeNode* node, const GURL& url) {
-    TestFrameNavigationObserver nav_observer(node);
-    ASSERT_TRUE(
-        ExecuteScript(node, "window.location.href='" + url.spec() + "'"));
-    nav_observer.Wait();
-  }
-
- private:
-  FrameTreeVisualizer visualizer_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(TopDocumentIsolationTest);
-};
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, SameSiteDeeplyNested) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
-
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A\n"
-      "   |--Site A\n"
-      "   +--Site A\n"
-      "        |--Site A\n"
-      "        +--Site A\n"
-      "             +--Site A\n"
-      "Where A = http://a.com/",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteDeeplyNested) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b(c(d(b))))"));
-
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "        +--Site B -- proxies for A\n"
-      "             +--Site B -- proxies for A\n"
-      "                  +--Site B -- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, ReturnToTopSite) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b(a(c)))"));
-
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "        +--Site A -- proxies for B\n"
-      "             +--Site B -- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b(c(d)))"));
-
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "        +--Site B -- proxies for A\n"
-      "             +--Site B -- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  GURL ada_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(d(a))"));
-  RendererInitiatedNavigateToURL(root()->child_at(0)->child_at(0), ada_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "        +--Site A -- proxies for B\n"
-      "             +--Site B -- proxies for A\n"
-      "                  +--Site A -- proxies for B\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateToSubframeSite) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL ab_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b)"));
-  GURL ba_url(embedded_test_server()->GetURL(
-      "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
-
-  NavigateToURL(shell(), ab_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  NavigateToURL(shell(), ba_url);
-
-  EXPECT_EQ(
-      " Site C ------------ proxies for D\n"
-      "   |--Site D ------- proxies for C\n"
-      "   +--Site D ------- proxies for C\n"
-      "Where C = http://b.com/\n"
-      "      D = default subframe process",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
-                       NavigateToSubframeSiteWithPopup) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  // A(B) -> B(A), but while a separate B(A) popup exists.
-  GURL ab_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b)"));
-
-  NavigateToURL(shell(), ab_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  Shell* popup =
-      OpenPopup(root()->child_at(0), "/cross_site_iframe_factory.html?b(a)");
-  FrameTreeNode* popup_root =
-      static_cast<WebContentsImpl*>(popup->web_contents())
-          ->GetFrameTree()
-          ->root();
-
-  // This popup's main frame must stay in the default subframe siteinstance,
-  // since its opener (the b.com subframe) may synchronously script it. Note
-  // that the popup's subframe is same-site with window.top.opener.top, the
-  // a.com main frame of the tab. But --top-document-isolation does not
-  // currently place the popup subframe in the a.com process in this case.
-  EXPECT_EQ(
-      " Site B\n"
-      "   +--Site B\n"
-      "Where B = default subframe process",
-      DepictFrameTree(popup_root));
-
-  GURL ba_url(embedded_test_server()->GetURL(
-      "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
-  EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), ba_url));
-
-  // This navigation destroys the popup's opener, so we allow the main frame to
-  // commit in a top level process for b.com, in spite of the b.com popup in the
-  // default subframe process.
-  EXPECT_EQ(
-      " Site C ------------ proxies for B\n"
-      "   |--Site B ------- proxies for C\n"
-      "   +--Site B ------- proxies for C\n"
-      "Where B = default subframe process\n"
-      "      C = http://b.com/",
-      DepictFrameTree(root()));
-  EXPECT_EQ(
-      " Site B\n"
-      "   +--Site B\n"
-      "Where B = default subframe process",
-      DepictFrameTree(popup_root));
-
-  // Navigate the popup to a new site.
-  GURL c_url(embedded_test_server()->GetURL(
-      "c.com", "/cross_site_iframe_factory.html?c(c, c, c, c)"));
-  EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(popup, c_url));
-  EXPECT_EQ(
-      " Site D ------------ proxies for B\n"
-      "   |--Site D ------- proxies for B\n"
-      "   |--Site D ------- proxies for B\n"
-      "   |--Site D ------- proxies for B\n"
-      "   +--Site D ------- proxies for B\n"
-      "Where B = default subframe process\n"
-      "      D = http://c.com/",
-      DepictFrameTree(popup_root));
-  EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), c_url));
-  EXPECT_EQ(
-      " Site D\n"
-      "   |--Site D\n"
-      "   |--Site D\n"
-      "   |--Site D\n"
-      "   +--Site D\n"
-      "Where D = http://c.com/",
-      DepictFrameTree(popup_root));
-  EXPECT_EQ(
-      " Site D\n"
-      "   |--Site D\n"
-      "   |--Site D\n"
-      "   |--Site D\n"
-      "   +--Site D\n"
-      "Where D = http://c.com/",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
-                       NavigateToSubframeSiteWithPopup2) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  // A(B, C) -> C(A, B), but while a separate C(A) popup exists.
-  //
-  // This test is constructed so that c.com is the second site to commit in the
-  // default subframe SiteInstance, so the default subframe SiteInstance does
-  // not have a "c.com" as the value of GetSiteURL().
-  GURL abb_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(b, b)"));
-
-  NavigateToURL(shell(), abb_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   |--Site B ------- proxies for A\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  // A(B, B) -> A(B, C)
-  GURL c_url(embedded_test_server()->GetURL(
-      "c.com", "/cross_site_iframe_factory.html?c"));
-  NavigateFrameToURL(root()->child_at(1), c_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   |--Site B ------- proxies for A\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  // This test exercises what happens when the SiteURL of the default subframe
-  // siteinstance doesn't match the subframe site.
-  EXPECT_NE("c.com", root()
-                         ->child_at(1)
-                         ->current_frame_host()
-                         ->GetSiteInstance()
-                         ->GetSiteURL()
-                         .host());
-
-  // Subframe C creates C(A) popup.
-  Shell* popup =
-      OpenPopup(root()->child_at(1), "/cross_site_iframe_factory.html?c(a)");
-
-  FrameTreeNode* popup_root =
-      static_cast<WebContentsImpl*>(popup->web_contents())
-          ->GetFrameTree()
-          ->root();
-
-  // The popup must stay with its opener, in the default subframe process.
-  EXPECT_EQ(
-      " Site B\n"
-      "   +--Site B\n"
-      "Where B = default subframe process",
-      DepictFrameTree(popup_root));
-
-  GURL cab_url(embedded_test_server()->GetURL(
-      "c.com", "/cross_site_iframe_factory.html?c(a, b)"));
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), cab_url));
-    deleted_observer.WaitUntilDeleted();
-  }
-
-  // This c.com navigation currently breaks out of the default subframe process,
-  // even though that process houses a c.com pop-up.
-  EXPECT_EQ(
-      " Site C ------------ proxies for B\n"
-      "   |--Site B ------- proxies for C\n"
-      "   +--Site B ------- proxies for C\n"
-      "Where B = default subframe process\n"
-      "      C = http://c.com/",
-      DepictFrameTree(root()));
-
-  // c.com popup should remain where it was, in the subframe process.
-  EXPECT_EQ(
-      " Site B\n"
-      "   +--Site B\n"
-      "Where B = default subframe process",
-      DepictFrameTree(popup_root));
-  EXPECT_EQ(nullptr, popup_root->opener());
-
-  // If we navigate the popup to a new site, it ought to transfer processes.
-  GURL d_url(embedded_test_server()->GetURL(
-      "d.com", "/cross_site_iframe_factory.html?d"));
-  {
-    RenderFrameDeletedObserver deleted_observer(
-        popup_root->current_frame_host());
-    EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(popup, d_url));
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site D ------------ proxies for B\n"
-      "Where B = default subframe process\n"
-      "      D = http://d.com/",
-      DepictFrameTree(popup_root));
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    EXPECT_TRUE(NavigateToURLInSameBrowsingInstance(shell(), d_url));
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site D\n"
-      "Where D = http://d.com/",
-      DepictFrameTree(popup_root));
-  EXPECT_EQ(
-      " Site D\n"
-      "Where D = http://d.com/",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  // First, do a series of navigations.
-  GURL a_url = embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a");
-  GURL b_url = embedded_test_server()->GetURL(
-      "b.com", "/cross_site_iframe_factory.html?b");
-  GURL c_url = embedded_test_server()->GetURL(
-      "c.com", "/cross_site_iframe_factory.html?c");
-
-  // Browser-initiated navigation to a.com.
-  NavigateToURL(shell(), a_url);
-  EXPECT_EQ(
-      " Site A\n"
-      "Where A = http://a.com/",
-      DepictFrameTree(root()));
-
-  // Browser-initiated navigation to b.com.
-  {
-    // For any cross-process navigations, we must wait for the old RenderFrame
-    // to be deleted before calling DepictFrameTree, or else there's a chance
-    // the old SiteInstance could be listed while pending deletion.
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    NavigateToURL(shell(), b_url);
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site B\n"
-      "Where B = http://b.com/",
-      DepictFrameTree(root()));
-
-  // Renderer-initiated navigation back to a.com. This shouldn't swap processes.
-  RendererInitiatedNavigateToURL(root(), a_url);
-  EXPECT_EQ(
-      " Site B\n"
-      "Where B = http://b.com/",
-      DepictFrameTree(root()));
-
-  // Browser-initiated navigation to c.com.
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    NavigateToURL(shell(), c_url);
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site C\n"
-      "Where C = http://c.com/",
-      DepictFrameTree(root()));
-
-  // Now, navigate to a fourth site with iframes to the sites in the history.
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    NavigateToURL(shell(),
-                  embedded_test_server()->GetURL(
-                      "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
-    deleted_observer.WaitUntilDeleted();
-  }
-
-  EXPECT_EQ(
-      " Site D ------------ proxies for E\n"
-      "   |--Site E ------- proxies for D\n"
-      "   |--Site E ------- proxies for D\n"
-      "   +--Site E ------- proxies for D\n"
-      "Where D = http://d.com/\n"
-      "      E = default subframe process",
-      DepictFrameTree(root()));
-
-  // Now try going back.
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    GoBack();
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site C\n"
-      "Where C = http://c.com/",
-      DepictFrameTree(root()));
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    GoBack();
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site B\n"
-      "Where B = http://b.com/",
-      DepictFrameTree(root()));
-  GoBack();
-  EXPECT_EQ(
-      " Site B\n"
-      "Where B = http://b.com/",
-      DepictFrameTree(root()));
-  {
-    RenderFrameDeletedObserver deleted_observer(root()->current_frame_host());
-    GoBack();
-    deleted_observer.WaitUntilDeleted();
-  }
-  EXPECT_EQ(
-      " Site A\n"
-      "Where A = http://a.com/",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteAtLevelTwo) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "a.com", "/cross_site_iframe_factory.html?a(a(b, a))"));
-
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site A ------- proxies for B\n"
-      "        |--Site B -- proxies for A\n"
-      "        +--Site A -- proxies for B\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  GURL c_url(embedded_test_server()->GetURL(
-      "c.com", "/cross_site_iframe_factory.html?c"));
-  NavigateFrameToURL(root()->child_at(0)->child_at(1), c_url);
-
-  // This navigation should complete in the default subframe siteinstance.
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site A ------- proxies for B\n"
-      "        |--Site B -- proxies for A\n"
-      "        +--Site B -- proxies for A\n"
-      "Where A = http://a.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-}
-
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, PopupAndRedirection) {
-  if (content::AreAllSitesIsolatedForTesting())
-    return;  // Top Document Isolation is disabled in this mode.
-
-  GURL main_url(embedded_test_server()->GetURL(
-      "page.com", "/cross_site_iframe_factory.html?page(adnetwork)"));
-
-  // User opens page on page.com which contains a subframe from adnetwork.com.
-  NavigateToURL(shell(), main_url);
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://page.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  GURL ad_url(embedded_test_server()->GetURL(
-      "ad.com", "/cross_site_iframe_factory.html?ad"));
-
-  // adnetwork.com retrieves an ad from advertiser (ad.com) and redirects the
-  // subframe to ad.com.
-  RendererInitiatedNavigateToURL(root()->child_at(0), ad_url);
-
-  // The subframe still uses the default subframe SiteInstance after navigation.
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://page.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-
-  // User clicks the ad in the subframe, which opens a popup on the ad
-  // network's domain.
-  GURL popup_url(embedded_test_server()->GetURL(
-      "adnetwork.com", "/cross_site_iframe_factory.html?adnetwork"));
-  Shell* popup = OpenPopup(root()->child_at(0), popup_url.spec());
-
-  FrameTreeNode* popup_root =
-      static_cast<WebContentsImpl*>(popup->web_contents())
-          ->GetFrameTree()
-          ->root();
-
-  // It's ok for the popup to break out of the subframe process because it's
-  // currently cross-site from its opener frame.
-  EXPECT_EQ(
-      " Site C ------------ proxies for B\n"
-      "Where B = default subframe process\n"
-      "      C = http://adnetwork.com/",
-      DepictFrameTree(popup_root));
-
-  EXPECT_EQ(
-      " Site A ------------ proxies for B C\n"
-      "   +--Site B ------- proxies for A C\n"
-      "Where A = http://page.com/\n"
-      "      B = default subframe process\n"
-      "      C = http://adnetwork.com/",
-      DepictFrameTree(root()));
-
-  // The popup redirects itself to the advertiser's website (ad.com).
-  RenderFrameDeletedObserver deleted_observer(popup_root->current_frame_host());
-  RendererInitiatedNavigateToURL(popup_root, ad_url);
-  deleted_observer.WaitUntilDeleted();
-
-  // This must join its same-site opener, in the default subframe SiteInstance.
-  EXPECT_EQ(
-      " Site A ------------ proxies for B\n"
-      "   +--Site B ------- proxies for A\n"
-      "Where A = http://page.com/\n"
-      "      B = default subframe process",
-      DepictFrameTree(root()));
-  EXPECT_EQ(
-      " Site B\n"
-      "Where B = default subframe process",
-      DepictFrameTree(popup_root));
-}
-
-}  // namespace content
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index 985aac6..8401b7c 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -36,6 +36,7 @@
 #include "services/network/public/cpp/network_switches.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/service_manager/sandbox/features.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/sandbox/switches.h"
 #include "services/service_manager/zygote/common/zygote_buildflags.h"
@@ -61,18 +62,21 @@
  public:
   UtilitySandboxedProcessLauncherDelegate(
       service_manager::SandboxType sandbox_type,
-      const base::EnvironmentMap& env)
+      const base::EnvironmentMap& env,
+      const base::CommandLine& cmd_line)
       :
 #if defined(OS_POSIX)
         env_(env),
 #endif
-        sandbox_type_(sandbox_type) {
+        sandbox_type_(sandbox_type),
+        cmd_line_(cmd_line) {
 #if DCHECK_IS_ON()
     bool supported_sandbox_type =
         sandbox_type_ == service_manager::SANDBOX_TYPE_NO_SANDBOX ||
 #if defined(OS_WIN)
         sandbox_type_ ==
             service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES ||
+        sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING ||
 #endif
         sandbox_type_ == service_manager::SANDBOX_TYPE_UTILITY ||
         sandbox_type_ == service_manager::SANDBOX_TYPE_NETWORK ||
@@ -88,6 +92,20 @@
   ~UtilitySandboxedProcessLauncherDelegate() override {}
 
 #if defined(OS_WIN)
+  bool GetAppContainerId(std::string* appcontainer_id) override {
+    if (sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+        base::FeatureList::IsEnabled(service_manager::features::kXRSandbox)) {
+      *appcontainer_id = base::WideToUTF8(cmd_line_.GetProgram().value());
+      return true;
+    }
+    return false;
+  }
+
+  bool DisableDefaultPolicy() override {
+    return sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+           base::FeatureList::IsEnabled(service_manager::features::kXRSandbox);
+  }
+
   bool ShouldLaunchElevated() override {
     return sandbox_type_ ==
            service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES;
@@ -100,6 +118,32 @@
     if (sandbox_type_ == service_manager::SANDBOX_TYPE_AUDIO)
       return audio::AudioPreSpawnTarget(policy);
 
+    if (sandbox_type_ == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+        base::FeatureList::IsEnabled(service_manager::features::kXRSandbox)) {
+      // There were issues with some mitigations, causing an inability
+      // to load OpenVR and Oculus APIs.
+      // TODO(https://crbug.com/881919): Try to harden the XR Compositor sandbox
+      // to use mitigations and restrict the token.
+      policy->SetProcessMitigations(0);
+      policy->SetDelayedProcessMitigations(0);
+
+      std::string appcontainer_id;
+      if (!GetAppContainerId(&appcontainer_id)) {
+        return false;
+      }
+      sandbox::ResultCode result =
+          service_manager::SandboxWin::AddAppContainerProfileToPolicy(
+              cmd_line_, sandbox_type_, appcontainer_id, policy);
+      if (result != sandbox::SBOX_ALL_OK) {
+        return false;
+      }
+
+      // Unprotected token/job.
+      policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
+                            sandbox::USER_UNPROTECTED);
+      service_manager::SandboxWin::SetJobLevel(
+          cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy);
+    }
     return true;
   }
 #endif  // OS_WIN
@@ -128,6 +172,7 @@
   base::EnvironmentMap env_;
 #endif  // OS_WIN
   service_manager::SandboxType sandbox_type_;
+  base::CommandLine cmd_line_;
 };
 
 UtilityMainThreadFactoryFunction g_utility_main_thread_factory = nullptr;
@@ -332,6 +377,7 @@
       switches::kForceWaveAudio,
       switches::kTrySupportedChannelLayouts,
       switches::kWaveOutBuffers,
+      service_manager::switches::kAddXrAppContainerCaps,
 #endif
     };
     cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
@@ -353,9 +399,10 @@
           *service_identity_, cmd_line.get());
     }
 
-    process_->Launch(std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
-                         sandbox_type_, env_),
-                     std::move(cmd_line), true);
+    std::unique_ptr<UtilitySandboxedProcessLauncherDelegate> delegate =
+        std::make_unique<UtilitySandboxedProcessLauncherDelegate>(
+            sandbox_type_, env_, *cmd_line);
+    process_->Launch(std::move(delegate), std::move(cmd_line), true);
   }
 
   return true;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 5785335b..7f0ae6d2 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -469,8 +469,8 @@
 
     deps += [
       "//third_party/fuchsia-sdk:fdio",
-      "//third_party/fuchsia-sdk:fonts",
-      "//third_party/fuchsia-sdk:scenic",
+      "//third_party/fuchsia-sdk/sdk:fonts",
+      "//third_party/fuchsia-sdk/sdk:scenic",
     ]
   }
 }
diff --git a/content/gpu/gpu_sandbox_hook_linux.cc b/content/gpu/gpu_sandbox_hook_linux.cc
index 306c25d..f154e84b 100644
--- a/content/gpu/gpu_sandbox_hook_linux.cc
+++ b/content/gpu/gpu_sandbox_hook_linux.cc
@@ -77,6 +77,24 @@
 #endif
 }
 
+#if defined(OS_CHROMEOS) && defined(__aarch64__)
+static const char kLibGlesPath[] = "/usr/lib64/libGLESv2.so.2";
+static const char kLibEglPath[] = "/usr/lib64/libEGL.so.1";
+static const char kLibMaliPath[] = "/usr/lib64/libmali.so";
+static const char kLibTegraPath[] = "/usr/lib64/libtegrav4l2.so";
+static const char kLibV4l2Path[] = "/usr/lib64/libv4l2.so";
+static const char kLibV4lEncPluginPath[] =
+    "/usr/lib64/libv4l/plugins/libv4l-encplugin.so";
+#else
+static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
+static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
+static const char kLibMaliPath[] = "/usr/lib/libmali.so";
+static const char kLibTegraPath[] = "/usr/lib/libtegrav4l2.so";
+static const char kLibV4l2Path[] = "/usr/lib/libv4l2.so";
+static const char kLibV4lEncPluginPath[] =
+    "/usr/lib/libv4l/plugins/libv4l-encplugin.so";
+#endif
+
 constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;
 
 void AddV4L2GpuWhitelist(
@@ -152,9 +170,6 @@
   static const char kLdSoCache[] = "/etc/ld.so.cache";
 
   // Files needed by the ARM GPU userspace.
-  static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
-  static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
-
   permissions->push_back(BrokerFilePermission::ReadOnly(kXAuthorityPath));
   permissions->push_back(BrokerFilePermission::ReadOnly(kLdSoCache));
   permissions->push_back(BrokerFilePermission::ReadOnly(kLibGlesPath));
@@ -261,10 +276,10 @@
         break;
     }
   } else {
-    dlopen("/usr/lib/libmali.so", dlopen_flag);
+    dlopen(kLibMaliPath, dlopen_flag);
 
     // Preload the Tegra V4L2 (video decode acceleration) library.
-    dlopen("/usr/lib/libtegrav4l2.so", dlopen_flag);
+    dlopen(kLibTegraPath, dlopen_flag);
   }
 }
 
@@ -295,11 +310,11 @@
 void LoadV4L2Libraries(
     const service_manager::SandboxSeccompBPF::Options& options) {
   if (IsAcceleratedVideoEnabled(options) && UseLibV4L2()) {
-    dlopen("/usr/lib/libv4l2.so", dlopen_flag);
+    dlopen(kLibV4l2Path, dlopen_flag);
 
     if (options.accelerated_video_encode_enabled) {
       // This is a device-specific encoder plugin.
-      dlopen("/usr/lib/libv4l/plugins/libv4l-encplugin.so", dlopen_flag);
+      dlopen(kLibV4lEncPluginPath, dlopen_flag);
     }
   }
 }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 9380603..de9a22f 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -160,13 +160,6 @@
   return false;
 }
 
-bool ContentBrowserClient::
-    ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-        const GURL& url,
-        SiteInstance* parent_site_instance) {
-  return false;
-}
-
 bool ContentBrowserClient::ShouldStayInParentProcessForNTP(
     const GURL& url,
     SiteInstance* parent_site_instance) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 1342f7010..236fbd71 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -375,14 +375,6 @@
                                         bool* is_renderer_initiated,
                                         content::Referrer* referrer) {}
 
-  // Allows the embedder to override top document isolation for specific frames.
-  // |url| is the URL being loaded in the subframe, and |parent_site_instance|
-  // is the SiteInstance of the parent frame. Called only for subframes and only
-  // when top document isolation mode is enabled.
-  virtual bool ShouldFrameShareParentSiteInstanceDespiteTopDocumentIsolation(
-      const GURL& url,
-      SiteInstance* parent_site_instance);
-
   // Temporary hack to determine whether to skip OOPIFs on the new tab page.
   // TODO(creis): Remove when https://crbug.com/566091 is fixed.
   virtual bool ShouldStayInParentProcessForNTP(
diff --git a/content/public/browser/site_instance.h b/content/public/browser/site_instance.h
index 1bb3482..9c9aa4e 100644
--- a/content/public/browser/site_instance.h
+++ b/content/public/browser/site_instance.h
@@ -130,11 +130,6 @@
   // process. This only returns true under the "site per process" process model.
   virtual bool RequiresDedicatedProcess() = 0;
 
-  // Returns true if this SiteInstance is used as the default SiteInstance for
-  // cross-site subframes. This only returns true if "top document isolation" is
-  // used.
-  virtual bool IsDefaultSubframeSiteInstance() const = 0;
-
   // Factory method to create a new SiteInstance.  This will create a new
   // new BrowsingInstance, so it should only be used when creating a new tab
   // from scratch (or similar circumstances).
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc
index ccadc0cf..834a5cc 100644
--- a/content/public/browser/site_isolation_policy.cc
+++ b/content/public/browser/site_isolation_policy.cc
@@ -69,18 +69,6 @@
 }
 
 // static
-bool SiteIsolationPolicy::IsTopDocumentIsolationEnabled() {
-  // --site-per-process trumps --top-document-isolation.
-  if (UseDedicatedProcessesForAllSites())
-    return false;
-
-  // The feature needs to be checked last, because checking the feature
-  // activates the field trial and assigns the client either to a control or an
-  // experiment group - such assignment should be final.
-  return base::FeatureList::IsEnabled(::features::kTopDocumentIsolation);
-}
-
-// static
 bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
   // NOTE: Because it is possible for --isolate-origins to be isolating origins
   // at a finer-than-site granularity, we do not suppress --isolate-origins when
@@ -114,8 +102,7 @@
   // where OOPIF is used such as isolate-extensions, but should be good for
   // feature testing purpose. Eventually, we will remove this check and use pdf
   // compositor service by default for printing.
-  return AreIsolatedOriginsEnabled() || IsTopDocumentIsolationEnabled() ||
-         UseDedicatedProcessesForAllSites();
+  return AreIsolatedOriginsEnabled() || UseDedicatedProcessesForAllSites();
 }
 
 // static
diff --git a/content/public/browser/site_isolation_policy.h b/content/public/browser/site_isolation_policy.h
index 4a0ca068..e3348681 100644
--- a/content/public/browser/site_isolation_policy.h
+++ b/content/public/browser/site_isolation_policy.h
@@ -38,10 +38,6 @@
   static void PopulateURLLoaderFactoryParamsPtrForCORB(
       network::mojom::URLLoaderFactoryParams* params);
 
-  // Returns true if third-party subframes of a page should be kept in a
-  // different process from the main frame.
-  static bool IsTopDocumentIsolationEnabled();
-
   // Returns true if isolated origins feature is enabled.
   static bool AreIsolatedOriginsEnabled();
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 30805f74..0dff056 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -426,12 +426,6 @@
 const base::Feature kTimerThrottlingForHiddenFrames{
     "TimerThrottlingForHiddenFrames", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Groups all out-of-process iframes to a different process from the process of
-// the top document. This is a performance isolation mode.  Launch bug:
-// https://crbug.com/595987.
-const base::Feature kTopDocumentIsolation{"top-document-isolation",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables async touchpad pinch zoom events. We check the ACK of the first
 // synthetic wheel event in a pinch sequence, then send the rest of the
 // synthetic wheel events of the pinch sequence as non-blocking if the first
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 62cc4c3..00fd287 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 kSignedHTTPExchangeOriginTrial;
 CONTENT_EXPORT extern const base::Feature kSpareRendererForSitePerProcess;
 CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
-CONTENT_EXPORT extern const base::Feature kTopDocumentIsolation;
 CONTENT_EXPORT extern const base::Feature kTouchpadAsyncPinchEvents;
 CONTENT_EXPORT extern const base::Feature kTouchpadOverscrollHistoryNavigation;
 CONTENT_EXPORT extern const base::Feature kUserActivationV2;
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc
index d2b6ef2..8d5a6ab 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -829,6 +829,7 @@
       compositor_->GetCurrentFrameWithoutUpdatingStatistics();
 
   media::Context3D context_3d;
+  gpu::ContextSupport* context_support = nullptr;
   if (frame && frame->HasTextures()) {
     auto* provider =
         RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
@@ -836,11 +837,11 @@
     if (!provider)
       return;
     context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
-    DCHECK(context_3d.gl);
+    context_support = provider->ContextSupport();
   }
   const gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height);
   video_renderer_.Paint(frame, canvas, dest_rect, flags, video_rotation_,
-                        context_3d);
+                        context_3d, context_support);
 }
 
 bool WebMediaPlayerMS::DidGetOpaqueResponseFromServiceWorker() const {
@@ -1016,8 +1017,8 @@
   DCHECK(context_3d.gl);
 
   return video_renderer_.CopyVideoFrameTexturesToGLTexture(
-      context_3d, gl, video_frame.get(), target, texture, internal_format,
-      format, type, level, premultiply_alpha, flip_y);
+      context_3d, provider->ContextSupport(), gl, video_frame.get(), target,
+      texture, internal_format, format, type, level, premultiply_alpha, flip_y);
 }
 
 bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture(
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
index c53c0be2..92b6b60 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -68,7 +68,8 @@
     DCHECK(provider->ContextGL());
     video_renderer->Copy(
         frame.get(), &paint_canvas,
-        media::Context3D(provider->ContextGL(), provider->GrContext()));
+        media::Context3D(provider->ContextGL(), provider->GrContext()),
+        provider->ContextSupport());
 
     SkPixmap pixmap;
     const bool result = bitmap.peekPixels(&pixmap);
diff --git a/content/renderer/media_recorder/video_track_recorder.cc b/content/renderer/media_recorder/video_track_recorder.cc
index c7fb3465..ef28d3170 100644
--- a/content/renderer/media_recorder/video_track_recorder.cc
+++ b/content/renderer/media_recorder/video_track_recorder.cc
@@ -313,7 +313,8 @@
     DCHECK(context_provider->ContextGL());
     video_renderer_->Copy(video_frame.get(), canvas_.get(),
                           media::Context3D(context_provider->ContextGL(),
-                                           context_provider->GrContext()));
+                                           context_provider->GrContext()),
+                          context_provider->ContextSupport());
 
     SkPixmap pixmap;
     if (!bitmap_.peekPixels(&pixmap)) {
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 6cde87d0..5babe8a6 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -3103,7 +3103,7 @@
   SkCanvas* canvas = image_data->GetCanvas();
   // Note: Do not SkBitmap::copyTo the canvas bitmap directly because it will
   // ignore the allocated pixels in shared memory and re-allocate a new buffer.
-  canvas->writePixels(image_skia_rep.sk_bitmap(), 0, 0);
+  canvas->writePixels(image_skia_rep.GetBitmap(), 0, 0);
 
   return image_data->GetReference();
 }
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 18f48701..fe508c3 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -973,7 +973,8 @@
 
 void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse(
     int fetch_event_id,
-    base::TimeTicks event_dispatch_time) {
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
   TRACE_EVENT_WITH_FLOW0(
       "ServiceWorker",
       "ServiceWorkerContextClient::RespondToFetchEventWithNoResponse",
@@ -984,14 +985,20 @@
   const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
       context_->fetch_response_callbacks[fetch_event_id];
   DCHECK(response_callback.is_bound());
-  response_callback->OnFallback(event_dispatch_time);
+
+  auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
+  timing->dispatch_event_time = event_dispatch_time;
+  timing->respond_with_settled_time = respond_with_settled_time;
+
+  response_callback->OnFallback(std::move(timing));
   context_->fetch_response_callbacks.erase(fetch_event_id);
 }
 
 void ServiceWorkerContextClient::RespondToFetchEvent(
     int fetch_event_id,
     const blink::WebServiceWorkerResponse& web_response,
-    base::TimeTicks event_dispatch_time) {
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
   TRACE_EVENT_WITH_FLOW0(
       "ServiceWorker", "ServiceWorkerContextClient::RespondToFetchEvent",
       TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
@@ -1003,7 +1010,11 @@
   const blink::mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback =
       context_->fetch_response_callbacks[fetch_event_id];
 
-  response_callback->OnResponse(std::move(response), event_dispatch_time);
+  auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
+  timing->dispatch_event_time = event_dispatch_time;
+  timing->respond_with_settled_time = respond_with_settled_time;
+
+  response_callback->OnResponse(std::move(response), std::move(timing));
   context_->fetch_response_callbacks.erase(fetch_event_id);
 }
 
@@ -1011,7 +1022,8 @@
     int fetch_event_id,
     const blink::WebServiceWorkerResponse& web_response,
     blink::WebServiceWorkerStreamHandle* web_body_as_stream,
-    base::TimeTicks event_dispatch_time) {
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
   TRACE_EVENT_WITH_FLOW0(
       "ServiceWorker",
       "ServiceWorkerContextClient::RespondToFetchEventWithResponseStream",
@@ -1033,8 +1045,12 @@
   web_body_as_stream->SetListener(
       std::make_unique<StreamHandleListener>(std::move(callback_ptr)));
 
+  auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
+  timing->dispatch_event_time = event_dispatch_time;
+  timing->respond_with_settled_time = respond_with_settled_time;
+
   response_callback->OnResponseStream(
-      std::move(response), std::move(body_as_stream), event_dispatch_time);
+      std::move(response), std::move(body_as_stream), std::move(timing));
   context_->fetch_response_callbacks.erase(fetch_event_id);
 }
 
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 41b3295..5955295 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -161,15 +161,18 @@
                              base::TimeTicks event_dispatch_time) override;
   void RespondToFetchEventWithNoResponse(
       int fetch_event_id,
-      base::TimeTicks event_dispatch_time) override;
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time) override;
   void RespondToFetchEvent(int fetch_event_id,
                            const blink::WebServiceWorkerResponse& response,
-                           base::TimeTicks event_dispatch_time) override;
+                           base::TimeTicks event_dispatch_time,
+                           base::TimeTicks respond_with_settled_time) override;
   void RespondToFetchEventWithResponseStream(
       int fetch_event_id,
       const blink::WebServiceWorkerResponse& response,
       blink::WebServiceWorkerStreamHandle* web_body_as_stream,
-      base::TimeTicks event_dispatch_time) override;
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time) override;
   void DidHandleFetchEvent(int fetch_event_id,
                            blink::mojom::ServiceWorkerEventStatus status,
                            base::TimeTicks event_dispatch_time) override;
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index d3346e3..44cf532 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -348,7 +348,7 @@
 
 void ServiceWorkerSubresourceLoader::OnResponse(
     blink::mojom::FetchAPIResponsePtr response,
-    base::TimeTicks dispatch_event_time) {
+    blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
   TRACE_EVENT_WITH_FLOW0("ServiceWorker",
                          "ServiceWorkerSubresourceLoader::OnResponse", this,
                          TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
@@ -359,7 +359,7 @@
 void ServiceWorkerSubresourceLoader::OnResponseStream(
     blink::mojom::FetchAPIResponsePtr response,
     blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
-    base::TimeTicks dispatch_event_time) {
+    blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
   TRACE_EVENT_WITH_FLOW0(
       "ServiceWorker", "ServiceWorkerSubresourceLoader::OnResponseStream", this,
       TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
@@ -368,7 +368,7 @@
 }
 
 void ServiceWorkerSubresourceLoader::OnFallback(
-    base::TimeTicks dispatch_event_time) {
+    blink::mojom::ServiceWorkerFetchEventTimingPtr timing) {
   SettleFetchEventDispatch(blink::ServiceWorkerStatusCode::kOk);
   // When the request mode is CORS or CORS-with-forced-preflight and the origin
   // of the request URL is different from the security origin of the document,
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h
index 9fd2067..28359d5 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -75,13 +75,15 @@
       base::Optional<blink::ServiceWorkerStatusCode> status);
 
   // blink::mojom::ServiceWorkerFetchResponseCallback overrides:
-  void OnResponse(blink::mojom::FetchAPIResponsePtr response,
-                  base::TimeTicks dispatch_event_time) override;
+  void OnResponse(
+      blink::mojom::FetchAPIResponsePtr response,
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override;
   void OnResponseStream(
       blink::mojom::FetchAPIResponsePtr response,
       blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
-      base::TimeTicks dispatch_event_time) override;
-  void OnFallback(base::TimeTicks dispatch_event_time) override;
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override;
+  void OnFallback(
+      blink::mojom::ServiceWorkerFetchEventTimingPtr timing) override;
 
   void StartResponse(blink::mojom::FetchAPIResponsePtr response,
                      blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream);
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index 492edc2..46abdd0 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -233,8 +233,9 @@
 
     switch (response_mode_) {
       case ResponseMode::kDefault:
-        response_callback->OnResponse(OkResponse(nullptr /* blob_body */),
-                                      base::TimeTicks::Now());
+        response_callback->OnResponse(
+            OkResponse(nullptr /* blob_body */),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED,
             base::TimeTicks());
@@ -244,28 +245,32 @@
                                 base::TimeTicks());
         break;
       case ResponseMode::kStream:
-        response_callback->OnResponseStream(OkResponse(nullptr /* blob_body */),
-                                            std::move(stream_handle_),
-                                            base::TimeTicks::Now());
+        response_callback->OnResponseStream(
+            OkResponse(nullptr /* blob_body */), std::move(stream_handle_),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED,
             base::TimeTicks());
         break;
       case ResponseMode::kBlob:
-        response_callback->OnResponse(OkResponse(std::move(blob_body_)),
-                                      base::TimeTicks::Now());
+        response_callback->OnResponse(
+            OkResponse(std::move(blob_body_)),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED,
             base::TimeTicks());
         break;
       case ResponseMode::kFallbackResponse:
-        response_callback->OnFallback(base::TimeTicks::Now());
+        response_callback->OnFallback(
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED,
             base::TimeTicks::Now());
         break;
       case ResponseMode::kErrorResponse:
-        response_callback->OnResponse(ErrorResponse(), base::TimeTicks::Now());
+        response_callback->OnResponse(
+            ErrorResponse(),
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::REJECTED,
             base::TimeTicks::Now());
@@ -273,7 +278,7 @@
       case ResponseMode::kRedirectResponse: {
         response_callback->OnResponse(
             RedirectResponse(redirect_location_header_),
-            base::TimeTicks::Now());
+            blink::mojom::ServiceWorkerFetchEventTiming::New());
         std::move(callback).Run(
             blink::mojom::ServiceWorkerEventStatus::COMPLETED,
             base::TimeTicks());
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 87fc4b1..361c05c 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -343,7 +343,7 @@
       "//components/crash/content/app:test_support",
       "//components/crash/content/browser",
     ]
-    deps += [ "//third_party/fuchsia-sdk:policy" ]
+    deps += [ "//third_party/fuchsia-sdk/sdk:policy" ]
   }
 
   # Annoyingly, this target and layouttest_support have circular includes.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 2e6242e..b480865 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -861,7 +861,6 @@
     "../browser/site_per_process_mac_browsertest.mm",
     "../browser/snapshot_browsertest.cc",
     "../browser/storage_partition_impl_browsertest.cc",
-    "../browser/top_document_isolation_browsertest.cc",
     "../browser/tracing/background_tracing_manager_browsertest.cc",
     "../browser/tracing/memory_instrumentation_browsertest.cc",
     "../browser/tracing/memory_tracing_browsertest.cc",
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
index 9179a0bc..41d0c24 100644
--- a/content/test/content_browser_test_utils_internal.cc
+++ b/content/test/content_browser_test_utils_internal.cc
@@ -235,8 +235,6 @@
     SiteInstanceImpl* site_instance =
         static_cast<SiteInstanceImpl*>(legend_entry.second);
     std::string description = site_instance->GetSiteURL().spec();
-    if (site_instance->IsDefaultSubframeSiteInstance())
-      description = "default subframe process";
     base::StringAppendF(&result, "\n%s%s = %s", prefix,
                         legend_entry.first.c_str(), description.c_str());
     // Highlight some exceptionable conditions.
diff --git a/content/test/gpu/gpu_tests/power_measurement_integration_test.py b/content/test/gpu/gpu_tests/power_measurement_integration_test.py
index bc4b64e..64452ff8 100644
--- a/content/test/gpu/gpu_tests/power_measurement_integration_test.py
+++ b/content/test/gpu/gpu_tests/power_measurement_integration_test.py
@@ -6,6 +6,21 @@
 to be installed on the machine before this script works. The software can be
 downloaded from:
   https://software.intel.com/en-us/articles/intel-power-gadget-20
+
+To run this test on a target machine without Chromium workspace checked out:
+1) inside Chromium workspace, run
+   python tools/mb/mb.py zip out/Release
+       telemetry_gpu_integration_test_scripts_only out/myfilename.zip
+   This zip doesn't include a chrome executable. The intent is to run with
+   one of the stable/beta/canary/dev channels installed on the target machine.
+2) copy the zip file to the target machine, unzip
+3) python content/test/gpu/run_gpu_integration_test.py power --browser=canary
+   (plus options listed through --help)
+
+This script is tested and works fine with the following video sites:
+  * https://www.youtube.com
+  * https://www.vimeo.com
+  * https://www.pond5.com
 """
 
 from gpu_tests import gpu_integration_test
@@ -32,14 +47,16 @@
     return rt;
   }
 
+  // Return true if video has started playing.
   function setupVideoElement() {
     var video = locateElement("video");
     if (video) {
-      video.volume = 0;
+      video.muted = true;
       video.loop = true;
       video.autoplay = true;
-      video.play();
+      return video.currentTime > 0;
     }
+    return false;
   }
 
   function isVideoPlaying() {
@@ -52,17 +69,30 @@
     return false;
   }
 
-  function locateButton(url) {
-    var lower_url = url.toLowerCase();
-    var button_class = '';
-    if (lower_url.indexOf('youtube') != -1)
-      button_class = 'ytp-fullscreen-button';
-    if (button_class == '')
-      return null;
-    var buttons = document.getElementsByClassName(button_class);
-    if (buttons.length == 0)
-      return null;
-    return buttons[0];
+  function locateButton(texts) {
+    var buttons = document.getElementsByTagName("button");
+    for (var ii = 0; ii < buttons.length; ++ii) {
+      var label = buttons[ii].textContent.toLowerCase();
+      for (var jj = 0; jj < texts.length; ++jj) {
+        if (label.indexOf(texts[jj]) != -1) {
+          return buttons[ii];
+        }
+      }
+      label = buttons[ii].getAttribute("title") ||
+              buttons[ii].getAttribute("data-tooltip-content");
+      if (label) {
+        label = label.toLowerCase();
+        for (var jj = 0; jj < texts.length; ++jj) {
+          if (label.indexOf(texts[jj]) != -1)
+            return buttons[ii];
+        }
+      }
+    }
+    return null;
+  }
+
+  function locateFullscreenButton() {
+    return locateButton(["full screen", "fullscreen"]);
   }
 """
 
@@ -150,15 +180,20 @@
       if test_path:
         self.tab.action_runner.Navigate(test_path, fullscreen_script)
         self.tab.WaitForDocumentReadyStateToBeComplete()
-        self.tab.action_runner.ExecuteJavaScript('setupVideoElement()')
+        if not self.tab.action_runner.EvaluateJavaScript('setupVideoElement()'):
+          # autoplay doesn't work for vimeo.
+          # action_runner.PlayMedia doesn't work for vimeo.
+          self.tab.action_runner.TapElement(element_function=(
+              'locateElement("video")'))
         self.tab.action_runner.WaitForJavaScriptCondition(
             'isVideoPlaying()', timeout=10)
 
       if fullscreen:
-        # TODO(zmo): Switch to use click instead of tap once Telemetry's click
-        # is implemented through DevTools.
+        if self.tab.action_runner.EvaluateJavaScript(
+               'locateFullscreenButton() == null'):
+          self.fail("Fullscreen button not located, --fullscreen won't work")
         self.tab.action_runner.TapElement(element_function=(
-            'locateButton("%s")' % test_path))
+            'locateFullscreenButton()'))
 
       logfile = None
       if ipg_logdir:
diff --git a/device/fido/ble/fido_ble_device.cc b/device/fido/ble/fido_ble_device.cc
index 89b7a173..5ea6e1e6 100644
--- a/device/fido/ble/fido_ble_device.cc
+++ b/device/fido/ble/fido_ble_device.cc
@@ -67,6 +67,14 @@
   return GetId(connection_->address());
 }
 
+base::string16 FidoBleDevice::GetDisplayName() const {
+  auto* device = connection_->GetBleDevice();
+  if (!device)
+    return base::string16();
+
+  return device->GetNameForDisplay();
+}
+
 FidoTransportProtocol FidoBleDevice::DeviceTransport() const {
   return FidoTransportProtocol::kBluetoothLowEnergy;
 }
diff --git a/device/fido/ble/fido_ble_device.h b/device/fido/ble/fido_ble_device.h
index 1c62bf4..edc453c 100644
--- a/device/fido/ble/fido_ble_device.h
+++ b/device/fido/ble/fido_ble_device.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 #include "base/timer/timer.h"
 #include "device/fido/ble/fido_ble_connection.h"
@@ -42,6 +43,7 @@
   void TryWink(WinkCallback callback) override;
   void Cancel() override;
   std::string GetId() const override;
+  base::string16 GetDisplayName() const override;
   FidoTransportProtocol DeviceTransport() const override;
 
   // Returns whether or not the underlying BLE device is currently in pairing
diff --git a/device/fido/fido_authenticator.h b/device/fido/fido_authenticator.h
index b2a254d..3d30e83 100644
--- a/device/fido/fido_authenticator.h
+++ b/device/fido/fido_authenticator.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/fido_transport_protocol.h"
@@ -48,6 +49,7 @@
                             GetAssertionCallback callback) = 0;
   virtual void Cancel() = 0;
   virtual std::string GetId() const = 0;
+  virtual base::string16 GetDisplayName() const = 0;
   virtual const AuthenticatorSupportedOptions& Options() const = 0;
   virtual FidoTransportProtocol AuthenticatorTransport() const = 0;
   virtual base::WeakPtr<FidoAuthenticator> GetWeakPtr() = 0;
diff --git a/device/fido/fido_device.cc b/device/fido/fido_device.cc
index b9b3001..b41fa9a 100644
--- a/device/fido/fido_device.cc
+++ b/device/fido/fido_device.cc
@@ -18,6 +18,11 @@
 FidoDevice::FidoDevice() = default;
 FidoDevice::~FidoDevice() = default;
 
+base::string16 FidoDevice::GetDisplayName() const {
+  const auto id = GetId();
+  return base::string16(id.begin(), id.end());
+}
+
 void FidoDevice::DiscoverSupportedProtocolAndDeviceInfo(
     base::OnceClosure done) {
   if (base::FeatureList::IsEnabled(kNewCtap2Device)) {
diff --git a/device/fido/fido_device.h b/device/fido/fido_device.h
index ec5a773..747734b2 100644
--- a/device/fido/fido_device.h
+++ b/device/fido/fido_device.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
 #include "device/fido/authenticator_get_info_response.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_transport_protocol.h"
@@ -59,6 +60,7 @@
   virtual void TryWink(WinkCallback callback) = 0;
   virtual void Cancel() = 0;
   virtual std::string GetId() const = 0;
+  virtual base::string16 GetDisplayName() const;
   virtual FidoTransportProtocol DeviceTransport() const = 0;
   virtual base::WeakPtr<FidoDevice> GetWeakPtr() = 0;
 
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc
index afb1d8a..eeb17f1f 100644
--- a/device/fido/fido_device_authenticator.cc
+++ b/device/fido/fido_device_authenticator.cc
@@ -60,6 +60,10 @@
   return device_->GetId();
 }
 
+base::string16 FidoDeviceAuthenticator::GetDisplayName() const {
+  return device_->GetDisplayName();
+}
+
 const AuthenticatorSupportedOptions& FidoDeviceAuthenticator::Options() const {
   static const AuthenticatorSupportedOptions default_options;
   switch (device_->supported_protocol()) {
diff --git a/device/fido/fido_device_authenticator.h b/device/fido/fido_device_authenticator.h
index e755f1f..606e5b99 100644
--- a/device/fido/fido_device_authenticator.h
+++ b/device/fido/fido_device_authenticator.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
 #include "device/fido/fido_authenticator.h"
 
 namespace device {
@@ -40,6 +41,7 @@
                     GetAssertionCallback callback) override;
   void Cancel() override;
   std::string GetId() const override;
+  base::string16 GetDisplayName() const override;
   const AuthenticatorSupportedOptions& Options() const override;
   FidoTransportProtocol AuthenticatorTransport() const override;
   base::WeakPtr<FidoAuthenticator> GetWeakPtr() override;
diff --git a/device/fido/mac/authenticator.h b/device/fido/mac/authenticator.h
index 090e643..8e9741a162 100644
--- a/device/fido/mac/authenticator.h
+++ b/device/fido/mac/authenticator.h
@@ -12,6 +12,7 @@
 #include "base/mac/availability.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
 #include "base/strings/string_piece_forward.h"
 #include "device/fido/fido_authenticator.h"
 #include "device/fido/fido_transport_protocol.h"
@@ -56,6 +57,7 @@
                     GetAssertionCallback callback) override;
   void Cancel() override;
   std::string GetId() const override;
+  base::string16 GetDisplayName() const override;
   const AuthenticatorSupportedOptions& Options() const override;
   FidoTransportProtocol AuthenticatorTransport() const override;
   base::WeakPtr<FidoAuthenticator> GetWeakPtr() override;
diff --git a/device/fido/mac/authenticator.mm b/device/fido/mac/authenticator.mm
index b5e03ce..43d4728 100644
--- a/device/fido/mac/authenticator.mm
+++ b/device/fido/mac/authenticator.mm
@@ -132,6 +132,10 @@
   return "TouchIdAuthenticator";
 }
 
+base::string16 TouchIdAuthenticator::GetDisplayName() const {
+  return base::string16();
+}
+
 FidoTransportProtocol TouchIdAuthenticator::AuthenticatorTransport() const {
   return FidoTransportProtocol::kInternal;
 }
diff --git a/docs/fuchsia_gardening.md b/docs/fuchsia_gardening.md
new file mode 100644
index 0000000..d248c9f
--- /dev/null
+++ b/docs/fuchsia_gardening.md
@@ -0,0 +1,38 @@
+# Cr-Fuchsia Gardening
+
+## Gardener Responsibilities
+
+In priority order, the responsibilities of the Fuchsia Gardener are as follows (though see notes below!):
+
+1.  **Chromium waterfall:** Keep [the Fuchsia bots on the Chromium waterfall](https://ci.chromium.org/p/chromium/g/chromium.linux/console) green.
+    1.  Join the #chromium IRC channel on Freenode.
+    1.  Not all waterfall bots have a corresponding try-bot configuration.
+    1.  E.g. the Cast Fuchsia bots are not run on the CQ by default.
+    1.  E.g. the CQ builds have DCHECKs enabled, whereas our Cast waterfall bots don't.
+1.  **Chromium try-bots:** Ensure that Fuchsia bots are not causing CQ flake.
+    1.  Join the #chromium IRC channel on Freenode.
+    1.  Watch for try-flakes emails & investigate any tests/suites reported flakey.
+    1.  Watch for IRC mentions of flakiness on the Fuchsia bots.
+1.  **Fuchsia SDK rolls:** Keep [the Fuchsia SDK auto-roller](https://autoroll.skia.org/r/fuchsia-sdk-chromium-autoroll) working.
+    1.  Watch for emailed status updates from auto-roller CLs.
+    1.  If a roll CL fails, check the failed bot to confirm SDK-related fail vs other flake.
+    1.  If it was an actual SDK-related failure, note the latest auto-roller patch-Id, and stop the auto-roller.
+    1.  Create a local branch e.g. with "`git checkout -b sdkRoll origin`".
+    1.  Pull-down the auto-roll CL with "`git cl patch <patch-Id> && gclient sync`".
+    1.  Clear the CL metadata with "`git cl issue 0`".
+    1.  Make any necessary modifications for compatibility with the new SDK.
+    1.  Commit the changes and run "`git cl upload`" to upload a new CL.
+    1.  Edit the CL description, which will include the git commit description from the auto-roller CL, making it easy to provide a consistent description.
+    1.  Note that if the auto-roller is blocked for a long time then it may be easier to fix the most-recent failed roll, and roll from there, to avoid having to deal with several different causes of breakage in a single roll!
+1.  **FYI waterfall:** Keep our bots on the [FYI waterfall](https://ci.chromium.org/p/chromium/g/chromium.fyi/console) green.
+    1.  FYI bots don't block the CQ, but still provide early-warning of regressions.
+    1.  They're also our staging-ground for bringing complex test suites to the CQ/waterfall.
+
+While the Gardener takes primary responsibility for each of these areas during their rotation, that does not mean that they must do all the work - if another teammate happens to have started fixing the SDK roll, un-breaking the bots, or sending you CLs to fix our Debug builder (look, ma! No try-bot!), then lucky you, your Gardening job is done. :)
+
+## Optional Gardener Tasks
+
+The waterfall is green, the try-bots reliable, SDK is rolling and pigs soar majestically in the sky. Fear not, gentle Gardener, you still have a valuable role to play!
+
+*   Look for tests that have been filtered under Fuchsia, and diagnose them.
+    *   File a new bug, or upate the filter to refer to existing bugs, as appropriate.
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index 9461bf64..2c159f6 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -513,13 +513,37 @@
 void EventRouter::DispatchEventWithLazyListener(const std::string& extension_id,
                                                 std::unique_ptr<Event> event) {
   DCHECK(!extension_id.empty());
+  const Extension* extension = ExtensionRegistry::Get(browser_context_)
+                                   ->enabled_extensions()
+                                   .GetByID(extension_id);
+  if (!extension)
+    return;
+  const bool is_service_worker_based_background =
+      BackgroundInfo::IsServiceWorkerBased(extension);
+
   std::string event_name = event->event_name;
-  bool has_listener = ExtensionHasEventListener(extension_id, event_name);
-  if (!has_listener)
-    AddLazyEventListener(event_name, extension_id);
+  const bool has_listener = ExtensionHasEventListener(extension_id, event_name);
+  if (!has_listener) {
+    if (is_service_worker_based_background) {
+      AddLazyServiceWorkerEventListener(
+          event_name, extension_id,
+          Extension::GetBaseURLFromExtensionId(extension_id));
+    } else {
+      AddLazyEventListener(event_name, extension_id);
+    }
+  }
+
   DispatchEventToExtension(extension_id, std::move(event));
-  if (!has_listener)
-    RemoveLazyEventListener(event_name, extension_id);
+
+  if (!has_listener) {
+    if (is_service_worker_based_background) {
+      RemoveLazyServiceWorkerEventListener(
+          event_name, extension_id,
+          Extension::GetBaseURLFromExtensionId(extension_id));
+    } else {
+      RemoveLazyEventListener(event_name, extension_id);
+    }
+  }
 }
 
 void EventRouter::DispatchEventImpl(const std::string& restrict_to_extension_id,
diff --git a/extensions/browser/extension_icon_image_unittest.cc b/extensions/browser/extension_icon_image_unittest.cc
index 9ef5962..f5ce427 100644
--- a/extensions/browser/extension_icon_image_unittest.cc
+++ b/extensions/browser/extension_icon_image_unittest.cc
@@ -171,7 +171,7 @@
   // Before the image representation is loaded, image should contain blank
   // image representation.
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
+      representation.GetBitmap(),
       CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P)));
 
   WaitForImageLoad();
@@ -181,14 +181,14 @@
   representation = image.image_skia().GetRepresentation(1.0f);
 
   // We should get the right representation now.
-  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
+  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(), bitmap_16));
   EXPECT_EQ(16, representation.pixel_width());
 
   // Gets representation for an additional scale factor.
   representation = image.image_skia().GetRepresentation(2.0f);
 
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
+      representation.GetBitmap(),
       CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
 
   WaitForImageLoad();
@@ -199,7 +199,7 @@
 
   // Image should have been resized.
   EXPECT_EQ(32, representation.pixel_width());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
+  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                    bitmap_48_resized_to_32));
 }
 
@@ -241,7 +241,7 @@
   // size.
   EXPECT_EQ(2.0f, representation.scale());
   EXPECT_EQ(64, representation.pixel_width());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
+  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                    EnsureBitmapSize(bitmap_48, 64)));
 }
 
@@ -278,7 +278,7 @@
   // We should have loaded the smallest bigger (resized) resource.
   EXPECT_EQ(1.0f, representation.scale());
   EXPECT_EQ(17, representation.pixel_width());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
+  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                    EnsureBitmapSize(bitmap_24, 17)));
 }
 
@@ -306,10 +306,9 @@
   gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
 
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
-      EnsureBitmapSize(
-          default_icon.GetRepresentation(1.0f).sk_bitmap(),
-          kRequestedSize)));
+      representation.GetBitmap(),
+      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
+                       kRequestedSize)));
 
   EXPECT_EQ(1, ImageLoadedCount());
   // We should have a default icon representation.
@@ -317,10 +316,9 @@
 
   representation = image.image_skia().GetRepresentation(1.0f);
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
-      EnsureBitmapSize(
-          default_icon.GetRepresentation(1.0f).sk_bitmap(),
-          kRequestedSize)));
+      representation.GetBitmap(),
+      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
+                       kRequestedSize)));
 }
 
 // If resource set is invalid, image load should be done asynchronously and
@@ -346,7 +344,7 @@
 
   gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
+      representation.GetBitmap(),
       CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));
 
   WaitForImageLoad();
@@ -356,10 +354,9 @@
 
   representation = image.image_skia().GetRepresentation(1.0f);
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
-      EnsureBitmapSize(
-          default_icon.GetRepresentation(1.0f).sk_bitmap(),
-          kInvalidIconSize)));
+      representation.GetBitmap(),
+      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
+                       kInvalidIconSize)));
 }
 
 // Test that IconImage works with lazily (but synchronously) created default
@@ -393,10 +390,9 @@
   // The resouce set is empty, so we should get the result right away.
   EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
-      EnsureBitmapSize(
-          default_icon.GetRepresentation(1.0f).sk_bitmap(),
-          kRequestedSize)));
+      representation.GetBitmap(),
+      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
+                       kRequestedSize)));
 
   // We should have a default icon representation.
   ASSERT_EQ(1u, image.image_skia().image_reps().size());
@@ -437,10 +433,9 @@
 
   representation = image.image_skia().GetRepresentation(1.0f);
   EXPECT_TRUE(gfx::BitmapsAreEqual(
-      representation.sk_bitmap(),
-      EnsureBitmapSize(
-          default_icon.GetRepresentation(1.0f).sk_bitmap(),
-          kInvalidIconSize)));
+      representation.GetBitmap(),
+      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
+                       kInvalidIconSize)));
 }
 
 // Tests behavior of image created by IconImage after IconImage host goes
@@ -482,7 +477,7 @@
 
   EXPECT_EQ(1.0f, representation.scale());
   EXPECT_EQ(16, representation.pixel_width());
-  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
+  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(), bitmap_16));
 
   // When requesting another representation, we should not crash and return some
   // image of the size. It could be blank or a rescale from the existing 1.0f
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index efc7b7ce..61a27d9 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -373,7 +373,7 @@
   "runtime": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
-    "contexts": ["blessed_extension", "lock_screen_extension"]
+    "contexts": ["blessed_extension", "lock_screen_extension", "extension_service_worker"]
   },
   "runtime.getManifest": {
     "contexts": [
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json
index c38b30ba..55c1c8ad 100644
--- a/extensions/common/api/_manifest_features.json
+++ b/extensions/common/api/_manifest_features.json
@@ -111,7 +111,7 @@
     "extension_types": "all"
   },
   "declarative_net_request": {
-    "channel": "trunk",
+    "channel": "dev",
     "extension_types": ["extension"],
     "min_manifest_version": 2
   },
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
index 923f679a..5a92d096 100644
--- a/extensions/common/api/_permission_features.json
+++ b/extensions/common/api/_permission_features.json
@@ -190,7 +190,7 @@
     "platforms": ["chromeos"]
   },
   "declarativeNetRequest": {
-    "channel": "trunk",
+    "channel": "dev",
     "extension_types": ["extension"],
     "min_manifest_version": 2
   },
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 670947f..dc6d4606 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -161,12 +161,6 @@
          security_state::features::kMarkHttpAsFeature,
          kMarkHttpAsFeatureVariations,
          "MarkHttpAs")},
-    {"web-payments", flag_descriptions::kWebPaymentsName,
-     flag_descriptions::kWebPaymentsDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(payments::features::kWebPayments)},
-    {"web-payments-native-apps", flag_descriptions::kWebPaymentsNativeAppsName,
-     flag_descriptions::kWebPaymentsNativeAppsDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(payments::features::kWebPaymentsNativeApps)},
     {"ios-captive-portal-metrics", flag_descriptions::kCaptivePortalMetricsName,
      flag_descriptions::kCaptivePortalMetricsDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kCaptivePortalMetrics)},
diff --git a/ios/chrome/browser/autofill/BUILD.gn b/ios/chrome/browser/autofill/BUILD.gn
index 4be47bd5..39d7a9d 100644
--- a/ios/chrome/browser/autofill/BUILD.gn
+++ b/ios/chrome/browser/autofill/BUILD.gn
@@ -7,6 +7,8 @@
   sources = [
     "address_normalizer_factory.cc",
     "address_normalizer_factory.h",
+    "autofill_profile_validator_factory.cc",
+    "autofill_profile_validator_factory.h",
     "form_input_accessory_consumer.h",
     "form_input_accessory_view.h",
     "form_input_accessory_view.mm",
diff --git a/ios/chrome/browser/autofill/autofill_profile_validator_factory.cc b/ios/chrome/browser/autofill/autofill_profile_validator_factory.cc
new file mode 100644
index 0000000..7759583
--- /dev/null
+++ b/ios/chrome/browser/autofill/autofill_profile_validator_factory.cc
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/autofill/autofill_profile_validator_factory.h"
+
+#include <memory>
+
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/autofill/validation_rules_storage_factory.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
+#include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
+
+namespace autofill {
+
+AutofillProfileValidator* AutofillProfileValidatorFactory::GetInstance() {
+  static base::LazyInstance<AutofillProfileValidatorFactory>::DestructorAtExit
+      instance = LAZY_INSTANCE_INITIALIZER;
+  return &(instance.Get().autofill_profile_validator_);
+}
+
+AutofillProfileValidatorFactory::AutofillProfileValidatorFactory()
+    : autofill_profile_validator_(
+          std::make_unique<autofill::ChromeMetadataSource>(
+              I18N_ADDRESS_VALIDATION_DATA_URL,
+              GetApplicationContext()->GetSharedURLLoaderFactory()),
+          ValidationRulesStorageFactory::CreateStorage()) {}
+
+AutofillProfileValidatorFactory::~AutofillProfileValidatorFactory() {}
+
+}  // namespace autofill
diff --git a/ios/chrome/browser/autofill/autofill_profile_validator_factory.h b/ios/chrome/browser/autofill/autofill_profile_validator_factory.h
new file mode 100644
index 0000000..8d6ae4fc
--- /dev/null
+++ b/ios/chrome/browser/autofill/autofill_profile_validator_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
+#define IOS_CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "components/autofill/core/browser/autofill_profile_validator.h"
+
+namespace autofill {
+
+// Singleton that owns a single AutofillProfileValidator instance.
+class AutofillProfileValidatorFactory {
+ public:
+  static AutofillProfileValidator* GetInstance();
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<AutofillProfileValidatorFactory>;
+
+  AutofillProfileValidatorFactory();
+  ~AutofillProfileValidatorFactory();
+
+  // The only instance that exists.
+  AutofillProfileValidator autofill_profile_validator_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidatorFactory);
+};
+
+}  // namespace autofill
+
+#endif  // IOS_CHROME_BROWSER_AUTOFILL_AUTOFILL_PROFILE_VALIDATOR_FACTORY_H_
diff --git a/ios/chrome/browser/autofill/automation/automation_action.mm b/ios/chrome/browser/autofill/automation/automation_action.mm
index a9bdcfa..aa0fa32 100644
--- a/ios/chrome/browser/autofill/automation/automation_action.mm
+++ b/ios/chrome/browser/autofill/automation/automation_action.mm
@@ -7,6 +7,7 @@
 #import "ios/chrome/browser/autofill/automation/automation_action.h"
 
 #include "base/guid.h"
+#include "base/mac/foundation_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -98,6 +99,19 @@
 @interface AutomationActionValidateField : AutomationAction
 @end
 
+// An action that selects a given option from a dropdown selector.
+// Checks are not made to confirm that given item is a dropdown.
+// We assume this action has a format resembling:
+// {
+//   "selectorType": "xpath",
+//   "selector": "//*[@id=\"shipping-user-lookup-options\"]",
+//   "context": [],
+//   "index": 1,
+//   "type": "select"
+// }
+@interface AutomationActionSelectDropdown : AutomationAction
+@end
+
 @implementation AutomationAction
 
 + (instancetype)actionWithValueDictionary:
@@ -119,6 +133,7 @@
     @"waitFor" : [AutomationActionWaitFor class],
     @"autofill" : [AutomationActionAutofill class],
     @"validateField" : [AutomationActionValidateField class],
+    @"select" : [AutomationActionSelectDropdown class],
     // More to come.
   };
 
@@ -181,6 +196,46 @@
   return expectedType;
 }
 
+// Returns an int corrensponding to the given key in the action
+// dictionary. Will raise a test failure if the key is missing or the value is
+// empty.
+- (int)getIntFromDictionaryWithKey:(std::string)key {
+  const base::Value* expectedTypeValue(
+      self.actionDictionary->FindKeyOfType(key, base::Value::Type::INTEGER));
+  GREYAssert(expectedTypeValue, @"%s is missing in action.", key.c_str());
+
+  return expectedTypeValue->GetInt();
+}
+
+// Runs the JS code passed in against the target element specified by the
+// selector passed in. The target element is passed in to the JS function
+// by the name "target", so example JS code is like:
+// return target.value
+- (id)executeJavascript:(std::string)function
+               onTarget:(web::test::ElementSelector)selector {
+  NSError* error;
+
+  id result = chrome_test_util::ExecuteJavaScript(
+      [NSString
+          stringWithFormat:@"    (function() {"
+                            "      try {"
+                            "        return function(target){%@}(%@);"
+                            "      } catch (ex) {return 'Exception encountered "
+                            "' + ex.message;}"
+                            "     "
+                            "    })();",
+                           base::SysUTF8ToNSString(function),
+                           base::SysUTF8ToNSString(
+                               selector.GetSelectorScript())],
+      &error);
+
+  if (error) {
+    GREYAssert(NO, @"Javascript execution error: %@", result);
+    return nil;
+  }
+  return result;
+}
+
 @end
 
 @implementation AutomationActionClick
@@ -227,16 +282,17 @@
     NSError* error;
     NSString* assertionString = base::SysUTF8ToNSString(assertion);
 
-    id result = chrome_test_util::ExecuteJavaScript(
-        [NSString stringWithFormat:@""
-                                    "    (function() {"
-                                    "      try {"
-                                    "        %@"
-                                    "      } catch (ex) {}"
-                                    "      return false;"
-                                    "    })();",
-                                   assertionString],
-        &error);
+    NSNumber* result =
+        base::mac::ObjCCastStrict<NSNumber>(chrome_test_util::ExecuteJavaScript(
+            [NSString stringWithFormat:@""
+                                        "    (function() {"
+                                        "      try {"
+                                        "        %@"
+                                        "      } catch (ex) {}"
+                                        "      return false;"
+                                        "    })();",
+                                       assertionString],
+            &error));
 
     if (![result boolValue] || error) {
       return assertionString;
@@ -348,12 +404,12 @@
   NSString* expectedValue = base::SysUTF8ToNSString(
       [self getStringFromDictionaryWithKey:"expectedValue"]);
 
-  NSString* predictionType =
-      [self executeJavascript:"return target.getAttribute('placeholder');"
-                     onTarget:[self selectorForTarget]];
+  NSString* predictionType = base::mac::ObjCCastStrict<NSString>([self
+      executeJavascript:"return target.getAttribute('placeholder');"
+               onTarget:[self selectorForTarget]]);
 
-  NSString* autofilledValue = [self executeJavascript:"return target.value;"
-                                             onTarget:[self selectorForTarget]];
+  NSString* autofilledValue = base::mac::ObjCCastStrict<NSString>(
+      [self executeJavascript:"return target.value;" onTarget:selector]);
 
   GREYAssertEqualObjects(predictionType, expectedType,
                          @"Expected prediction type %@ but got %@",
@@ -363,33 +419,23 @@
                          expectedValue, autofilledValue);
 }
 
-// Runs the JS code passed in against the target element specified by the
-// selector passed in. The target element is passed in to the JS function
-// by the name "target", so example JS code is like:
-// return target.value
-- (NSString*)executeJavascript:(std::string)function
-                      onTarget:(web::test::ElementSelector)selector {
-  NSError* error;
+@end
 
-  NSString* result = chrome_test_util::ExecuteJavaScript(
-      [NSString
-          stringWithFormat:@"    (function() {"
-                            "      try {"
-                            "        return function(target){%@}(%@);"
-                            "      } catch (ex) {return 'Exception encountered "
-                            "' + ex.message;}"
-                            "     "
-                            "    })();",
-                           base::SysUTF8ToNSString(function),
-                           base::SysUTF8ToNSString(
-                               selector.GetSelectorScript())],
-      &error);
+@implementation AutomationActionSelectDropdown
 
-  if (error) {
-    GREYAssert(NO, @"Javascript execution error: %@", result);
-    return nil;
-  }
-  return result;
+- (void)execute {
+  web::test::ElementSelector selector = [self selectorForTarget];
+
+  // Wait for the element to be visible on the page.
+  [ChromeEarlGrey waitForWebViewContainingElement:selector];
+
+  int selectedIndex = [self getIntFromDictionaryWithKey:"index"];
+  [self executeJavascript:
+            base::SysNSStringToUTF8([NSString
+                stringWithFormat:@"target.options.selectedIndex = %d; "
+                                 @"triggerOnChangeEventOnElement(target);",
+                                 selectedIndex])
+                 onTarget:selector];
 }
 
 @end
diff --git a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
index 1fb9d8e..4992d1b 100644
--- a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
+++ b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
@@ -74,4 +74,23 @@
   [waitForAction execute];
 }
 
+- (void)testAutomationActionSelectDropdown {
+  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kTestPageUrl)];
+
+  base::DictionaryValue selectDict = base::DictionaryValue();
+  selectDict.SetKey("type", base::Value("select"));
+  selectDict.SetKey("selector", base::Value("//*[@id=\"test_dropdown\"]"));
+  selectDict.SetKey("index", base::Value(1));
+  AutomationAction* selectAction =
+      [AutomationAction actionWithValueDictionary:selectDict];
+  [selectAction execute];
+
+  NSError* error;
+  id result = chrome_test_util::ExecuteJavaScript(
+      @"document.getElementById(\"test_dropdown\").value == \"dropdown_2\"",
+      &error);
+  GREYAssert([result boolValue] && !error,
+             @"Select automation action did not change the dropdown.");
+}
+
 @end
diff --git a/ios/chrome/browser/autofill/personal_data_manager_factory.cc b/ios/chrome/browser/autofill/personal_data_manager_factory.cc
index 14eb2867..20744b8 100644
--- a/ios/chrome/browser/autofill/personal_data_manager_factory.cc
+++ b/ios/chrome/browser/autofill/personal_data_manager_factory.cc
@@ -13,6 +13,7 @@
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/autofill/autofill_profile_validator_factory.h"
 #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/signin/identity_manager_factory.h"
@@ -55,6 +56,7 @@
   service->Init(
       autofill_db, nullptr, chrome_browser_state->GetPrefs(),
       IdentityManagerFactory::GetForBrowserState(chrome_browser_state),
+      AutofillProfileValidatorFactory::GetInstance(),
       chrome_browser_state->IsOffTheRecord());
   return service;
 }
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index 4e87d19..2847ed3f 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -280,15 +280,6 @@
     "When enabled, text in web pages will respect the user's Dynamic Type "
     "setting.";
 
-const char kWebPaymentsName[] = "Web Payments";
-const char kWebPaymentsDescription[] =
-    "Enable Payment Request API integration, a JavaScript API for merchants.";
-
-const char kWebPaymentsNativeAppsName[] = "Web Payments Native Apps";
-const char kWebPaymentsNativeAppsDescription[] =
-    "Enable third party iOS native apps as payments methods within Payment "
-    "Request.";
-
 const char kWKHTTPSystemCookieStoreName[] = "Use WKHTTPSystemCookieStore.";
 const char kWKHTTPSystemCookieStoreDescription[] =
     "Use WKHTTPCookieStore backed store for main context URL requests.";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index 9258ffc..afefa2d 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -232,15 +232,6 @@
 extern const char kWebPageTextAccessibilityName[];
 extern const char kWebPageTextAccessibilityDescription[];
 
-// Title and description for the flag to enable Web Payments.
-extern const char kWebPaymentsName[];
-extern const char kWebPaymentsDescription[];
-
-// Title and description for the flag to enable third party payment app
-// integration with Web Payments.
-extern const char kWebPaymentsNativeAppsName[];
-extern const char kWebPaymentsNativeAppsDescription[];
-
 // Title and description for the flag to enable WKHTTPSystemCookieStore usage
 // for main context URL requests.
 extern const char kWKHTTPSystemCookieStoreName[];
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 5b6001b1..6a89e7b 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -39,7 +39,6 @@
 #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
 #include "components/infobars/core/infobar_manager.h"
 #import "components/language/ios/browser/ios_language_detection_tab_helper.h"
-#include "components/payments/core/features.h"
 #include "components/prefs/pref_service.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "components/search_engines/search_engines_pref_names.h"
@@ -2375,14 +2374,12 @@
   _externalSearchCoordinator = [[ExternalSearchCoordinator alloc] init];
   _externalSearchCoordinator.dispatcher = _dispatcher;
 
-  if (base::FeatureList::IsEnabled(payments::features::kWebPayments)) {
-    _paymentRequestManager = [[PaymentRequestManager alloc]
-        initWithBaseViewController:self
-                      browserState:_browserState
-                        dispatcher:self.dispatcher];
-    [_paymentRequestManager setToolbarModel:_toolbarModel.get()];
-    [_paymentRequestManager setActiveWebState:[_model currentTab].webState];
-  }
+  _paymentRequestManager = [[PaymentRequestManager alloc]
+      initWithBaseViewController:self
+                    browserState:_browserState
+                      dispatcher:self.dispatcher];
+  [_paymentRequestManager setToolbarModel:_toolbarModel.get()];
+  [_paymentRequestManager setActiveWebState:[_model currentTab].webState];
 }
 
 // Set the frame for the various views. View must be loaded.
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
index 02322da9..3b080bf 100644
--- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -11,9 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
-#include "components/payments/core/features.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/sessions/core/tab_restore_service.h"
@@ -350,25 +348,4 @@
                            dismissOmnibox:YES];
 }
 
-// Tests for the browser view controller when Payment Request is enabled.
-class PaymentRequestBrowserViewControllerTest
-    : public BrowserViewControllerTest {
- public:
-  PaymentRequestBrowserViewControllerTest() {}
-
- protected:
-  void SetUp() override {
-    feature_list_.InitAndEnableFeature(payments::features::kWebPayments);
-    BrowserViewControllerTest::SetUp();
-  }
-
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Verifies that the controller starts up and shuts down cleanly with Payment
-// Request enabled.
-TEST_F(PaymentRequestBrowserViewControllerTest, TestStartupAndShutdown) {
-  // The body of this test is deliberately left empty.
-}
-
 }  // namespace
diff --git a/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm b/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm
index 7f894edd..88ad71a 100644
--- a/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_egtest_base.mm
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <memory>
 
-#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
@@ -15,7 +14,6 @@
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/payments/core/features.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
 #include "ios/chrome/browser/payments/ios_payment_request_cache_factory.h"
@@ -52,16 +50,6 @@
 
 #pragma mark - XCTestCase
 
-+ (void)setUp {
-  [super setUp];
-  if (!base::FeatureList::IsEnabled(payments::features::kWebPayments)) {
-    // payments::features::kWebPayments feature is not enabled,
-    // You have to pass --enable-features=WebPayments command line argument in
-    // order to run this test.
-    DCHECK(false);
-  }
-}
-
 - (void)setUp {
   [super setUp];
   _personalDataManager =
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index ed2b1d578..9779c9f 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -11,7 +11,6 @@
 #include "base/mac/bundle_locations.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/dom_distiller/core/url_constants.h"
-#include "components/payments/core/features.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "ios/chrome/browser/application_context.h"
@@ -187,9 +186,7 @@
     [scripts addObject:GetPageScript(@"credential_manager")];
   }
 
-  if (base::FeatureList::IsEnabled(payments::features::kWebPayments)) {
-    [scripts addObject:GetPageScript(@"payment_request")];
-  }
+  [scripts addObject:GetPageScript(@"payment_request")];
 
   return [scripts componentsJoinedByString:@";"];
 }
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index 925b45e..f98d759 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -13,7 +13,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
-#include "components/payments/core/features.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/passwords/credential_manager_features.h"
 #import "ios/chrome/browser/web/error_page_util.h"
@@ -163,16 +162,13 @@
                              web_view, @"typeof navigator.credentials"));
 }
 
-// Tests that ChromeWebClient provides payment request script for WKWebView if
-// the feature is enabled.
-TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPaymentRequestEnabled) {
+// Tests that ChromeWebClient provides payment request script for WKWebView.
+TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPaymentRequest) {
   // Chrome scripts rely on __gCrWeb object presence.
   WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
   web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
 
   web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(payments::features::kWebPayments);
   NSString* script =
       web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
   web::test::ExecuteJavaScript(web_view, script);
@@ -180,23 +176,6 @@
                                web_view, @"typeof window.PaymentRequest"));
 }
 
-// Tests that ChromeWebClient does not provide payment request script for
-// WKWebView if the feature is disabled.
-TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPaymentRequestDisabled) {
-  // Chrome scripts rely on __gCrWeb object presence.
-  WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
-  web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
-
-  web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(payments::features::kWebPayments);
-  NSString* script =
-      web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
-  web::test::ExecuteJavaScript(web_view, script);
-  EXPECT_NSEQ(@"undefined", web::test::ExecuteJavaScript(
-                                web_view, @"typeof window.PaymentRequest"));
-}
-
 // Tests PrepareErrorPage wth non-post, not Off The Record error.
 TEST_F(ChromeWebClientTest, PrepareErrorPageNonPostNonOtr) {
   ChromeWebClient web_client;
diff --git a/ios/web_view/internal/autofill/web_view_personal_data_manager_factory.cc b/ios/web_view/internal/autofill/web_view_personal_data_manager_factory.cc
index fc64bf2..c13a0f7 100644
--- a/ios/web_view/internal/autofill/web_view_personal_data_manager_factory.cc
+++ b/ios/web_view/internal/autofill/web_view_personal_data_manager_factory.cc
@@ -57,7 +57,7 @@
   service->Init(
       autofill_db, nullptr, browser_state->GetPrefs(),
       WebViewIdentityManagerFactory::GetForBrowserState(browser_state),
-      browser_state->IsOffTheRecord());
+      /*client_profile_validator=*/nullptr, browser_state->IsOffTheRecord());
   return service;
 }
 
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 6b7ecca..c1fc438 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -323,7 +323,7 @@
       "fuchsia/audio_output_stream_fuchsia.cc",
       "fuchsia/audio_output_stream_fuchsia.h",
     ]
-    deps += [ "//third_party/fuchsia-sdk:media" ]
+    deps += [ "//third_party/fuchsia-sdk/sdk:media" ]
   }
 
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index 5bca4f2..d03c4e8 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -36,9 +36,6 @@
 #include "media/base/provision_fetcher.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
-// In SHARED_INTERMEDIATE_DIR
-#include "widevine_cdm_version.h"  // NOLINT(build/include)
-
 using base::android::AttachCurrentThread;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertJavaStringToUTF8;
diff --git a/media/base/android/media_drm_bridge_unittest.cc b/media/base/android/media_drm_bridge_unittest.cc
index 699fee6..2458dfd0 100644
--- a/media/base/android/media_drm_bridge_unittest.cc
+++ b/media/base/android/media_drm_bridge_unittest.cc
@@ -14,8 +14,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
-#include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
-
 namespace media {
 
 #define EXPECT_TRUE_IF_WIDEVINE_AVAILABLE(a)                              \
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 253f3fd..c6d0d94 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1131,10 +1131,12 @@
 
   gfx::Rect gfx_rect(rect);
   Context3D context_3d;
+  gpu::ContextSupport* context_support = nullptr;
   if (video_frame.get() && video_frame->HasTextures()) {
     if (context_provider_) {
       context_3d = Context3D(context_provider_->ContextGL(),
                              context_provider_->GrContext());
+      context_support = context_provider_->ContextSupport();
     }
     if (!context_3d.gl)
       return;  // Unable to get/create a shared main thread context.
@@ -1152,7 +1154,8 @@
   }
   video_renderer_.Paint(
       video_frame, canvas, gfx::RectF(gfx_rect), flags,
-      pipeline_metadata_.video_decoder_config.video_rotation(), context_3d);
+      pipeline_metadata_.video_decoder_config.video_rotation(), context_3d,
+      context_support);
 }
 
 bool WebMediaPlayerImpl::DidGetOpaqueResponseFromServiceWorker() const {
@@ -1238,13 +1241,15 @@
   }
 
   Context3D context_3d;
+  gpu::ContextSupport* context_support = nullptr;
   if (context_provider_) {
     context_3d = Context3D(context_provider_->ContextGL(),
                            context_provider_->GrContext());
+    context_support = context_provider_->ContextSupport();
   }
   return video_renderer_.CopyVideoFrameTexturesToGLTexture(
-      context_3d, gl, video_frame.get(), target, texture, internal_format,
-      format, type, level, premultiply_alpha, flip_y);
+      context_3d, context_support, gl, video_frame.get(), target, texture,
+      internal_format, format, type, level, premultiply_alpha, flip_y);
 }
 
 // static
diff --git a/media/ffmpeg/ffmpeg_regression_tests.cc b/media/ffmpeg/ffmpeg_regression_tests.cc
index 554eba4..b20644c 100644
--- a/media/ffmpeg/ffmpeg_regression_tests.cc
+++ b/media/ffmpeg/ffmpeg_regression_tests.cc
@@ -116,10 +116,7 @@
                  "security/117912.webm",
                  DEMUXER_ERROR_COULD_NOT_OPEN,
                  DEMUXER_ERROR_COULD_NOT_OPEN);
-FFMPEG_TEST_CASE(Cr123481,
-                 "security/123481.ogv",
-                 DEMUXER_ERROR_COULD_NOT_PARSE,
-                 DEMUXER_ERROR_COULD_NOT_PARSE);
+FFMPEG_TEST_CASE(Cr123481, "security/123481.ogv", PIPELINE_OK, PIPELINE_OK);
 FFMPEG_TEST_CASE(Cr132779,
                  "security/132779.webm",
                  DEMUXER_ERROR_COULD_NOT_PARSE,
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc
index 8d12b5f..3a181ba1 100644
--- a/media/renderers/paint_canvas_video_renderer.cc
+++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -14,6 +14,7 @@
 #include "cc/paint/paint_image.h"
 #include "cc/paint/paint_image_builder.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
@@ -275,6 +276,35 @@
   }
 }
 
+void OnQueryDone(scoped_refptr<VideoFrame> video_frame,
+                 gpu::gles2::GLES2Interface* gl,
+                 unsigned query_id) {
+  gl->DeleteQueriesEXT(1, &query_id);
+  // |video_frame| is dropped here.
+}
+
+void SynchronizeVideoFrameRead(scoped_refptr<VideoFrame> video_frame,
+                               gpu::gles2::GLES2Interface* gl,
+                               gpu::ContextSupport* context_support) {
+  DCHECK(gl);
+  DCHECK(context_support);
+
+  SyncTokenClientImpl client(gl);
+  video_frame->UpdateReleaseSyncToken(&client);
+
+  if (video_frame->metadata()->IsTrue(
+          VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) {
+    // |video_frame| must be kept alive during read operations.
+    unsigned query_id = 0;
+    gl->GenQueriesEXT(1, &query_id);
+    DCHECK(query_id);
+    gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id);
+    gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+    context_support->SignalQuery(
+        query_id, base::BindOnce(&OnQueryDone, video_frame, gl, query_id));
+  }
+}
+
 }  // anonymous namespace
 
 // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
@@ -416,7 +446,8 @@
     const gfx::RectF& dest_rect,
     cc::PaintFlags& flags,
     VideoRotation video_rotation,
-    const Context3D& context_3d) {
+    const Context3D& context_3d,
+    gpu::ContextSupport* context_support) {
   DCHECK(thread_checker_.CalledOnValidThread());
   if (flags.getAlpha() == 0) {
     return;
@@ -509,22 +540,23 @@
   canvas->flush();
 
   if (video_frame->HasTextures()) {
-    DCHECK(gl);
-    SyncTokenClientImpl client(gl);
-    video_frame->UpdateReleaseSyncToken(&client);
+    // Synchronize |video_frame| with the read operations in UpdateLastImage(),
+    // which are triggered by canvas->flush().
+    SynchronizeVideoFrameRead(video_frame, gl, context_support);
   }
 }
 
 void PaintCanvasVideoRenderer::Copy(
     const scoped_refptr<VideoFrame>& video_frame,
     cc::PaintCanvas* canvas,
-    const Context3D& context_3d) {
+    const Context3D& context_3d,
+    gpu::ContextSupport* context_support) {
   cc::PaintFlags flags;
   flags.setBlendMode(SkBlendMode::kSrc);
   flags.setFilterQuality(kLow_SkFilterQuality);
   Paint(video_frame, canvas,
         gfx::RectF(gfx::SizeF(video_frame->visible_rect().size())), flags,
-        media::VIDEO_ROTATION_0, context_3d);
+        media::VIDEO_ROTATION_0, context_3d, context_support);
 }
 
 namespace {
@@ -901,14 +933,14 @@
                                     target, texture, internal_format, format,
                                     type, level, premultiply_alpha, flip_y);
   gl->DeleteTextures(1, &source_texture);
-  gl->Flush();
-
-  SyncTokenClientImpl client(gl);
-  video_frame->UpdateReleaseSyncToken(&client);
+  gl->ShallowFlushCHROMIUM();
+  // The caller must call SynchronizeVideoFrameRead() after this operation, but
+  // we can't do that because we don't have the ContextSupport.
 }
 
 bool PaintCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture(
     const Context3D& context_3d,
+    gpu::ContextSupport* context_support,
     gpu::gles2::GLES2Interface* destination_gl,
     const scoped_refptr<VideoFrame>& video_frame,
     unsigned int target,
@@ -922,7 +954,9 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(video_frame);
   DCHECK(video_frame->HasTextures());
-  if (video_frame->NumTextures() > 1) {
+  if (video_frame->NumTextures() > 1 ||
+      video_frame->metadata()->IsTrue(
+          VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) {
     if (!context_3d.gr_context)
       return false;
     if (!UpdateLastImage(video_frame, context_3d))
@@ -936,7 +970,11 @@
     if (!backend_texture.getGLTextureInfo(&texture_info))
       return false;
 
+    // Synchronize |video_frame| with the read operations in UpdateLastImage(),
+    // which are triggered by getBackendTexture().
     gpu::gles2::GLES2Interface* canvas_gl = context_3d.gl;
+    SynchronizeVideoFrameRead(video_frame, canvas_gl, context_support);
+
     gpu::MailboxHolder mailbox_holder;
     mailbox_holder.texture_target = texture_info.fTarget;
     canvas_gl->ProduceTextureDirectCHROMIUM(texture_info.fID,
@@ -964,9 +1002,6 @@
     gpu::SyncToken dest_sync_token;
     destination_gl->GenUnverifiedSyncTokenCHROMIUM(dest_sync_token.GetData());
     canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData());
-
-    SyncTokenClientImpl client(canvas_gl);
-    video_frame->UpdateReleaseSyncToken(&client);
   } else {
     CopyVideoFrameSingleTextureToGLTexture(
         destination_gl, video_frame.get(), target, texture, internal_format,
@@ -1208,8 +1243,9 @@
       return false;
     last_id_ = video_frame->unique_id();
   }
+
+  DCHECK(last_image_);
   last_image_deleting_timer_.Reset();
-  DCHECK(!!last_image_);
   return true;
 }
 
diff --git a/media/renderers/paint_canvas_video_renderer.h b/media/renderers/paint_canvas_video_renderer.h
index d732111..d4752f3 100644
--- a/media/renderers/paint_canvas_video_renderer.h
+++ b/media/renderers/paint_canvas_video_renderer.h
@@ -29,6 +29,7 @@
 
 namespace gpu {
 struct Capabilities;
+class ContextSupport;
 }
 
 namespace media {
@@ -39,25 +40,29 @@
   PaintCanvasVideoRenderer();
   ~PaintCanvasVideoRenderer();
 
-  // Paints |video_frame| on |canvas|, scaling and rotating the result to fit
-  // dimensions specified by |dest_rect|.
-  // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d|
-  // must be provided.
+  // Paints |video_frame| translated and scaled to |dest_rect| on |canvas|.
   //
-  // Black will be painted on |canvas| if |video_frame| is null.
+  // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d|
+  // and |context_support| must be provided.
+  //
+  // If |video_frame| is nullptr or an unsupported format, |dest_rect| will be
+  // painted black.
   void Paint(const scoped_refptr<VideoFrame>& video_frame,
              cc::PaintCanvas* canvas,
              const gfx::RectF& dest_rect,
              cc::PaintFlags& flags,
              VideoRotation video_rotation,
-             const Context3D& context_3d);
+             const Context3D& context_3d,
+             gpu::ContextSupport* context_support);
 
-  // Copy |video_frame| on |canvas|.
+  // Paints |video_frame| scaled to its visible size on |canvas|.
+  //
   // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d|
-  // must be provided.
+  // and |context_support| must be provided.
   void Copy(const scoped_refptr<VideoFrame>& video_frame,
             cc::PaintCanvas* canvas,
-            const Context3D& context_3d);
+            const Context3D& context_3d,
+            gpu::ContextSupport* context_support);
 
   // Convert the contents of |video_frame| to raw RGB pixels. |rgb_pixels|
   // should point into a buffer large enough to hold as many 32 bit RGBA pixels
@@ -82,15 +87,12 @@
       bool premultiply_alpha,
       bool flip_y);
 
-  // Copy the contents of texture of |video_frame| to texture |texture| in
-  // context |destination_gl|.
-  // |level|, |internal_format|, |type| specify target texture |texture|.
+  // Copy the contents of |video_frame| to |texture| of |destination_gl|.
+  //
   // The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE.
-  // |context_3d| has a GrContext that may be used during the copy.
-  // CorrectLastImageDimensions() ensures that the source texture will be
-  // cropped to |visible_rect|. Returns true on success.
   bool CopyVideoFrameTexturesToGLTexture(
       const Context3D& context_3d,
+      gpu::ContextSupport* context_support,
       gpu::gles2::GLES2Interface* destination_gl,
       const scoped_refptr<VideoFrame>& video_frame,
       unsigned int target,
@@ -168,8 +170,6 @@
   // never be painted again, so we can release the resource.
   void ResetCache();
 
-  void CorrectLastImageDimensions(const SkIRect& visible_rect);
-
   // Used for unit test.
   SkISize LastImageDimensionsForTesting();
 
@@ -179,6 +179,8 @@
   bool UpdateLastImage(const scoped_refptr<VideoFrame>& video_frame,
                        const Context3D& context_3d);
 
+  void CorrectLastImageDimensions(const SkIRect& visible_rect);
+
   // Last image used to draw to the canvas.
   cc::PaintImage last_image_;
 
diff --git a/media/renderers/paint_canvas_video_renderer_unittest.cc b/media/renderers/paint_canvas_video_renderer_unittest.cc
index 3bca993..bd321305 100644
--- a/media/renderers/paint_canvas_video_renderer_unittest.cc
+++ b/media/renderers/paint_canvas_video_renderer_unittest.cc
@@ -225,7 +225,7 @@
   cc::PaintFlags flags;
   flags.setFilterQuality(kLow_SkFilterQuality);
   renderer_.Paint(nullptr, canvas, kNaturalRect, flags, VIDEO_ROTATION_0,
-                  Context3D());
+                  Context3D(), nullptr);
 }
 
 void PaintCanvasVideoRendererTest::Paint(
@@ -260,13 +260,13 @@
   flags.setBlendMode(mode);
   flags.setFilterQuality(kLow_SkFilterQuality);
   renderer_.Paint(video_frame, canvas, dest_rect, flags, video_rotation,
-                  Context3D());
+                  Context3D(), nullptr);
 }
 
 void PaintCanvasVideoRendererTest::Copy(
     const scoped_refptr<VideoFrame>& video_frame,
     cc::PaintCanvas* canvas) {
-  renderer_.Copy(video_frame, canvas, Context3D());
+  renderer_.Copy(video_frame, canvas, Context3D(), nullptr);
 }
 
 TEST_F(PaintCanvasVideoRendererTest, NoFrame) {
@@ -564,7 +564,7 @@
   flags.setFilterQuality(kNone_SkFilterQuality);
   renderer_.Paint(video_frame, &canvas,
                   gfx::RectF(bitmap.width(), bitmap.height()), flags,
-                  VIDEO_ROTATION_0, Context3D());
+                  VIDEO_ROTATION_0, Context3D(), nullptr);
   for (int j = 0; j < bitmap.height(); j++) {
     for (int i = 0; i < bitmap.width(); i++) {
       const int value = i + j * bitmap.width();
@@ -657,43 +657,32 @@
   cc::PaintFlags flags;
   flags.setFilterQuality(kLow_SkFilterQuality);
   renderer_.Paint(video_frame, &canvas, kNaturalRect, flags, VIDEO_ROTATION_90,
-                  context_3d);
+                  context_3d, nullptr);
 }
 
 void EmptyCallback(const gpu::SyncToken& sync_token) {}
 
 TEST_F(PaintCanvasVideoRendererTest, CorrectFrameSizeToVisibleRect) {
-  int fWidth{16}, fHeight{16};
+  constexpr int fWidth{16}, fHeight{16};
   SkImageInfo imInfo =
       SkImageInfo::MakeN32(fWidth, fHeight, kOpaque_SkAlphaType);
 
-  sk_sp<const GrGLInterface> glInterface(GrGLCreateNullInterface());
-  sk_sp<GrContext> grContext = GrContext::MakeGL(std::move(glInterface));
+  cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight));
 
-  sk_sp<SkSurface> surface =
-      SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, imInfo);
-  cc::SkiaPaintCanvas canvas(surface->getCanvas());
-
-  TestGLES2Interface gles2;
-  Context3D context_3d(&gles2, grContext.get());
   gfx::Size coded_size(fWidth, fHeight);
   gfx::Size visible_size(fWidth / 2, fHeight / 2);
 
-  gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
-  for (size_t i = 0; i < VideoFrame::kMaxPlanes; i++) {
-    mailbox_holders[i] = gpu::MailboxHolder(
-        gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_RECTANGLE_ARB);
-  }
+  uint8_t memory[fWidth * fHeight * 2] = {0};
 
-  auto video_frame = VideoFrame::WrapNativeTextures(
-      PIXEL_FORMAT_I420, mailbox_holders, base::Bind(EmptyCallback), coded_size,
-      gfx::Rect(visible_size), visible_size,
+  auto video_frame = media::VideoFrame::WrapExternalData(
+      media::PIXEL_FORMAT_Y16, coded_size, gfx::Rect(visible_size),
+      visible_size, &memory[0], fWidth * fHeight * 2,
       base::TimeDelta::FromMilliseconds(4));
 
   gfx::RectF visible_rect(visible_size.width(), visible_size.height());
   cc::PaintFlags flags;
   renderer_.Paint(video_frame, &canvas, visible_rect, flags, VIDEO_ROTATION_0,
-                  context_3d);
+                  Context3D(), nullptr);
 
   EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width());
   EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height());
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index 952c9a7..5b4abce 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -866,7 +866,7 @@
 
         // This is software path, so canvas and video_frame are always backed
         // by software.
-        video_renderer_->Copy(video_frame, &canvas, Context3D());
+        video_renderer_->Copy(video_frame, &canvas, Context3D(), nullptr);
       } else {
         HardwarePlaneResource* hardware_resource = plane_resource->AsHardware();
         size_t bytes_per_row = viz::ResourceSizes::CheckedWidthInBytes<size_t>(
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 19b6bc7..ea6c4c1 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2178,7 +2178,7 @@
     }
 
     if (is_fuchsia) {
-      public_deps += [ "//third_party/fuchsia-sdk:netstack" ]
+      public_deps += [ "//third_party/fuchsia-sdk/sdk:netstack" ]
     }
 
     if (use_platform_icu_alternatives) {
@@ -5374,7 +5374,7 @@
     use_test_server = true
     deps += [
       "//third_party/fuchsia-sdk:fidl_cpp",
-      "//third_party/fuchsia-sdk:netstack",
+      "//third_party/fuchsia-sdk/sdk:netstack",
     ]
     sources += [ "base/network_change_notifier_fuchsia_unittest.cc" ]
   }
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index be599a2b..275a0903 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -26627,7 +26627,6 @@
     { "name": "mosin.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "mosos.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "motorcheck.ie", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "mottomortgage.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "moumaobuchiyu.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "moviepilot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "movingtohttps.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -42910,7 +42909,6 @@
     { "name": "kopjethee.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koppelvlak.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "korben.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kostal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kotly-marten.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kouten-jp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koval.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -43996,7 +43994,6 @@
     { "name": "cozo.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "craftydev.design", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "creativefolks.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "creatixx-network.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "credia.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "credigo.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "creorin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -45158,7 +45155,6 @@
     { "name": "jule-spil.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "juliankirchner.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "julibon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "jurisprudent.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "juul.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kalilinux.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "karalane.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48008,7 +48004,6 @@
     { "name": "avocatbeziau.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "avptp.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "axchap.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "axfr.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "axonholdingse.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "b4ckbone.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "b4r7.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -54870,7 +54865,6 @@
     { "name": "grillen-darf-nicht-gesund-sein.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "grottenthaler.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "grrmmll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "gsdb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gtopala.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "guerard.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hacertest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58816,6 +58810,517 @@
     { "name": "zqstudio.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zyzsdy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zz295.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "08detaxe.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0x48.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "10xiuxiu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2012.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2chan.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2chan.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4x4tt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "65d88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aaex.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "actualadmins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adnanoktar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "advancedsurgicalconsultantsllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adventaholdings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aegisinsight.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aeronautix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "akademie-frankfurt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "albertcuyp-markt.amsterdam", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "albinma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "algeriepart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alinbu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "almut-zielonka.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alstertouch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alstertouch.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "am-executive-consulting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amandadamsphotography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anabolic.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antaresmedia.com.py", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antvklik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anwalt.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aoil.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "argonium.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armin-cme.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armin-cpe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atlanticpediatricortho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "awecademy.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "axiatancell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "azsupport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bagelcraft.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baserverz.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bauernmarkt-fernitz.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "baur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beer9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bellyandbrain.amsterdam", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biehl.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biehl.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blackjackballroomcasino.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blackroot.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blogsdna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blokmy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonniecoloring.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonniedraw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonsi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "borneodictionary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boulderswap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "breaky.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brightworkcreative.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brody.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brody.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brycecanyon.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buena-vista.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "builtory.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "burzmedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "busyon.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bytrain.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cadcreations.co.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "caldaro.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calebennett.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "callidus-vulpes.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cargomaps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carrosserie-dubois.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "catering-xanadu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cecame.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centa-am.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cespri.com.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cg-goerlitz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chattersworld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chauffage-budget.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chci-web.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christwaycounseling.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clush.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cme-colleg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "co2eco.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "codecommunity.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "codevat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "codimaker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coinroom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "complexorganizations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comvos.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cordejong.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "corvax.kiev.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cpe-colleg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cplala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "craftsmany.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "createcos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "creditta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crimesolutions.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cstrong.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cxadd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "d88688.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "d88871.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "d88988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "darklaunch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "davypropper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dedicatedtowomenobgyn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deepinsight.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deliveryiquique.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "destinyofthephoenix.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "desuchan.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "desuchan.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "diamond-hairstyle.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dinerroboticurology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "disinfestazioni.gorizia.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dive-japan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dlcwilson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dojozendebourges.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doleta.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "domwkwiatach.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dongjingre.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dostalsecurity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dragonwolfpackaquaria.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drakecommercial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreamlordpress.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreatho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drinkgas-jihlava.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drlutfi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drpetervoigt.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drschlarb.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dstvinstallalberton.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dtpak.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dvdinmotion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eco2u.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "efipsactiva.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ekostrateg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eldercare.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elderjustice.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eletor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eletor.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eliaskordelakos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elielaloum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eligibilis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elo-forum.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epicdowney.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "estetistarimini.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "estudio21pattern.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eurodentaire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "everettsautorepair.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "excelhot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "expe.voyage", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "expertvagabond.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exxo.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fabian-klose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fabian-klose.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fabian-klose.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faidatefacile.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fantasticservicesgroup.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fateitalia.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faultlines.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fbi.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fccarbon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feeeei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feuerwehr-gebirge.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "finkmartin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "firekoi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fixed.supply", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flavinus.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "floresvilleedc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "formulastudent.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fotoboxvysocina.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fpsclasico.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fq.mk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freebies.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freesslcertificate.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "friedenauer-herbstfest.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frownonline.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "frpg.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fs-g.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fsg.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "futaba-works.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "g-ds.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaengler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "galilel.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gameanalytics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gamechefpummarola.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gcodetools.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gorealya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "happybirthdaywisher.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "healthdata.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heartyapp.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "henke-home.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hiparish.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hoish.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "holycrossphl.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hostinecpodlipou.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hpage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "humass.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iaitouzi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibykos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ifly.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ikudo.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ilovequiz.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ilovethiscampsite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "im-haus-sonnenschein.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "indiecongdr.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "info-screen-usercontent.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "interpol.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "introverted.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "invasivespeciesinfo.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "invinoaustria.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "invinoaustria.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ipid.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iszy.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itap.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itsv.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iwyc.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jack2celebrities.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jacksorrell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "javik.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jazminguaramato.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jazzy-feet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jikegu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jlpn.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jlpn.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joanofarcmtcarmel.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joinus-outfits.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jonasled.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joompress.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jtconsultancy.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jwod.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "k-bone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kalkulacka-havarijni.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kanzlei-gaengler.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kara-fabian.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "karewan.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "katzrkool.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kevin-darmor.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kimono-rental-one.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kleding.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "klose.family", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "klubxanadu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "koenzk.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ks88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kunra.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kurumi.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kvalitetsaktiepodden.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "la-fenice-neheim.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "labcenter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lamontre.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lazistance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lcacommons.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "led-jihlava.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leekspin.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lemazol.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lenou.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leontiekoetter.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lifetree.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ligadosgames.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livi.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livi.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livres-et-stickers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lizmooredestinationweddings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "llemoz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "llnl.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loanreadycredit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "locomocosec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "long139.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "long18.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "long688.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longtermcare.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "loteamentomontereiitu.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lovemanagementaccounts.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lsscreens.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m-monitor.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "made-to-usb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magicalshuttle.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maillink.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "majorpaintingco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malik.holdings", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mambas.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "manti.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maquininhamercadopoint.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marinecadastre.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mariskavankasbergen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marketingbrandingnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marksmanhomes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marsikelektro.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mazenjobs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mecaniquemondor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medellinapartamentos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mediahaus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medpeer.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megakoncert90.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "merakilp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mers.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "metric.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mglink.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "microzubr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minfin.gov.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "minutashop.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mkie.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mmmaximaliselmeny.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moekes.amsterdam", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mokken-fabriek.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "montgomerysoccer.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mostholynameofjesus.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mruczek.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mssora.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mta.org.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtravelers.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muz2u.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mydoc.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mygedit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myweddingaway.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mzstatic.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nefro-cme.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neheim-huesten.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neuber.uno", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nfpors.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ngt.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nifc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nihtek.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nij.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ninetailed.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nixtest.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nkforum.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "northcreekresort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ntsb.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nutrition.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nvtc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obrienswine.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ocni-ambulance-most.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "okurapictures.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oldsticker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oldstmary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "olympeakgaming.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osti.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourladymountcarmel.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourladyofcalvary.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourladyoftheassumptionchurch.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ourladyqueenofmartyrs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paccolat.name", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paginaweb4u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "panzerscreen.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "patrick21.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peliweb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pension-am-alten-waschhaus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peperstraat.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "philipssupportforum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "philosophy.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pikalongwar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pintosbeeremovals.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pivniraj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pornsocket.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pracevjihlave.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "practisforms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "presidio.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prihatno.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proeflokaalbakker.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "progresswww.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "projectsafechildhood.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promods.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qtmsheep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raspitec.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "razvanburz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "realpropertyprofile.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rediverge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "refu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "regeneo.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reginfo.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reifr.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reo.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "responsepartner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richardfeinbergdds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rocis.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rokass.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rteguide.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rteworld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rths.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rthsoftware.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rttss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ryssl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saidtezel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sainthelenas.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saintjamestheapostle.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saintjohn-bocaraton.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salandalairconditioning.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "salidaswap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saludyvida.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saorsat.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sazavafest.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schlarb.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schneidr.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schwarz-gelbe-fuechse.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scra.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sebastian-tobie.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sendtrix.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "serinamusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "servicemembers.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sewa.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sfg-net.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sfg-net.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sfg-net.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sfg-net.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shee.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shinsyo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "silica-project.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "silica-project.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sinfonietta-meridiana.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smokefree.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soontm.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sopo.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sotai.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spartacuslife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spectroom.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spectrum.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sportabee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "st-bede.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "steemyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stfrancisnaugatuck.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stgabrielstowepa.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sthenryrc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stm32f4.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stmichaelunion.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "studio44.fit", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "studiohomebase.amsterdam", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stuffiwouldbuy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sullenholland.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supioka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "supmil.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sv-bachum-bergheim.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swiftcashforcars.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taiwania.capital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taiwania.vc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taiwaniacapital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taiwaniacapital.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taiwaniacapital.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tansuya.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taxi-jihlava.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "techbrawl.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "the-pack.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thelifeofmala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thevenueofhollywood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thrillernyc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tiekoetter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tilman.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toontown.team", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "topdroneusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "topgshop.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trade.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradernet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradernet.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "travelemy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "treussart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tribaljusticeandsafety.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trix360.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ulitroyo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usaseanconnect.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usdoj.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "userra.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "usphs.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ussst.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ustugov.kiev.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ustugova.kiev.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valek.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valkova.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valorizofficial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valueofblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vaporpunk.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "variomedia.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "varshasookt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vauceri.hr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "veneerssandiego.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vila-eden.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "villa-eden.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "virtualspeech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vlakem.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vos-systems.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vseomedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vtuber.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webutils.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weems.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whirlpool.net.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskygentle.men", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whitehouseconferenceonaging.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "winningattitudeawards.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "worker.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "worldsinperil.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wyydsb.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wyydsb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wyydsb.xin", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xanadu-auto.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xanadu-catering.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xanadu-golf.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xanadu-trans.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xiangfajia.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xliang.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xmine128.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--ehqw04eq6e.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yellotalk.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yhenke.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youpickfarms.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "your-waterserver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "youthrules.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yxs.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeibekiko-souvlaki.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zirka24.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zl0iu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zl8862.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zunda.cafe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zxc.science", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/third_party/spdy/PRESUBMIT.py b/net/third_party/spdy/PRESUBMIT.py
index fc3a1a08..09ab19bf 100644
--- a/net/third_party/spdy/PRESUBMIT.py
+++ b/net/third_party/spdy/PRESUBMIT.py
@@ -50,8 +50,8 @@
       "Include \"net/third_party/spdy/platform/api/spdy_string_utils.h\" "
           "instead of \"net/base/hex_utils.h\"",
       "Use SpdyStringPiece instead of base::StringPiece",
-      "Use SpdyStringPrintf instead of base::StringPrintf",
-      "Use SpdyStringAppendF instead of base::StringAppendF",
+      "Use SpdyStrCat instead of base::StringPrintf",
+      "Use SpdyStrCat instead of base::StringAppendF",
       "Use SpdyHexDigitToInt instead of base::HexDigitToInt",
       "Use SpdyHexDecode instead of HexDecode",
       "Use SpdyHexDump instead of HexDump",
diff --git a/net/third_party/spdy/core/hpack/hpack_entry.cc b/net/third_party/spdy/core/hpack/hpack_entry.cc
index 216438c..4776017 100644
--- a/net/third_party/spdy/core/hpack/hpack_entry.cc
+++ b/net/third_party/spdy/core/hpack/hpack_entry.cc
@@ -78,10 +78,10 @@
 }
 
 SpdyString HpackEntry::GetDebugString() const {
-  return SpdyStringPrintf(
-      "{ name: \"%.*s\", value: \"%.*s\", index: %d %s }", name_ref_.size(),
-      name_ref_.data(), value_ref_.size(), value_ref_.data(), insertion_index_,
-      (IsStatic() ? " static" : (IsLookup() ? " lookup" : " dynamic")));
+  return SpdyStrCat(
+      "{ name: \"", name_ref_, "\", value: \"", value_ref_,
+      "\", index: ", insertion_index_, " ",
+      (IsStatic() ? " static" : (IsLookup() ? " lookup" : " dynamic")), " }");
 }
 
 size_t HpackEntry::EstimateMemoryUsage() const {
diff --git a/net/third_party/spdy/core/spdy_alt_svc_wire_format.cc b/net/third_party/spdy/core/spdy_alt_svc_wire_format.cc
index c8e0575..c19d855 100644
--- a/net/third_party/spdy/core/spdy_alt_svc_wire_format.cc
+++ b/net/third_party/spdy/core/spdy_alt_svc_wire_format.cc
@@ -47,7 +47,7 @@
       host(host),
       port(port),
       max_age(max_age),
-      version(version) {}
+      version(std::move(version)) {}
 
 SpdyAltSvcWireFormat::AlternativeService::~AlternativeService() = default;
 
@@ -264,9 +264,9 @@
       }
       value.push_back(c);
     }
-    SpdyStringAppendF(&value, ":%d\"", altsvc.port);
+    value.append(SpdyStrCat(":", altsvc.port, "\""));
     if (altsvc.max_age != 86400) {
-      SpdyStringAppendF(&value, "; ma=%d", altsvc.max_age);
+      value.append(SpdyStrCat("; ma=", altsvc.max_age));
     }
     if (!altsvc.version.empty()) {
       if (is_ietf_format_quic) {
@@ -281,7 +281,7 @@
           if (it != altsvc.version.begin()) {
             value.append(",");
           }
-          SpdyStringAppendF(&value, "%d", *it);
+          value.append(SpdyStrCat(*it));
         }
         value.append("\"");
       }
diff --git a/net/third_party/spdy/platform/api/spdy_string_utils.h b/net/third_party/spdy/platform/api/spdy_string_utils.h
index e789287..f8fd0ca0 100644
--- a/net/third_party/spdy/platform/api/spdy_string_utils.h
+++ b/net/third_party/spdy/platform/api/spdy_string_utils.h
@@ -29,16 +29,6 @@
   SpdyStrAppendImpl(output, std::forward<const Args&>(args)...);
 }
 
-template <typename... Args>
-inline SpdyString SpdyStringPrintf(const Args&... args) {
-  return SpdyStringPrintfImpl(std::forward<const Args&>(args)...);
-}
-
-template <typename... Args>
-inline void SpdyStringAppendF(const Args&... args) {
-  SpdyStringAppendFImpl(std::forward<const Args&>(args)...);
-}
-
 inline char SpdyHexDigitToInt(char c) {
   return SpdyHexDigitToIntImpl(c);
 }
diff --git a/net/third_party/spdy/platform/api/spdy_string_utils_test.cc b/net/third_party/spdy/platform/api/spdy_string_utils_test.cc
index bd0c1d4..62ca20f 100644
--- a/net/third_party/spdy/platform/api/spdy_string_utils_test.cc
+++ b/net/third_party/spdy/platform/api/spdy_string_utils_test.cc
@@ -165,29 +165,6 @@
   EXPECT_EQ("foo1foo081bar3.141513.141511bar18bar13.14150", output);
 }
 
-TEST(SpdyStringUtilsTest, SpdyStringPrintf) {
-  EXPECT_EQ("", SpdyStringPrintf("%s", ""));
-  EXPECT_EQ("foobar", SpdyStringPrintf("%sbar", "foo"));
-  EXPECT_EQ("foobar", SpdyStringPrintf("%s%s", "foo", "bar"));
-  EXPECT_EQ("foo: 1, bar: 2.0", SpdyStringPrintf("foo: %d, bar: %.1f", 1, 2.0));
-}
-
-TEST(SpdyStringUtilsTest, SpdyStringAppendF) {
-  SpdyString output;
-
-  SpdyStringAppendF(&output, "%s", "");
-  EXPECT_TRUE(output.empty());
-
-  SpdyStringAppendF(&output, "%sbar", "foo");
-  EXPECT_EQ("foobar", output);
-
-  SpdyStringAppendF(&output, "%s%s", "foo", "bar");
-  EXPECT_EQ("foobarfoobar", output);
-
-  SpdyStringAppendF(&output, "foo: %d, bar: %.1f", 1, 2.0);
-  EXPECT_EQ("foobarfoobarfoo: 1, bar: 2.0", output);
-}
-
 TEST(SpdyStringUtilsTest, SpdyHexDigitToInt) {
   EXPECT_EQ(0, SpdyHexDigitToInt('0'));
   EXPECT_EQ(1, SpdyHexDigitToInt('1'));
diff --git a/net/third_party/spdy/platform/impl/spdy_string_utils_impl.h b/net/third_party/spdy/platform/impl/spdy_string_utils_impl.h
index b7fdd101..b764ebe 100644
--- a/net/third_party/spdy/platform/impl/spdy_string_utils_impl.h
+++ b/net/third_party/spdy/platform/impl/spdy_string_utils_impl.h
@@ -31,16 +31,6 @@
   output->append(SpdyStrCatImpl(args...));
 }
 
-template <typename... Args>
-inline SpdyString SpdyStringPrintfImpl(const Args&... args) {
-  return base::StringPrintf(std::forward<const Args&>(args)...);
-}
-
-template <typename... Args>
-inline void SpdyStringAppendFImpl(const Args&... args) {
-  base::StringAppendF(std::forward<const Args&>(args)...);
-}
-
 inline char SpdyHexDigitToIntImpl(char c) {
   return base::HexDigitToInt(c);
 }
diff --git a/services/content/navigable_contents_impl.cc b/services/content/navigable_contents_impl.cc
index aba1696..97d5484 100644
--- a/services/content/navigable_contents_impl.cc
+++ b/services/content/navigable_contents_impl.cc
@@ -102,6 +102,7 @@
   DCHECK(!local_view_host_);
   local_view_host_ = std::make_unique<views::NativeViewHost>();
   local_view_host_->set_owned_by_client();
+  view->set_native_view(local_view_host_->native_view());
   view->view()->AddChildView(local_view_host_.get());
   view->view()->Layout();
   local_view_host_->Attach(native_content_view_);
diff --git a/services/content/public/cpp/BUILD.gn b/services/content/public/cpp/BUILD.gn
index f34a2b9..ad8a638 100644
--- a/services/content/public/cpp/BUILD.gn
+++ b/services/content/public/cpp/BUILD.gn
@@ -30,6 +30,7 @@
     "//base",
     "//net",
     "//services/content/public/mojom",
+    "//ui/gfx:native_widget_types",
     "//ui/gfx/geometry",
     "//url",
   ]
diff --git a/services/content/public/cpp/navigable_contents_view.cc b/services/content/public/cpp/navigable_contents_view.cc
index fd5c1f6..aea39112 100644
--- a/services/content/public/cpp/navigable_contents_view.cc
+++ b/services/content/public/cpp/navigable_contents_view.cc
@@ -19,6 +19,7 @@
 #if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
 #include "services/ws/public/mojom/window_tree_constants.mojom.h"  // nogncheck
 #include "ui/base/ui_base_features.h"                   // nogncheck
+#include "ui/views/controls/native/native_view_host.h"  // nogncheck
 #include "ui/views/mus/remote_view/remote_view_host.h"  // nogncheck
 #endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
 #endif  // defined(TOOLKIT_VIEWS)
@@ -41,6 +42,15 @@
   return *in_service_process;
 }
 
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
+NavigableContentsView::RemoteViewFactory& GetRemoteViewFactory() {
+  static base::NoDestructor<NavigableContentsView::RemoteViewFactory> factory;
+  return *factory;
+}
+
+#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
 }  // namespace
 
 NavigableContentsView::~NavigableContentsView() = default;
@@ -60,25 +70,41 @@
   view_ = std::make_unique<views::View>();
   view_->set_owned_by_client();
   view_->SetLayoutManager(std::make_unique<views::FillLayout>());
-#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
-  if (!IsClientRunningInServiceProcess()) {
-    DCHECK(!remote_view_host_);
-    remote_view_host_ = new views::RemoteViewHost;
-    view_->AddChildView(remote_view_host_);
-  }
-#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
 #endif  // defined(TOOLKIT_VIEWS)
 }
 
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
+// static
+void NavigableContentsView::SetRemoteViewFactory(RemoteViewFactory factory) {
+  GetRemoteViewFactory() = std::move(factory);
+}
+
+#endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+
 void NavigableContentsView::EmbedUsingToken(
     const base::UnguessableToken& token) {
 #if defined(TOOLKIT_VIEWS)
 #if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
-  if (remote_view_host_) {
-    const uint32_t kEmbedFlags =
-        ws::mojom::kEmbedFlagEmbedderInterceptsEvents |
-        ws::mojom::kEmbedFlagEmbedderControlsVisibility;
-    remote_view_host_->EmbedUsingToken(token, kEmbedFlags, base::DoNothing());
+  if (!IsClientRunningInServiceProcess()) {
+    const RemoteViewFactory& factory = GetRemoteViewFactory();
+    std::unique_ptr<views::NativeViewHost> remote_view_host;
+    if (factory) {
+      remote_view_host = factory.Run(token);
+    } else {
+      auto host = std::make_unique<views::RemoteViewHost>();
+      constexpr uint32_t kEmbedFlags =
+          ws::mojom::kEmbedFlagEmbedderInterceptsEvents |
+          ws::mojom::kEmbedFlagEmbedderControlsVisibility;
+      host->EmbedUsingToken(token, kEmbedFlags, base::DoNothing());
+      remote_view_host = std::move(host);
+    }
+
+    auto* raw_remote_view_host = remote_view_host.release();
+    view_->AddChildView(raw_remote_view_host);
+    native_view_ = raw_remote_view_host->native_view();
+
+    view_->Layout();
     return;
   }
 #endif  // BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
@@ -94,6 +120,9 @@
     return;
   }
 
+  // Invoke a callback provided by the Content Service's host environment. This
+  // should parent a web content view to our own |view()|, as well as set
+  // |native_view_| to the corresponding web contents' own NativeView.
   auto callback = std::move(it->second);
   embeddings.erase(it);
   std::move(callback).Run(this);
diff --git a/services/content/public/cpp/navigable_contents_view.h b/services/content/public/cpp/navigable_contents_view.h
index fd1d757..1050e6a 100644
--- a/services/content/public/cpp/navigable_contents_view.h
+++ b/services/content/public/cpp/navigable_contents_view.h
@@ -7,13 +7,15 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "base/component_export.h"
 #include "base/unguessable_token.h"
 #include "services/content/public/cpp/buildflags.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace views {
-class RemoteViewHost;
 class View;
+class NativeViewHost;
 }  // namespace views
 
 namespace content {
@@ -29,6 +31,18 @@
 // Views UI.
 class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) NavigableContentsView {
  public:
+#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
+  // May be used if the Content Service client is running within a process whose
+  // UI environment requires a different remote View implementation from
+  // the default one. For example, on Chrome OS when Ash and the Window Service
+  // are running in the same process, the default implementation
+  // (views::RemoteViewHost) will not work.
+  using RemoteViewFactory =
+      base::RepeatingCallback<std::unique_ptr<views::NativeViewHost>(
+          const base::UnguessableToken& embed_token)>;
+  static void SetRemoteViewFactory(RemoteViewFactory factory);
+#endif
+
   ~NavigableContentsView();
 
   // Used to set/query whether the calling process is the same process in which
@@ -43,6 +57,8 @@
   views::View* view() const { return view_.get(); }
 #endif
 
+  gfx::NativeView native_view() const { return native_view_; }
+
  private:
   friend class NavigableContents;
   friend class NavigableContentsImpl;
@@ -53,6 +69,10 @@
   // object and another native UI object within the Content Service.
   void EmbedUsingToken(const base::UnguessableToken& token);
 
+  // Used by NavigableContentsImpl to directly inject a NativeView in the
+  // in-process case.
+  void set_native_view(gfx::NativeView view) { native_view_ = view; }
+
   // Used by the service directly when running in the same process. Establishes
   // a way for an embed token to be used without the UI service.
   static void RegisterInProcessEmbedCallback(
@@ -63,12 +83,14 @@
   // This NavigableContents's View. Only initialized if |GetView()| is called,
   // and only on platforms which support Views UI.
   std::unique_ptr<views::View> view_;
-
-#if BUILDFLAG(ENABLE_REMOTE_NAVIGABLE_CONTENTS_VIEW)
-  views::RemoteViewHost* remote_view_host_ = nullptr;
-#endif
 #endif  // BUILDFLAG(TOOLKIT_VIEWS)
 
+  // Returns the native view object in which this NavigableContentsView is
+  // rendering its web contents. For in-process clients, this is the NativeView
+  // of the WebContents itself; for out-of-process clients, it's the contents'
+  // embedding root within this (the client) process.
+  gfx::NativeView native_view_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(NavigableContentsView);
 };
 
diff --git a/services/service_manager/sandbox/features.cc b/services/service_manager/sandbox/features.cc
index 85e43fa..22b4e13 100644
--- a/services/service_manager/sandbox/features.cc
+++ b/services/service_manager/sandbox/features.cc
@@ -24,6 +24,9 @@
 // sandbox::MITIGATION_EXTENSION_POINT_DISABLE.
 const base::Feature kWinSboxDisableExtensionPoints{
     "WinSboxDisableExtensionPoint", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Controls whether the isolated XR service is sandboxed.
+const base::Feature kXRSandbox{"XRSandbox", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_WIN)
 
 }  // namespace features
diff --git a/services/service_manager/sandbox/features.h b/services/service_manager/sandbox/features.h
index 919806c..d67ffa47 100644
--- a/services/service_manager/sandbox/features.h
+++ b/services/service_manager/sandbox/features.h
@@ -23,6 +23,8 @@
 
 SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature
     kWinSboxDisableExtensionPoints;
+
+SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature kXRSandbox;
 #endif  // defined(OS_WIN)
 
 }  // namespace features
diff --git a/services/service_manager/sandbox/sandbox_type.cc b/services/service_manager/sandbox/sandbox_type.cc
index 1c471e5..f0b90a4 100644
--- a/services/service_manager/sandbox/sandbox_type.cc
+++ b/services/service_manager/sandbox/sandbox_type.cc
@@ -19,6 +19,10 @@
 #if defined(OS_WIN)
     case SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES:
       return true;
+
+    case SANDBOX_TYPE_XRCOMPOSITING:
+      return !base::FeatureList::IsEnabled(
+          service_manager::features::kXRSandbox);
 #endif
     case SANDBOX_TYPE_AUDIO:
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
@@ -34,6 +38,7 @@
 #else
       return true;
 #endif
+
     default:
       return false;
   }
@@ -73,6 +78,9 @@
     case SANDBOX_TYPE_CDM:
     case SANDBOX_TYPE_PDF_COMPOSITOR:
     case SANDBOX_TYPE_PROFILING:
+#if defined(OS_WIN)
+    case SANDBOX_TYPE_XRCOMPOSITING:
+#endif
     case SANDBOX_TYPE_AUDIO:
       DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
              switches::kUtilityProcess);
@@ -138,6 +146,10 @@
       return switches::kProfilingSandbox;
     case SANDBOX_TYPE_UTILITY:
       return switches::kUtilitySandbox;
+#if defined(OS_WIN)
+    case SANDBOX_TYPE_XRCOMPOSITING:
+      return switches::kXrCompositingSandbox;
+#endif
     case SANDBOX_TYPE_AUDIO:
       return switches::kAudioSandbox;
     default:
@@ -166,6 +178,10 @@
     return SANDBOX_TYPE_PDF_COMPOSITOR;
   if (sandbox_string == switches::kProfilingSandbox)
     return SANDBOX_TYPE_PROFILING;
+#if defined(OS_WIN)
+  if (sandbox_string == switches::kXrCompositingSandbox)
+    return SANDBOX_TYPE_XRCOMPOSITING;
+#endif
   if (sandbox_string == switches::kAudioSandbox)
     return SANDBOX_TYPE_AUDIO;
   return SANDBOX_TYPE_UTILITY;
diff --git a/services/service_manager/sandbox/sandbox_type.h b/services/service_manager/sandbox/sandbox_type.h
index 1c5832b..f0c04da8 100644
--- a/services/service_manager/sandbox/sandbox_type.h
+++ b/services/service_manager/sandbox/sandbox_type.h
@@ -26,6 +26,9 @@
 #if defined(OS_WIN)
   // Do not apply any sandboxing and elevate the privileges of the process.
   SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES,
+
+  // The XR Compositing process.
+  SANDBOX_TYPE_XRCOMPOSITING,
 #endif
 
   // Renderer or worker process. Most common case.
diff --git a/services/service_manager/sandbox/switches.cc b/services/service_manager/sandbox/switches.cc
index 7eecefdc..28e9729 100644
--- a/services/service_manager/sandbox/switches.cc
+++ b/services/service_manager/sandbox/switches.cc
@@ -26,6 +26,7 @@
 const char kPpapiSandbox[] = "ppapi";
 const char kUtilitySandbox[] = "utility";
 const char kCdmSandbox[] = "cdm";
+const char kXrCompositingSandbox[] = "xr_compositing";
 const char kPdfCompositorSandbox[] = "pdf_compositor";
 const char kProfilingSandbox[] = "profiling";
 const char kAudioSandbox[] = "audio";
@@ -92,6 +93,10 @@
 
 // Disables the sandbox and gives the process elevated privileges.
 const char kNoSandboxAndElevatedPrivileges[] = "no-sandbox-and-elevated";
+
+// Add additional capabilities to the AppContainer sandbox used for XR
+// compositing.
+const char kAddXrAppContainerCaps[] = "add-xr-appcontainer-caps";
 #endif
 
 #if defined(OS_MACOSX)
diff --git a/services/service_manager/sandbox/switches.h b/services/service_manager/sandbox/switches.h
index c5436d2..a161598 100644
--- a/services/service_manager/sandbox/switches.h
+++ b/services/service_manager/sandbox/switches.h
@@ -25,6 +25,7 @@
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPpapiSandbox[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kUtilitySandbox[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kCdmSandbox[];
+SERVICE_MANAGER_SANDBOX_EXPORT extern const char kXrCompositingSandbox[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPdfCompositorSandbox[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kProfilingSandbox[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAudioSandbox[];
@@ -50,6 +51,7 @@
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kEnableGpuAppContainer[];
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char
     kNoSandboxAndElevatedPrivileges[];
+SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAddXrAppContainerCaps[];
 #endif
 #if defined(OS_MACOSX)
 SERVICE_MANAGER_SANDBOX_EXPORT extern const char kEnableSandboxLogging[];
diff --git a/services/service_manager/sandbox/win/sandbox_win.cc b/services/service_manager/sandbox/win/sandbox_win.cc
index 79ae61d..95cffa1b4 100644
--- a/services/service_manager/sandbox/win/sandbox_win.cc
+++ b/services/service_manager/sandbox/win/sandbox_win.cc
@@ -594,10 +594,19 @@
 base::string16 GetAppContainerProfileName(
     const std::string& appcontainer_id,
     service_manager::SandboxType sandbox_type) {
-  DCHECK(sandbox_type == service_manager::SANDBOX_TYPE_GPU);
+  DCHECK(sandbox_type == service_manager::SANDBOX_TYPE_GPU ||
+         sandbox_type == service_manager::SANDBOX_TYPE_XRCOMPOSITING);
   auto sha1 = base::SHA1HashString(appcontainer_id);
-  auto profile_name = base::StrCat(
-      {"chrome.sandbox.gpu", base::HexEncode(sha1.data(), sha1.size())});
+  std::string sandbox_base_name =
+      (sandbox_type == service_manager::SANDBOX_TYPE_XRCOMPOSITING)
+          ? std::string("chrome.sandbox.xrdevice")
+          : std::string("chrome.sandbox.gpu");
+  std::string profile_name = base::StrCat(
+      {sandbox_base_name, base::HexEncode(sha1.data(), sha1.size())});
+  // CreateAppContainerProfile requires that the profile name is at most 64
+  // characters.  The size of sha1 is a constant 40, so validate that the base
+  // names are sufficiently short that the total length is valid.
+  DCHECK(profile_name.length() <= 64);
   return base::UTF8ToWide(profile_name);
 }
 
@@ -605,23 +614,41 @@
     sandbox::AppContainerProfile* profile,
     const base::CommandLine& command_line,
     service_manager::SandboxType sandbox_type) {
-  if (sandbox_type != service_manager::SANDBOX_TYPE_GPU)
+  if (sandbox_type != service_manager::SANDBOX_TYPE_GPU &&
+      sandbox_type != service_manager::SANDBOX_TYPE_XRCOMPOSITING)
     return sandbox::SBOX_ERROR_UNSUPPORTED;
 
-  if (!profile->AddImpersonationCapability(L"chromeInstallFiles")) {
+  if (sandbox_type == service_manager::SANDBOX_TYPE_GPU &&
+      !profile->AddImpersonationCapability(L"chromeInstallFiles")) {
     DLOG(ERROR) << "AppContainerProfile::AddImpersonationCapability() failed";
     return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
   }
 
+  if (sandbox_type == service_manager::SANDBOX_TYPE_XRCOMPOSITING &&
+      !profile->AddCapability(L"chromeInstallFiles")) {
+    DLOG(ERROR) << "AppContainerProfile::AddCapability() failed";
+    return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
+  }
+
   std::vector<base::string16> base_caps = {
       L"lpacChromeInstallFiles", L"registryRead",
   };
 
-  auto cmdline_caps =
-      base::SplitString(command_line.GetSwitchValueNative(
-                            service_manager::switches::kAddGpuAppContainerCaps),
-                        L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  base_caps.insert(base_caps.end(), cmdline_caps.begin(), cmdline_caps.end());
+  if (sandbox_type == service_manager::SANDBOX_TYPE_GPU) {
+    auto cmdline_caps = base::SplitString(
+        command_line.GetSwitchValueNative(
+            service_manager::switches::kAddGpuAppContainerCaps),
+        L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    base_caps.insert(base_caps.end(), cmdline_caps.begin(), cmdline_caps.end());
+  }
+
+  if (sandbox_type == service_manager::SANDBOX_TYPE_XRCOMPOSITING) {
+    auto cmdline_caps = base::SplitString(
+        command_line.GetSwitchValueNative(
+            service_manager::switches::kAddXrAppContainerCaps),
+        L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    base_caps.insert(base_caps.end(), cmdline_caps.begin(), cmdline_caps.end());
+  }
 
   for (const auto& cap : base_caps) {
     if (!profile->AddCapability(cap.c_str())) {
@@ -630,7 +657,9 @@
     }
   }
 
-  if (!command_line.HasSwitch(service_manager::switches::kDisableGpuLpac)) {
+  // Enable LPAC for GPU process, but not for XRCompositor service.
+  if (sandbox_type == service_manager::SANDBOX_TYPE_GPU &&
+      !command_line.HasSwitch(service_manager::switches::kDisableGpuLpac)) {
     profile->SetEnableLowPrivilegeAppContainer(true);
   }
 
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 250a595..cfbf1aa8 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -499,7 +499,7 @@
       "ext/fontmgr_fuchsia.h",
     ]
     deps += [
-      "//third_party/fuchsia-sdk:fonts",
+      "//third_party/fuchsia-sdk/sdk:fonts",
       "//third_party/icu:icuuc",
     ]
   }
@@ -823,7 +823,7 @@
   if (is_fuchsia) {
     sources += [ "ext/fontmgr_fuchsia_unittest.cc" ]
     deps += [
-      "//third_party/fuchsia-sdk:fonts",
+      "//third_party/fuchsia-sdk/sdk:fonts",
       "//third_party/test_fonts",
     ]
     data_deps = [
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 0dc358d..3199ff3 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -155,11 +155,6 @@
 #define SK_SUPPORT_LEGACY_TILED_BITMAPS
 #endif
 
-// remove after rebaselining svg layout tests
-#ifndef SK_SUPPORT_LEGACY_SVG_ARC_TO
-#define SK_SUPPORT_LEGACY_SVG_ARC_TO
-#endif
-
 // Max. verb count for paths rendered by the edge-AA tessellating path renderer.
 #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 100
 
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate.cc b/storage/browser/fileapi/copy_or_move_operation_delegate.cc
index 4b1adfd..fbcb102e 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate.cc
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -32,8 +32,7 @@
 class CopyOrMoveOperationDelegate::CopyOrMoveImpl {
  public:
   virtual ~CopyOrMoveImpl() = default;
-  virtual void Run(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0;
+  virtual void Run(CopyOrMoveOperationDelegate::StatusCallback callback) = 0;
   virtual void Cancel() = 0;
 
  protected:
@@ -63,16 +62,16 @@
         src_url_(src_url),
         dest_url_(dest_url),
         option_(option),
-        file_progress_callback_(file_progress_callback) {
-  }
+        file_progress_callback_(file_progress_callback) {}
 
-  void Run(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) override {
+  void Run(CopyOrMoveOperationDelegate::StatusCallback callback) override {
     if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) {
-      operation_runner_->MoveFileLocal(src_url_, dest_url_, option_, callback);
+      operation_runner_->MoveFileLocal(src_url_, dest_url_, option_,
+                                       std::move(callback));
     } else {
-      operation_runner_->CopyFileLocal(
-          src_url_, dest_url_, option_, file_progress_callback_, callback);
+      operation_runner_->CopyFileLocal(src_url_, dest_url_, option_,
+                                       file_progress_callback_,
+                                       std::move(callback));
     }
   }
 
@@ -116,23 +115,21 @@
         validator_factory_(validator_factory),
         file_progress_callback_(file_progress_callback),
         cancel_requested_(false),
-        weak_factory_(this) {
-  }
+        weak_factory_(this) {}
 
-  void Run(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) override {
+  void Run(CopyOrMoveOperationDelegate::StatusCallback callback) override {
     file_progress_callback_.Run(0);
     operation_runner_->CreateSnapshotFile(
         src_url_,
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void Cancel() override { cancel_requested_ = true; }
 
  private:
   void RunAfterCreateSnapshot(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error,
       const base::File::Info& file_info,
       const base::FilePath& platform_path,
@@ -141,7 +138,7 @@
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
@@ -152,29 +149,29 @@
     if (!validator_factory_) {
       // No validation is needed.
       RunAfterPreWriteValidation(platform_path, file_info, std::move(file_ref),
-                                 callback, base::File::FILE_OK);
+                                 std::move(callback), base::File::FILE_OK);
       return;
     }
 
     // Run pre write validation.
     PreWriteValidation(
         platform_path,
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation,
-                   weak_factory_.GetWeakPtr(), platform_path, file_info,
-                   std::move(file_ref), callback));
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation,
+                       weak_factory_.GetWeakPtr(), platform_path, file_info,
+                       std::move(file_ref), std::move(callback)));
   }
 
   void RunAfterPreWriteValidation(
       const base::FilePath& platform_path,
       const base::File::Info& file_info,
       scoped_refptr<storage::ShareableFileReference> file_ref,
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
@@ -182,45 +179,43 @@
     // CopyInForeignFile() is completed.
     operation_runner_->CopyInForeignFile(
         platform_path, dest_url_,
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile,
-                   weak_factory_.GetWeakPtr(), file_info, std::move(file_ref),
-                   callback));
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile,
+                       weak_factory_.GetWeakPtr(), file_info,
+                       std::move(file_ref), std::move(callback)));
   }
 
   void RunAfterCopyInForeignFile(
       const base::File::Info& file_info,
       scoped_refptr<storage::ShareableFileReference> file_ref,
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
     file_progress_callback_.Run(file_info.size);
 
     if (option_ == FileSystemOperation::OPTION_NONE) {
-      RunAfterTouchFile(callback, base::File::FILE_OK);
+      RunAfterTouchFile(std::move(callback), base::File::FILE_OK);
       return;
     }
 
     operation_runner_->TouchFile(
-        dest_url_, base::Time::Now() /* last_access */,
-        file_info.last_modified,
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterTouchFile,
-                   weak_factory_.GetWeakPtr(), callback));
+        dest_url_, base::Time::Now() /* last_access */, file_info.last_modified,
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterTouchFile,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void RunAfterTouchFile(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
-      base::File::Error error) {
+  void RunAfterTouchFile(CopyOrMoveOperationDelegate::StatusCallback callback,
+                         base::File::Error error) {
     // Even if TouchFile is failed, just ignore it.
 
     if (cancel_requested_) {
-      callback.Run(base::File::FILE_ERROR_ABORT);
+      std::move(callback).Run(base::File::FILE_ERROR_ABORT);
       return;
     }
 
@@ -228,20 +223,20 @@
     // validation.
     if (!validator_) {
       // No validation is needed.
-      RunAfterPostWriteValidation(callback, base::File::FILE_OK);
+      RunAfterPostWriteValidation(std::move(callback), base::File::FILE_OK);
       return;
     }
 
     PostWriteValidation(
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RunAfterPostWriteValidation(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (cancel_requested_) {
-      callback.Run(base::File::FILE_ERROR_ABORT);
+      std::move(callback).Run(base::File::FILE_ERROR_ABORT);
       return;
     }
 
@@ -249,13 +244,14 @@
       // Failed to validate. Remove the destination file.
       operation_runner_->Remove(
           dest_url_, true /* recursive */,
-          base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError,
-                     weak_factory_.GetWeakPtr(), error, callback));
+          base::BindOnce(&SnapshotCopyOrMoveImpl::DidRemoveDestForError,
+                         weak_factory_.GetWeakPtr(), error,
+                         std::move(callback)));
       return;
     }
 
     if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
-      callback.Run(base::File::FILE_OK);
+      std::move(callback).Run(base::File::FILE_OK);
       return;
     }
 
@@ -264,55 +260,56 @@
     // Remove the source for finalizing move operation.
     operation_runner_->Remove(
         src_url_, true /* recursive */,
-        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RunAfterRemoveSourceForMove(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
 
     if (error == base::File::FILE_ERROR_NOT_FOUND)
       error = base::File::FILE_OK;
-    callback.Run(error);
+    std::move(callback).Run(error);
   }
 
   void DidRemoveDestForError(
       base::File::Error prior_error,
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (error != base::File::FILE_OK) {
       VLOG(1) << "Error removing destination file after validation error: "
               << error;
     }
-    callback.Run(prior_error);
+    std::move(callback).Run(prior_error);
   }
 
   // Runs pre-write validation.
   void PreWriteValidation(
       const base::FilePath& platform_path,
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) {
+      CopyOrMoveOperationDelegate::StatusCallback callback) {
     DCHECK(validator_factory_);
-    validator_.reset(
-        validator_factory_->CreateCopyOrMoveFileValidator(
-            src_url_, platform_path));
-    validator_->StartPreWriteValidation(callback);
+    validator_.reset(validator_factory_->CreateCopyOrMoveFileValidator(
+        src_url_, platform_path));
+    // TODO(mek): Update CopyOrMoveFileValidator to use OnceCallback.
+    validator_->StartPreWriteValidation(
+        base::AdaptCallbackForRepeating(std::move(callback)));
   }
 
   // Runs post-write validation.
   void PostWriteValidation(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) {
+      CopyOrMoveOperationDelegate::StatusCallback callback) {
     operation_runner_->CreateSnapshotFile(
         dest_url_,
-        base::Bind(
+        base::BindOnce(
             &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile,
-            weak_factory_.GetWeakPtr(), callback));
+            weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void PostWriteValidationAfterCreateSnapshotFile(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error,
       const base::File::Info& file_info,
       const base::FilePath& platform_path,
@@ -321,26 +318,28 @@
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
     DCHECK(validator_);
     // Note: file_ref passed here to keep the file alive until after
     // the StartPostWriteValidation operation finishes.
+    // TODO(mek): Update CopyOrMoveFileValidator to use OnceCallback.
     validator_->StartPostWriteValidation(
-        platform_path,
-        base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation,
-                   weak_factory_.GetWeakPtr(), std::move(file_ref), callback));
+        platform_path, base::AdaptCallbackForRepeating(base::BindOnce(
+                           &SnapshotCopyOrMoveImpl::DidPostWriteValidation,
+                           weak_factory_.GetWeakPtr(), std::move(file_ref),
+                           std::move(callback))));
   }
 
   // |file_ref| is unused; it is passed here to make sure the reference is
   // alive until after post-write validation is complete.
   void DidPostWriteValidation(
       scoped_refptr<storage::ShareableFileReference> file_ref,
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
-    callback.Run(error);
+    std::move(callback).Run(error);
   }
 
   FileSystemOperationRunner* operation_runner_;
@@ -393,16 +392,16 @@
         cancel_requested_(false),
         weak_factory_(this) {}
 
-  void Run(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback) override {
+  void Run(CopyOrMoveOperationDelegate::StatusCallback callback) override {
     // Reader can be created even if the entry does not exist or the entry is
     // a directory. To check errors before destination file creation,
     // check metadata first.
     operation_runner_->GetMetadata(
-        src_url_, FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
-                      FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
-        base::Bind(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource,
-                   weak_factory_.GetWeakPtr(), callback));
+        src_url_,
+        FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY |
+            FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
+        base::BindOnce(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void Cancel() override {
@@ -434,35 +433,33 @@
   }
 
   void RunAfterGetMetadataForSource(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error,
       const base::File::Info& file_info) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
     if (file_info.is_directory) {
       // If not a directory, failed with appropriate error code.
-      callback.Run(base::File::FILE_ERROR_NOT_A_FILE);
+      std::move(callback).Run(base::File::FILE_ERROR_NOT_A_FILE);
       return;
     }
 
     // To use FileStreamWriter, we need to ensure the destination file exists.
     operation_runner_->CreateFile(
-        dest_url_,
-        true /* exclusive */,
-        base::Bind(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination,
-                   weak_factory_.GetWeakPtr(),
-                   callback,
-                   file_info.last_modified));
+        dest_url_, true /* exclusive */,
+        base::BindOnce(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination,
+                       weak_factory_.GetWeakPtr(), std::move(callback),
+                       file_info.last_modified));
   }
 
   void RunAfterCreateFileForDestination(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       const base::Time& last_modified,
       base::File::Error error) {
     if (cancel_requested_)
@@ -474,33 +471,31 @@
 
     if (error != base::File::FILE_OK &&
         error != base::File::FILE_ERROR_EXISTS) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
     if (error == base::File::FILE_ERROR_EXISTS) {
       operation_runner_->Truncate(
-          dest_url_,
-          0 /* length */,
-          base::Bind(&StreamCopyOrMoveImpl::RunAfterTruncateForDestination,
-                     weak_factory_.GetWeakPtr(),
-                     callback,
-                     last_modified));
+          dest_url_, 0 /* length */,
+          base::BindOnce(&StreamCopyOrMoveImpl::RunAfterTruncateForDestination,
+                         weak_factory_.GetWeakPtr(), std::move(callback),
+                         last_modified));
       return;
     }
-    RunAfterTruncateForDestination(
-        callback, last_modified, base::File::FILE_OK);
+    RunAfterTruncateForDestination(std::move(callback), last_modified,
+                                   base::File::FILE_OK);
   }
 
   void RunAfterTruncateForDestination(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       const base::Time& last_modified,
       base::File::Error error) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
@@ -512,15 +507,14 @@
         file_progress_callback_,
         base::TimeDelta::FromMilliseconds(
             kMinProgressCallbackInvocationSpanInMilliseconds)));
-    copy_helper_->Run(
-        base::Bind(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
-                   weak_factory_.GetWeakPtr(), callback, last_modified));
+    copy_helper_->Run(base::BindOnce(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
+                                     weak_factory_.GetWeakPtr(),
+                                     std::move(callback), last_modified));
   }
 
-  void RunAfterStreamCopy(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
-      const base::Time& last_modified,
-      base::File::Error error) {
+  void RunAfterStreamCopy(CopyOrMoveOperationDelegate::StatusCallback callback,
+                          const base::Time& last_modified,
+                          base::File::Error error) {
     // Destruct StreamCopyHelper to close the destination file.
     // This is important because some file system implementations update
     // timestamps on file close and thus it should happen before we call
@@ -533,32 +527,31 @@
       error = base::File::FILE_ERROR_ABORT;
 
     if (error != base::File::FILE_OK) {
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
     if (option_ == FileSystemOperation::OPTION_NONE) {
-      RunAfterTouchFile(callback, base::File::FILE_OK);
+      RunAfterTouchFile(std::move(callback), base::File::FILE_OK);
       return;
     }
 
     operation_runner_->TouchFile(
         dest_url_, base::Time::Now() /* last_access */, last_modified,
-        base::Bind(&StreamCopyOrMoveImpl::RunAfterTouchFile,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&StreamCopyOrMoveImpl::RunAfterTouchFile,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void RunAfterTouchFile(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
-      base::File::Error error) {
+  void RunAfterTouchFile(CopyOrMoveOperationDelegate::StatusCallback callback,
+                         base::File::Error error) {
     // Even if TouchFile is failed, just ignore it.
     if (cancel_requested_) {
-      callback.Run(base::File::FILE_ERROR_ABORT);
+      std::move(callback).Run(base::File::FILE_ERROR_ABORT);
       return;
     }
 
     if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
-      callback.Run(base::File::FILE_OK);
+      std::move(callback).Run(base::File::FILE_OK);
       return;
     }
 
@@ -567,18 +560,18 @@
     // Remove the source for finalizing move operation.
     operation_runner_->Remove(
         src_url_, false /* recursive */,
-        base::Bind(&StreamCopyOrMoveImpl::RunAfterRemoveForMove,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&StreamCopyOrMoveImpl::RunAfterRemoveForMove,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RunAfterRemoveForMove(
-      const CopyOrMoveOperationDelegate::StatusCallback& callback,
+      CopyOrMoveOperationDelegate::StatusCallback callback,
       base::File::Error error) {
     if (cancel_requested_)
       error = base::File::FILE_ERROR_ABORT;
     if (error == base::File::FILE_ERROR_NOT_FOUND)
       error = base::File::FILE_OK;
-    callback.Run(error);
+    std::move(callback).Run(error);
   }
 
   FileSystemOperationRunner* operation_runner_;
@@ -620,10 +613,10 @@
 CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() = default;
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::Run(
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   file_progress_callback_.Run(0);
   last_progress_callback_invocation_time_ = base::Time::Now();
-  Read(callback);
+  Read(std::move(callback));
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() {
@@ -631,64 +624,69 @@
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::Read(
-    const StatusCallback& callback) {
+    StatusCallback callback) {
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   int result = reader_->Read(
       io_buffer_.get(), io_buffer_->size(),
-      base::Bind(&StreamCopyHelper::DidRead,
-                 weak_factory_.GetWeakPtr(), callback));
+      base::BindOnce(&StreamCopyHelper::DidRead, weak_factory_.GetWeakPtr(),
+                     repeatable_callback));
   if (result != net::ERR_IO_PENDING)
-    DidRead(callback, result);
+    DidRead(repeatable_callback, result);
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead(
-    const StatusCallback& callback, int result) {
+    StatusCallback callback,
+    int result) {
   if (cancel_requested_) {
-    callback.Run(base::File::FILE_ERROR_ABORT);
+    std::move(callback).Run(base::File::FILE_ERROR_ABORT);
     return;
   }
 
   if (result < 0) {
-    callback.Run(NetErrorToFileError(result));
+    std::move(callback).Run(NetErrorToFileError(result));
     return;
   }
 
   if (result == 0) {
     // Here is the EOF.
     if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION)
-      Flush(callback, true /* is_eof */);
+      Flush(std::move(callback), true /* is_eof */);
     else
-      callback.Run(base::File::FILE_OK);
+      std::move(callback).Run(base::File::FILE_OK);
     return;
   }
 
-  Write(callback,
+  Write(std::move(callback),
         base::MakeRefCounted<net::DrainableIOBuffer>(io_buffer_, result));
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::Write(
-    const StatusCallback& callback,
+    StatusCallback callback,
     scoped_refptr<net::DrainableIOBuffer> buffer) {
   DCHECK_GT(buffer->BytesRemaining(), 0);
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   int result = writer_->Write(
       buffer.get(), buffer->BytesRemaining(),
-      base::Bind(&StreamCopyHelper::DidWrite,
-                 weak_factory_.GetWeakPtr(), callback, buffer));
+      base::BindOnce(&StreamCopyHelper::DidWrite, weak_factory_.GetWeakPtr(),
+                     repeatable_callback, buffer));
   if (result != net::ERR_IO_PENDING)
-    DidWrite(callback, buffer, result);
+    DidWrite(repeatable_callback, buffer, result);
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
-    const StatusCallback& callback,
+    StatusCallback callback,
     scoped_refptr<net::DrainableIOBuffer> buffer,
     int result) {
   if (cancel_requested_) {
-    callback.Run(base::File::FILE_ERROR_ABORT);
+    std::move(callback).Run(base::File::FILE_ERROR_ABORT);
     return;
   }
 
   if (result < 0) {
-    callback.Run(NetErrorToFileError(result));
+    std::move(callback).Run(NetErrorToFileError(result));
     return;
   }
 
@@ -704,39 +702,44 @@
   }
 
   if (buffer->BytesRemaining() > 0) {
-    Write(callback, buffer);
+    Write(std::move(callback), buffer);
     return;
   }
 
   if (flush_policy_ == storage::FlushPolicy::FLUSH_ON_COMPLETION &&
       (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) {
-    Flush(callback, false /* not is_eof */);
+    Flush(std::move(callback), false /* not is_eof */);
   } else {
-    Read(callback);
+    Read(std::move(callback));
   }
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush(
-    const StatusCallback& callback, bool is_eof) {
-  int result = writer_->Flush(
-      base::Bind(&StreamCopyHelper::DidFlush,
-                 weak_factory_.GetWeakPtr(), callback, is_eof));
+    StatusCallback callback,
+    bool is_eof) {
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
+  int result = writer_->Flush(base::BindOnce(&StreamCopyHelper::DidFlush,
+                                             weak_factory_.GetWeakPtr(),
+                                             repeatable_callback, is_eof));
   if (result != net::ERR_IO_PENDING)
-    DidFlush(callback, is_eof, result);
+    DidFlush(repeatable_callback, is_eof, result);
 }
 
 void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush(
-    const StatusCallback& callback, bool is_eof, int result) {
+    StatusCallback callback,
+    bool is_eof,
+    int result) {
   if (cancel_requested_) {
-    callback.Run(base::File::FILE_ERROR_ABORT);
+    std::move(callback).Run(base::File::FILE_ERROR_ABORT);
     return;
   }
 
   previous_flush_offset_ = num_copied_bytes_;
   if (is_eof)
-    callback.Run(NetErrorToFileError(result));
+    std::move(callback).Run(NetErrorToFileError(result));
   else
-    Read(callback);
+    Read(std::move(callback));
 }
 
 CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate(
@@ -747,7 +750,7 @@
     CopyOrMoveOption option,
     ErrorBehavior error_behavior,
     const CopyProgressCallback& progress_callback,
-    const StatusCallback& callback)
+    StatusCallback callback)
     : RecursiveOperationDelegate(file_system_context),
       src_root_(src_root),
       dest_root_(dest_root),
@@ -755,7 +758,7 @@
       option_(option),
       error_behavior_(error_behavior),
       progress_callback_(progress_callback),
-      callback_(callback),
+      callback_(std::move(callback)),
       weak_factory_(this) {
   same_file_system_ = src_root_.IsInSameFileSystem(dest_root_);
 }
@@ -768,11 +771,15 @@
 }
 
 void CopyOrMoveOperationDelegate::RunRecursively() {
+#if DCHECK_IS_ON()
+  DCHECK(!did_run_);
+  did_run_ = true;
+#endif
   // Perform light-weight checks first.
 
   // It is an error to try to copy/move an entry into its child.
   if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) {
-    callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback_).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
@@ -780,7 +787,7 @@
     // In JS API this should return error, but we return success because Pepper
     // wants to return success and we have a code path that returns error in
     // Blink for JS (http://crbug.com/329517).
-    callback_.Run(base::File::FILE_OK);
+    std::move(callback_).Run(base::File::FILE_OK);
     return;
   }
 
@@ -788,15 +795,14 @@
   // TODO(kinuko): This could be too expensive for same_file_system_==true
   // and operation==MOVE case, probably we can just rename the root directory.
   // http://crbug.com/172187
-  StartRecursiveOperation(src_root_, error_behavior_, callback_);
+  StartRecursiveOperation(src_root_, error_behavior_, std::move(callback_));
 }
 
-void CopyOrMoveOperationDelegate::ProcessFile(
-    const FileSystemURL& src_url,
-    const StatusCallback& callback) {
+void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url,
+                                              StatusCallback callback) {
   if (!progress_callback_.is_null()) {
-    progress_callback_.Run(
-        FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
+    progress_callback_.Run(FileSystemOperation::BEGIN_COPY_ENTRY, src_url,
+                           FileSystemURL(), 0);
   }
 
   FileSystemURL dest_url = CreateDestURL(src_url);
@@ -821,7 +827,7 @@
         progress_callback_.Run(FileSystemOperation::ERROR_COPY_ENTRY, src_url,
                                dest_url, 0);
 
-      callback.Run(error);
+      std::move(callback).Run(error);
       return;
     }
 
@@ -853,14 +859,13 @@
 
   CopyOrMoveImpl* impl_ptr = impl.get();
   running_copy_set_[impl_ptr] = std::move(impl);
-  impl_ptr->Run(base::Bind(&CopyOrMoveOperationDelegate::DidCopyOrMoveFile,
-                           weak_factory_.GetWeakPtr(), src_url, dest_url,
-                           callback, impl_ptr));
+  impl_ptr->Run(base::BindOnce(&CopyOrMoveOperationDelegate::DidCopyOrMoveFile,
+                               weak_factory_.GetWeakPtr(), src_url, dest_url,
+                               std::move(callback), impl_ptr));
 }
 
-void CopyOrMoveOperationDelegate::ProcessDirectory(
-    const FileSystemURL& src_url,
-    const StatusCallback& callback) {
+void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url,
+                                                   StatusCallback callback) {
   if (src_url == src_root_) {
     // The src_root_ looks to be a directory.
     // Try removing the dest_root_ to see if it exists and/or it is an
@@ -869,33 +874,34 @@
     // already called in ProcessFile().
     operation_runner()->RemoveDirectory(
         dest_root_,
-        base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
     return;
   }
 
   if (!progress_callback_.is_null()) {
-    progress_callback_.Run(
-        FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
+    progress_callback_.Run(FileSystemOperation::BEGIN_COPY_ENTRY, src_url,
+                           FileSystemURL(), 0);
   }
 
-  ProcessDirectoryInternal(src_url, CreateDestURL(src_url), callback);
+  ProcessDirectoryInternal(src_url, CreateDestURL(src_url),
+                           std::move(callback));
 }
 
 void CopyOrMoveOperationDelegate::PostProcessDirectory(
     const FileSystemURL& src_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   if (option_ == FileSystemOperation::OPTION_NONE) {
-    PostProcessDirectoryAfterTouchFile(
-        src_url, callback, base::File::FILE_OK);
+    PostProcessDirectoryAfterTouchFile(src_url, std::move(callback),
+                                       base::File::FILE_OK);
     return;
   }
 
   operation_runner()->GetMetadata(
       src_url, FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED,
-      base::Bind(
+      base::BindOnce(
           &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata,
-          weak_factory_.GetWeakPtr(), src_url, callback));
+          weak_factory_.GetWeakPtr(), src_url, std::move(callback)));
 }
 
 void CopyOrMoveOperationDelegate::OnCancel() {
@@ -907,7 +913,7 @@
 void CopyOrMoveOperationDelegate::DidCopyOrMoveFile(
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback,
+    StatusCallback callback,
     CopyOrMoveImpl* impl,
     base::File::Error error) {
   running_copy_set_.erase(impl);
@@ -918,84 +924,85 @@
                            dest_url, 0);
 
   if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
-    progress_callback_.Run(
-        FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
+    progress_callback_.Run(FileSystemOperation::END_COPY_ENTRY, src_url,
+                           dest_url, 0);
   }
 
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot(
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error) {
   if (error == base::File::FILE_ERROR_NOT_A_DIRECTORY) {
-    callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
   if (error != base::File::FILE_OK &&
       error != base::File::FILE_ERROR_NOT_FOUND) {
-    callback_.Run(error);
+    std::move(callback).Run(error);
     return;
   }
 
-  ProcessDirectoryInternal(src_root_, dest_root_, callback);
+  ProcessDirectoryInternal(src_root_, dest_root_, std::move(callback));
 }
 
 void CopyOrMoveOperationDelegate::ProcessDirectoryInternal(
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   // If operation_type == Move we may need to record directories and
   // restore directory timestamps in the end, though it may have
   // negative performance impact.
   // See http://crbug.com/171284 for more details.
   operation_runner()->CreateDirectory(
       dest_url, false /* exclusive */, false /* recursive */,
-      base::Bind(&CopyOrMoveOperationDelegate::DidCreateDirectory,
-                 weak_factory_.GetWeakPtr(), src_url, dest_url, callback));
+      base::BindOnce(&CopyOrMoveOperationDelegate::DidCreateDirectory,
+                     weak_factory_.GetWeakPtr(), src_url, dest_url,
+                     std::move(callback)));
 }
 
 void CopyOrMoveOperationDelegate::DidCreateDirectory(
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error) {
   if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
-    progress_callback_.Run(
-        FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
+    progress_callback_.Run(FileSystemOperation::END_COPY_ENTRY, src_url,
+                           dest_url, 0);
   }
 
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata(
     const FileSystemURL& src_url,
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error,
     const base::File::Info& file_info) {
   if (error != base::File::FILE_OK) {
     // Ignore the error, and run post process which should run after TouchFile.
-    PostProcessDirectoryAfterTouchFile(
-        src_url, callback, base::File::FILE_OK);
+    PostProcessDirectoryAfterTouchFile(src_url, std::move(callback),
+                                       base::File::FILE_OK);
     return;
   }
 
   operation_runner()->TouchFile(
       CreateDestURL(src_url), base::Time::Now() /* last access */,
       file_info.last_modified,
-      base::Bind(
+      base::BindOnce(
           &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile,
-          weak_factory_.GetWeakPtr(), src_url, callback));
+          weak_factory_.GetWeakPtr(), src_url, std::move(callback)));
 }
 
 void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile(
     const FileSystemURL& src_url,
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error) {
   // Even if the TouchFile is failed, just ignore it.
 
   if (operation_type_ == OPERATION_COPY) {
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
     return;
   }
 
@@ -1005,24 +1012,24 @@
   // so remove the source directory for finalizing move operation.
   operation_runner()->Remove(
       src_url, false /* recursive */,
-      base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
-                 weak_factory_.GetWeakPtr(), callback));
+      base::BindOnce(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error error) {
   if (error == base::File::FILE_ERROR_NOT_FOUND)
     error = base::File::FILE_OK;
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 void CopyOrMoveOperationDelegate::OnCopyFileProgress(
     const FileSystemURL& src_url,
     int64_t size) {
   if (!progress_callback_.is_null()) {
-    progress_callback_.Run(
-        FileSystemOperation::PROGRESS, src_url, FileSystemURL(), size);
+    progress_callback_.Run(FileSystemOperation::PROGRESS, src_url,
+                           FileSystemURL(), size);
   }
 }
 
@@ -1035,9 +1042,7 @@
   src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(),
                                               &relative);
   return file_system_context()->CreateCrackedFileSystemURL(
-      dest_root_.origin(),
-      dest_root_.mount_type(),
-      relative);
+      dest_root_.origin(), dest_root_.mount_type(), relative);
 }
 
 }  // namespace storage
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate.h b/storage/browser/fileapi/copy_or_move_operation_delegate.h
index fc877a8..529ce4b 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate.h
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate.h
@@ -57,7 +57,7 @@
         const base::TimeDelta& min_progress_callback_invocation_span);
     ~StreamCopyHelper();
 
-    void Run(const StatusCallback& callback);
+    void Run(StatusCallback callback);
 
     // Requests cancelling. After the cancelling is done, |callback| passed to
     // Run will be called.
@@ -65,18 +65,19 @@
 
    private:
     // Reads the content from the |reader_|.
-    void Read(const StatusCallback& callback);
-    void DidRead(const StatusCallback& callback, int result);
+    void Read(StatusCallback callback);
+    void DidRead(StatusCallback callback, int result);
 
     // Writes the content in |buffer| to |writer_|.
-    void Write(const StatusCallback& callback,
+    void Write(StatusCallback callback,
                scoped_refptr<net::DrainableIOBuffer> buffer);
-    void DidWrite(const StatusCallback& callback,
-                  scoped_refptr<net::DrainableIOBuffer> buffer, int result);
+    void DidWrite(StatusCallback callback,
+                  scoped_refptr<net::DrainableIOBuffer> buffer,
+                  int result);
 
     // Flushes the written content in |writer_|.
-    void Flush(const StatusCallback& callback, bool is_eof);
-    void DidFlush(const StatusCallback& callback, bool is_eof, int result);
+    void Flush(StatusCallback callback, bool is_eof);
+    void DidFlush(StatusCallback callback, bool is_eof, int result);
 
     std::unique_ptr<storage::FileStreamReader> reader_;
     std::unique_ptr<FileStreamWriter> writer_;
@@ -99,18 +100,17 @@
                               CopyOrMoveOption option,
                               ErrorBehavior error_behavior,
                               const CopyProgressCallback& progress_callback,
-                              const StatusCallback& callback);
+                              StatusCallback callback);
   ~CopyOrMoveOperationDelegate() override;
 
   // RecursiveOperationDelegate overrides:
   void Run() override;
   void RunRecursively() override;
-  void ProcessFile(const FileSystemURL& url,
-                   const StatusCallback& callback) override;
+  void ProcessFile(const FileSystemURL& url, StatusCallback callback) override;
   void ProcessDirectory(const FileSystemURL& url,
-                        const StatusCallback& callback) override;
+                        StatusCallback callback) override;
   void PostProcessDirectory(const FileSystemURL& url,
-                            const StatusCallback& callback) override;
+                            StatusCallback callback) override;
 
  protected:
   void OnCancel() override;
@@ -118,32 +118,33 @@
  private:
   void DidCopyOrMoveFile(const FileSystemURL& src_url,
                          const FileSystemURL& dest_url,
-                         const StatusCallback& callback,
+                         StatusCallback callback,
                          CopyOrMoveImpl* impl,
                          base::File::Error error);
-  void DidTryRemoveDestRoot(const StatusCallback& callback,
-                            base::File::Error error);
+  void DidTryRemoveDestRoot(StatusCallback callback, base::File::Error error);
   void ProcessDirectoryInternal(const FileSystemURL& src_url,
                                 const FileSystemURL& dest_url,
-                                const StatusCallback& callback);
+                                StatusCallback callback);
   void DidCreateDirectory(const FileSystemURL& src_url,
                           const FileSystemURL& dest_url,
-                          const StatusCallback& callback,
+                          StatusCallback callback,
                           base::File::Error error);
-  void PostProcessDirectoryAfterGetMetadata(
-      const FileSystemURL& src_url,
-      const StatusCallback& callback,
-      base::File::Error error,
-      const base::File::Info& file_info);
+  void PostProcessDirectoryAfterGetMetadata(const FileSystemURL& src_url,
+                                            StatusCallback callback,
+                                            base::File::Error error,
+                                            const base::File::Info& file_info);
   void PostProcessDirectoryAfterTouchFile(const FileSystemURL& src_url,
-                                          const StatusCallback& callback,
+                                          StatusCallback callback,
                                           base::File::Error error);
-  void DidRemoveSourceForMove(const StatusCallback& callback,
-                              base::File::Error error);
+  void DidRemoveSourceForMove(StatusCallback callback, base::File::Error error);
 
   void OnCopyFileProgress(const FileSystemURL& src_url, int64_t size);
   FileSystemURL CreateDestURL(const FileSystemURL& src_url) const;
 
+#if DCHECK_IS_ON()
+  bool did_run_ = false;
+#endif
+
   FileSystemURL src_root_;
   FileSystemURL dest_root_;
   bool same_file_system_;
diff --git a/storage/browser/fileapi/file_system_operation.h b/storage/browser/fileapi/file_system_operation.h
index dc8288d..a966684 100644
--- a/storage/browser/fileapi/file_system_operation.h
+++ b/storage/browser/fileapi/file_system_operation.h
@@ -64,20 +64,20 @@
   virtual ~FileSystemOperation() {}
 
   // Used for CreateFile(), etc. |result| is the return code of the operation.
-  using StatusCallback = base::Callback<void(base::File::Error result)>;
+  using StatusCallback = base::OnceCallback<void(base::File::Error result)>;
 
   // Used for GetMetadata(). |result| is the return code of the operation,
   // |file_info| is the obtained file info.
   using GetMetadataCallback =
-      base::Callback<void(base::File::Error result,
-                          const base::File::Info& file_info)>;
+      base::OnceCallback<void(base::File::Error result,
+                              const base::File::Info& file_info)>;
 
   // Used for OpenFile(). |on_close_callback| will be called after the file is
   // closed in the child process. It can be null, if no operation is needed on
   // closing a file.
   using OpenFileCallback =
-      base::Callback<void(base::File file,
-                          base::OnceClosure on_close_callback)>;
+      base::OnceCallback<void(base::File file,
+                              base::OnceClosure on_close_callback)>;
 
   // Used for ReadDirectoryCallback.
   using FileEntryList = std::vector<filesystem::mojom::DirectoryEntry>;
@@ -198,17 +198,17 @@
     ERROR_COPY_ENTRY
   };
   using CopyProgressCallback =
-      base::Callback<void(CopyProgressType type,
-                          const FileSystemURL& source_url,
-                          const FileSystemURL& destination_url,
-                          int64_t size)>;
+      base::RepeatingCallback<void(CopyProgressType type,
+                                   const FileSystemURL& source_url,
+                                   const FileSystemURL& destination_url,
+                                   int64_t size)>;
 
   // Used for CopyFileLocal() to report progress update.
   // |size| is the cumulative copied bytes for the copy.
   // At the beginning the progress callback should be called with |size| = 0,
   // and also at the ending the progress callback should be called with |size|
   // set to the copied file size.
-  using CopyFileProgressCallback = base::Callback<void(int64_t size)>;
+  using CopyFileProgressCallback = base::RepeatingCallback<void(int64_t size)>;
 
   // The option for copy or move operation.
   enum CopyOrMoveOption {
@@ -231,14 +231,14 @@
   };
 
   // Used for Write().
-  using WriteCallback = base::Callback<
+  using WriteCallback = base::RepeatingCallback<
       void(base::File::Error result, int64_t bytes, bool complete)>;
 
   // Creates a file at |path|. If |exclusive| is true, an error is raised
   // in case a file is already present at the URL.
   virtual void CreateFile(const FileSystemURL& path,
                           bool exclusive,
-                          const StatusCallback& callback) = 0;
+                          StatusCallback callback) = 0;
 
   // Creates a directory at |path|. If |exclusive| is true, an error is
   // raised in case a directory is already present at the URL. If
@@ -247,7 +247,7 @@
   virtual void CreateDirectory(const FileSystemURL& path,
                                bool exclusive,
                                bool recursive,
-                               const StatusCallback& callback) = 0;
+                               StatusCallback callback) = 0;
 
   // Copies a file or directory from |src_path| to |dest_path|. If
   // |src_path| is a directory, the contents of |src_path| are copied to
@@ -274,7 +274,7 @@
                     CopyOrMoveOption option,
                     ErrorBehavior error_behavior,
                     const CopyProgressCallback& progress_callback,
-                    const StatusCallback& callback) = 0;
+                    StatusCallback callback) = 0;
 
   // Moves a file or directory from |src_path| to |dest_path|. A new file
   // or directory is created at |dest_path| as needed.
@@ -294,20 +294,20 @@
   virtual void Move(const FileSystemURL& src_path,
                     const FileSystemURL& dest_path,
                     CopyOrMoveOption option,
-                    const StatusCallback& callback) = 0;
+                    StatusCallback callback) = 0;
 
   // Checks if a directory is present at |path|.
   virtual void DirectoryExists(const FileSystemURL& path,
-                               const StatusCallback& callback) = 0;
+                               StatusCallback callback) = 0;
 
   // Checks if a file is present at |path|.
   virtual void FileExists(const FileSystemURL& path,
-                          const StatusCallback& callback) = 0;
+                          StatusCallback callback) = 0;
 
   // Gets the metadata of a file or directory at |path|.
   virtual void GetMetadata(const FileSystemURL& path,
                            int fields,
-                           const GetMetadataCallback& callback) = 0;
+                           GetMetadataCallback callback) = 0;
 
   // Reads contents of a directory at |path|.
   virtual void ReadDirectory(const FileSystemURL& path,
@@ -315,13 +315,20 @@
 
   // Removes a file or directory at |path|. If |recursive| is true, remove
   // all files and directories under the directory at |path| recursively.
-  virtual void Remove(const FileSystemURL& path, bool recursive,
-                      const StatusCallback& callback) = 0;
+  virtual void Remove(const FileSystemURL& path,
+                      bool recursive,
+                      StatusCallback callback) = 0;
 
   // Writes the data read from |blob_reader| using |writer_delegate|.
+  virtual void WriteBlob(const FileSystemURL& url,
+                         std::unique_ptr<FileWriterDelegate> writer_delegate,
+                         std::unique_ptr<BlobReader> blob_reader,
+                         const WriteCallback& callback) = 0;
+
+  // Writes the data read from |data_pipe| using |writer_delegate|.
   virtual void Write(const FileSystemURL& url,
                      std::unique_ptr<FileWriterDelegate> writer_delegate,
-                     std::unique_ptr<BlobReader> blob_reader,
+                     mojo::ScopedDataPipeConsumerHandle data_pipe,
                      const WriteCallback& callback) = 0;
 
   // Truncates a file at |path| to |length|. If |length| is larger than
@@ -329,7 +336,7 @@
   // part is filled with null bytes.
   virtual void Truncate(const FileSystemURL& path,
                         int64_t length,
-                        const StatusCallback& callback) = 0;
+                        StatusCallback callback) = 0;
 
   // Tries to cancel the current operation [we support cancelling write or
   // truncate only]. Reports failure for the current operation, then reports
@@ -338,7 +345,7 @@
   // E.g. a typical cancel implementation would look like:
   //
   //   virtual void SomeOperationImpl::Cancel(
-  //       const StatusCallback& cancel_callback) {
+  //       StatusCallback cancel_callback) {
   //     // Abort the current inflight operation first.
   //     ...
   //
@@ -348,13 +355,13 @@
   //
   //     // Dispatch 'success' for the cancel (or dispatch appropriate
   //     // error code with DidFail() if the cancel has somehow failed).
-  //     cancel_callback.Run(base::File::FILE_OK);
+  //     std::move(cancel_callback).Run(base::File::FILE_OK);
   //   }
   //
   // Note that, for reporting failure, the callback function passed to a
   // cancellable operations are kept around with the operation instance
   // (as |operation_callback_| in the code example).
-  virtual void Cancel(const StatusCallback& cancel_callback) = 0;
+  virtual void Cancel(StatusCallback cancel_callback) = 0;
 
   // Modifies timestamps of a file or directory at |path| with
   // |last_access_time| and |last_modified_time|. The function DOES NOT
@@ -364,7 +371,7 @@
   virtual void TouchFile(const FileSystemURL& path,
                          const base::Time& last_access_time,
                          const base::Time& last_modified_time,
-                         const StatusCallback& callback) = 0;
+                         StatusCallback callback) = 0;
 
   // Opens a file at |path| with |file_flags|, where flags are OR'ed
   // values of base::File::Flags.
@@ -372,7 +379,7 @@
   // This function is used only by Pepper as of writing.
   virtual void OpenFile(const FileSystemURL& path,
                         int file_flags,
-                        const OpenFileCallback& callback) = 0;
+                        OpenFileCallback callback) = 0;
 
   // Creates a local snapshot file for a given |path| and returns the
   // metadata and platform path of the snapshot file via |callback|.
@@ -397,7 +404,7 @@
   //
   virtual void CopyInForeignFile(const base::FilePath& src_local_disk_path,
                                  const FileSystemURL& dest_url,
-                                 const StatusCallback& callback) = 0;
+                                 StatusCallback callback) = 0;
 
   // Removes a single file.
   //
@@ -406,7 +413,7 @@
   // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file.
   //
   virtual void RemoveFile(const FileSystemURL& url,
-                          const StatusCallback& callback) = 0;
+                          StatusCallback callback) = 0;
 
   // Removes a single empty directory.
   //
@@ -416,7 +423,7 @@
   // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty.
   //
   virtual void RemoveDirectory(const FileSystemURL& url,
-                               const StatusCallback& callback) = 0;
+                               StatusCallback callback) = 0;
 
   // Copies a file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -440,7 +447,7 @@
                              const FileSystemURL& dest_url,
                              CopyOrMoveOption option,
                              const CopyFileProgressCallback& progress_callback,
-                             const StatusCallback& callback) = 0;
+                             StatusCallback callback) = 0;
 
   // Moves a local file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -460,7 +467,7 @@
   virtual void MoveFileLocal(const FileSystemURL& src_url,
                              const FileSystemURL& dest_url,
                              CopyOrMoveOption option,
-                             const StatusCallback& callback) = 0;
+                             StatusCallback callback) = 0;
 
   // Synchronously gets the platform path for the given |url|.
   // This may fail if the given |url|'s filesystem type is neither
diff --git a/storage/browser/fileapi/file_system_operation_impl.cc b/storage/browser/fileapi/file_system_operation_impl.cc
index 87454ac..cde6155 100644
--- a/storage/browser/fileapi/file_system_operation_impl.cc
+++ b/storage/browser/fileapi/file_system_operation_impl.cc
@@ -42,7 +42,7 @@
 
 void DidOpenFile(scoped_refptr<FileSystemContext> context,
                  base::WeakPtr<FileSystemOperationImpl> operation,
-                 const FileSystemOperationImpl::OpenFileCallback& callback,
+                 FileSystemOperationImpl::OpenFileCallback callback,
                  base::File file,
                  base::OnceClosure on_close_callback) {
   if (!operation) {
@@ -50,7 +50,7 @@
         FROM_HERE, base::BindOnce(&Destruct, std::move(file)));
     return;
   }
-  callback.Run(std::move(file), std::move(on_close_callback));
+  std::move(callback).Run(std::move(file), std::move(on_close_callback));
 }
 
 }  // namespace
@@ -67,34 +67,39 @@
 
 void FileSystemOperationImpl::CreateFile(const FileSystemURL& url,
                                          bool exclusive,
-                                         const StatusCallback& callback) {
+                                         StatusCallback callback) {
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::CreateFile");
 
   DCHECK(SetPendingOperationType(kOperationCreateFile));
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       url,
-      base::Bind(&FileSystemOperationImpl::DoCreateFile,
-                 weak_factory_.GetWeakPtr(), url, callback, exclusive),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoCreateFile,
+                     weak_factory_.GetWeakPtr(), url, repeatable_callback,
+                     exclusive),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
 void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url,
                                               bool exclusive,
                                               bool recursive,
-                                              const StatusCallback& callback) {
+                                              StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationCreateDirectory));
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::CreateDirectory");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       url,
-      base::Bind(&FileSystemOperationImpl::DoCreateDirectory,
-                 weak_factory_.GetWeakPtr(), url, callback,
-                 exclusive, recursive),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoCreateDirectory,
+                     weak_factory_.GetWeakPtr(), url, repeatable_callback,
+                     exclusive, recursive),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
 void FileSystemOperationImpl::Copy(
@@ -103,7 +108,7 @@
     CopyOrMoveOption option,
     ErrorBehavior error_behavior,
     const CopyProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationCopy));
   DCHECK(!recursive_operation_delegate_);
 
@@ -111,61 +116,62 @@
       file_system_context(), src_url, dest_url,
       CopyOrMoveOperationDelegate::OPERATION_COPY, option, error_behavior,
       progress_callback,
-      base::Bind(&FileSystemOperationImpl::DidFinishOperation,
-                 weak_factory_.GetWeakPtr(), callback)));
+      base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
+                     weak_factory_.GetWeakPtr(), std::move(callback))));
   recursive_operation_delegate_->RunRecursively();
 }
 
 void FileSystemOperationImpl::Move(const FileSystemURL& src_url,
                                    const FileSystemURL& dest_url,
                                    CopyOrMoveOption option,
-                                   const StatusCallback& callback) {
+                                   StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationMove));
   DCHECK(!recursive_operation_delegate_);
   recursive_operation_delegate_.reset(new CopyOrMoveOperationDelegate(
       file_system_context(), src_url, dest_url,
       CopyOrMoveOperationDelegate::OPERATION_MOVE, option, ERROR_BEHAVIOR_ABORT,
       FileSystemOperation::CopyProgressCallback(),
-      base::Bind(&FileSystemOperationImpl::DidFinishOperation,
-                 weak_factory_.GetWeakPtr(), callback)));
+      base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
+                     weak_factory_.GetWeakPtr(), std::move(callback))));
   recursive_operation_delegate_->RunRecursively();
 }
 
 void FileSystemOperationImpl::DirectoryExists(const FileSystemURL& url,
-                                              const StatusCallback& callback) {
+                                              StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationDirectoryExists));
   async_file_util_->GetFileInfo(
       std::move(operation_context_), url, GET_METADATA_FIELD_IS_DIRECTORY,
       base::BindOnce(&FileSystemOperationImpl::DidDirectoryExists,
-                     weak_factory_.GetWeakPtr(), callback));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void FileSystemOperationImpl::FileExists(const FileSystemURL& url,
-                                         const StatusCallback& callback) {
+                                         StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationFileExists));
   async_file_util_->GetFileInfo(
       std::move(operation_context_), url, GET_METADATA_FIELD_IS_DIRECTORY,
       base::BindOnce(&FileSystemOperationImpl::DidFileExists,
-                     weak_factory_.GetWeakPtr(), callback));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void FileSystemOperationImpl::GetMetadata(const FileSystemURL& url,
                                           int fields,
-                                          const GetMetadataCallback& callback) {
+                                          GetMetadataCallback callback) {
   DCHECK(SetPendingOperationType(kOperationGetMetadata));
   async_file_util_->GetFileInfo(std::move(operation_context_), url, fields,
-                                callback);
+                                std::move(callback));
 }
 
 void FileSystemOperationImpl::ReadDirectory(
-    const FileSystemURL& url, const ReadDirectoryCallback& callback) {
+    const FileSystemURL& url,
+    const ReadDirectoryCallback& callback) {
   DCHECK(SetPendingOperationType(kOperationReadDirectory));
   async_file_util_->ReadDirectory(std::move(operation_context_), url, callback);
 }
 
 void FileSystemOperationImpl::Remove(const FileSystemURL& url,
                                      bool recursive,
-                                     const StatusCallback& callback) {
+                                     StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationRemove));
   DCHECK(!recursive_operation_delegate_);
 
@@ -176,19 +182,18 @@
     async_file_util_->DeleteRecursively(
         std::move(operation_context_), url,
         base::BindOnce(&FileSystemOperationImpl::DidDeleteRecursively,
-                       weak_factory_.GetWeakPtr(), url, callback));
+                       weak_factory_.GetWeakPtr(), url, std::move(callback)));
     return;
   }
 
-  recursive_operation_delegate_.reset(
-      new RemoveOperationDelegate(
-          file_system_context(), url,
-          base::Bind(&FileSystemOperationImpl::DidFinishOperation,
-                     weak_factory_.GetWeakPtr(), callback)));
+  recursive_operation_delegate_.reset(new RemoveOperationDelegate(
+      file_system_context(), url,
+      base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
+                     weak_factory_.GetWeakPtr(), std::move(callback))));
   recursive_operation_delegate_->Run();
 }
 
-void FileSystemOperationImpl::Write(
+void FileSystemOperationImpl::WriteBlob(
     const FileSystemURL& url,
     std::unique_ptr<FileWriterDelegate> writer_delegate,
     std::unique_ptr<BlobReader> blob_reader,
@@ -201,25 +206,41 @@
                  url, callback));
 }
 
+void FileSystemOperationImpl::Write(
+    const FileSystemURL& url,
+    std::unique_ptr<FileWriterDelegate> writer_delegate,
+    mojo::ScopedDataPipeConsumerHandle data_pipe,
+    const WriteCallback& callback) {
+  DCHECK(SetPendingOperationType(kOperationWrite));
+  file_writer_delegate_ = std::move(writer_delegate);
+  file_writer_delegate_->Start(
+      std::move(data_pipe),
+      base::BindRepeating(&FileSystemOperationImpl::DidWrite,
+                          weak_factory_.GetWeakPtr(), url, callback));
+}
+
 void FileSystemOperationImpl::Truncate(const FileSystemURL& url,
                                        int64_t length,
-                                       const StatusCallback& callback) {
+                                       StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationTruncate));
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::Truncate");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       url,
-      base::Bind(&FileSystemOperationImpl::DoTruncate,
-                 weak_factory_.GetWeakPtr(), url, callback, length),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoTruncate,
+                     weak_factory_.GetWeakPtr(), url, repeatable_callback,
+                     length),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
 void FileSystemOperationImpl::TouchFile(const FileSystemURL& url,
                                         const base::Time& last_access_time,
                                         const base::Time& last_modified_time,
-                                        const StatusCallback& callback) {
+                                        StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationTouchFile));
 
   // crbug.com/349708
@@ -228,38 +249,40 @@
   async_file_util_->Touch(
       std::move(operation_context_), url, last_access_time, last_modified_time,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
-                     weak_factory_.GetWeakPtr(), callback));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void FileSystemOperationImpl::OpenFile(const FileSystemURL& url,
                                        int file_flags,
-                                       const OpenFileCallback& callback) {
+                                       OpenFileCallback callback) {
   DCHECK(SetPendingOperationType(kOperationOpenFile));
 
-  if (file_flags &
-      (base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN)) {
-    callback.Run(base::File(base::File::FILE_ERROR_FAILED),
-                 base::Closure());
+  if (file_flags & (base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN)) {
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_FAILED),
+                            base::OnceClosure());
     return;
   }
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::OpenFile");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       url,
-      base::Bind(&FileSystemOperationImpl::DoOpenFile,
-                 weak_factory_.GetWeakPtr(),
-                 url, callback, file_flags),
-      base::Bind(callback, Passed(base::File(base::File::FILE_ERROR_FAILED)),
-                 base::Closure()));
+      base::BindOnce(&FileSystemOperationImpl::DoOpenFile,
+                     weak_factory_.GetWeakPtr(), url, repeatable_callback,
+                     file_flags),
+      base::BindOnce(repeatable_callback,
+                     base::File(base::File::FILE_ERROR_FAILED),
+                     base::OnceClosure()));
 }
 
 // We can only get here on a write or truncate that's not yet completed.
 // We don't support cancelling any other operation at this time.
-void FileSystemOperationImpl::Cancel(const StatusCallback& cancel_callback) {
+void FileSystemOperationImpl::Cancel(StatusCallback cancel_callback) {
   DCHECK(cancel_callback_.is_null());
-  cancel_callback_ = cancel_callback;
+  cancel_callback_ = std::move(cancel_callback);
 
   if (file_writer_delegate_.get()) {
     DCHECK_EQ(kOperationWrite, pending_operation_);
@@ -286,38 +309,38 @@
 void FileSystemOperationImpl::CopyInForeignFile(
     const base::FilePath& src_local_disk_file_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationCopyInForeignFile));
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::CopyInForeinFile");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       dest_url,
-      base::Bind(&FileSystemOperationImpl::DoCopyInForeignFile,
-                 weak_factory_.GetWeakPtr(), src_local_disk_file_path, dest_url,
-                 callback),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoCopyInForeignFile,
+                     weak_factory_.GetWeakPtr(), src_local_disk_file_path,
+                     dest_url, repeatable_callback),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
-void FileSystemOperationImpl::RemoveFile(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void FileSystemOperationImpl::RemoveFile(const FileSystemURL& url,
+                                         StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationRemove));
   async_file_util_->DeleteFile(
       std::move(operation_context_), url,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
-                     weak_factory_.GetWeakPtr(), callback));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void FileSystemOperationImpl::RemoveDirectory(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+void FileSystemOperationImpl::RemoveDirectory(const FileSystemURL& url,
+                                              StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationRemove));
   async_file_util_->DeleteDirectory(
       std::move(operation_context_), url,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation,
-                     weak_factory_.GetWeakPtr(), callback));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void FileSystemOperationImpl::CopyFileLocal(
@@ -325,38 +348,41 @@
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
     const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationCopy));
   DCHECK(src_url.IsInSameFileSystem(dest_url));
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::CopyFileLocal");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       dest_url,
-      base::Bind(&FileSystemOperationImpl::DoCopyFileLocal,
-                 weak_factory_.GetWeakPtr(), src_url, dest_url, option,
-                 progress_callback, callback),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoCopyFileLocal,
+                     weak_factory_.GetWeakPtr(), src_url, dest_url, option,
+                     progress_callback, repeatable_callback),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
-void FileSystemOperationImpl::MoveFileLocal(
-    const FileSystemURL& src_url,
-    const FileSystemURL& dest_url,
-    CopyOrMoveOption option,
-    const StatusCallback& callback) {
+void FileSystemOperationImpl::MoveFileLocal(const FileSystemURL& src_url,
+                                            const FileSystemURL& dest_url,
+                                            CopyOrMoveOption option,
+                                            StatusCallback callback) {
   DCHECK(SetPendingOperationType(kOperationMove));
   DCHECK(src_url.IsInSameFileSystem(dest_url));
 
   // crbug.com/349708
   TRACE_EVENT0("io", "FileSystemOperationImpl::MoveFileLocal");
 
+  auto repeatable_callback =
+      base::AdaptCallbackForRepeating(std::move(callback));
   GetUsageAndQuotaThenRunTask(
       dest_url,
-      base::Bind(&FileSystemOperationImpl::DoMoveFileLocal,
-                 weak_factory_.GetWeakPtr(),
-                 src_url, dest_url, option, callback),
-      base::Bind(callback, base::File::FILE_ERROR_FAILED));
+      base::BindOnce(&FileSystemOperationImpl::DoMoveFileLocal,
+                     weak_factory_.GetWeakPtr(), src_url, dest_url, option,
+                     repeatable_callback),
+      base::BindOnce(repeatable_callback, base::File::FILE_ERROR_FAILED));
 }
 
 base::File::Error FileSystemOperationImpl::SyncGetPlatformPath(
@@ -390,8 +416,8 @@
 
 void FileSystemOperationImpl::GetUsageAndQuotaThenRunTask(
     const FileSystemURL& url,
-    const base::Closure& task,
-    const base::Closure& error_callback) {
+    base::OnceClosure task,
+    base::OnceClosure error_callback) {
   storage::QuotaManagerProxy* quota_manager_proxy =
       file_system_context()->quota_manager_proxy();
   if (!quota_manager_proxy ||
@@ -400,7 +426,7 @@
     // does not support quota, we should be able to let it go.
     operation_context_->set_allowed_bytes_growth(
         std::numeric_limits<int64_t>::max());
-    task.Run();
+    std::move(task).Run();
     return;
   }
 
@@ -410,45 +436,44 @@
       url::Origin::Create(url.origin()),
       FileSystemTypeToQuotaStorageType(url.type()),
       base::BindOnce(&FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask,
-                     weak_ptr_, task, error_callback));
+                     weak_ptr_, std::move(task), std::move(error_callback)));
 }
 
 void FileSystemOperationImpl::DidGetUsageAndQuotaAndRunTask(
-    const base::Closure& task,
-    const base::Closure& error_callback,
+    base::OnceClosure task,
+    base::OnceClosure error_callback,
     blink::mojom::QuotaStatusCode status,
     int64_t usage,
     int64_t quota) {
   if (status != blink::mojom::QuotaStatusCode::kOk) {
     LOG(WARNING) << "Got unexpected quota error : " << static_cast<int>(status);
-    error_callback.Run();
+    std::move(error_callback).Run();
     return;
   }
 
   operation_context_->set_allowed_bytes_growth(quota - usage);
-  task.Run();
+  std::move(task).Run();
 }
 
-void FileSystemOperationImpl::DoCreateFile(
-    const FileSystemURL& url,
-    const StatusCallback& callback,
-    bool exclusive) {
+void FileSystemOperationImpl::DoCreateFile(const FileSystemURL& url,
+                                           StatusCallback callback,
+                                           bool exclusive) {
   async_file_util_->EnsureFileExists(
       std::move(operation_context_), url,
       base::BindOnce(
           exclusive ? &FileSystemOperationImpl::DidEnsureFileExistsExclusive
                     : &FileSystemOperationImpl::DidEnsureFileExistsNonExclusive,
-          weak_ptr_, callback));
+          weak_ptr_, std::move(callback)));
 }
 
-void FileSystemOperationImpl::DoCreateDirectory(
-    const FileSystemURL& url,
-    const StatusCallback& callback,
-    bool exclusive, bool recursive) {
+void FileSystemOperationImpl::DoCreateDirectory(const FileSystemURL& url,
+                                                StatusCallback callback,
+                                                bool exclusive,
+                                                bool recursive) {
   async_file_util_->CreateDirectory(
       std::move(operation_context_), url, exclusive, recursive,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                     callback));
+                     std::move(callback)));
 }
 
 void FileSystemOperationImpl::DoCopyFileLocal(
@@ -456,118 +481,118 @@
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
     const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   async_file_util_->CopyFileLocal(
       std::move(operation_context_), src_url, dest_url, option,
       progress_callback,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                     callback));
+                     std::move(callback)));
 }
 
-void FileSystemOperationImpl::DoMoveFileLocal(
-    const FileSystemURL& src_url,
-    const FileSystemURL& dest_url,
-    CopyOrMoveOption option,
-    const StatusCallback& callback) {
+void FileSystemOperationImpl::DoMoveFileLocal(const FileSystemURL& src_url,
+                                              const FileSystemURL& dest_url,
+                                              CopyOrMoveOption option,
+                                              StatusCallback callback) {
   async_file_util_->MoveFileLocal(
       std::move(operation_context_), src_url, dest_url, option,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                     callback));
+                     std::move(callback)));
 }
 
 void FileSystemOperationImpl::DoCopyInForeignFile(
     const base::FilePath& src_local_disk_file_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   async_file_util_->CopyInForeignFile(
       std::move(operation_context_), src_local_disk_file_path, dest_url,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                     callback));
+                     std::move(callback)));
 }
 
 void FileSystemOperationImpl::DoTruncate(const FileSystemURL& url,
-                                         const StatusCallback& callback,
+                                         StatusCallback callback,
                                          int64_t length) {
   async_file_util_->Truncate(
       std::move(operation_context_), url, length,
       base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                     callback));
+                     std::move(callback)));
 }
 
 void FileSystemOperationImpl::DoOpenFile(const FileSystemURL& url,
-                                         const OpenFileCallback& callback,
+                                         OpenFileCallback callback,
                                          int file_flags) {
   async_file_util_->CreateOrOpen(
       std::move(operation_context_), url, file_flags,
-      base::BindOnce(&DidOpenFile, file_system_context_, weak_ptr_, callback));
+      base::BindOnce(&DidOpenFile, file_system_context_, weak_ptr_,
+                     std::move(callback)));
 }
 
 void FileSystemOperationImpl::DidEnsureFileExistsExclusive(
-    const StatusCallback& callback,
-    base::File::Error rv, bool created) {
+    StatusCallback callback,
+    base::File::Error rv,
+    bool created) {
   if (rv == base::File::FILE_OK && !created) {
-    callback.Run(base::File::FILE_ERROR_EXISTS);
+    std::move(callback).Run(base::File::FILE_ERROR_EXISTS);
   } else {
-    DidFinishOperation(callback, rv);
+    DidFinishOperation(std::move(callback), rv);
   }
 }
 
 void FileSystemOperationImpl::DidEnsureFileExistsNonExclusive(
-    const StatusCallback& callback,
-    base::File::Error rv, bool /* created */) {
-  DidFinishOperation(callback, rv);
+    StatusCallback callback,
+    base::File::Error rv,
+    bool /* created */) {
+  DidFinishOperation(std::move(callback), rv);
 }
 
-void FileSystemOperationImpl::DidFinishOperation(
-    const StatusCallback& callback,
-    base::File::Error rv) {
+void FileSystemOperationImpl::DidFinishOperation(StatusCallback callback,
+                                                 base::File::Error rv) {
   if (!cancel_callback_.is_null()) {
-    StatusCallback cancel_callback = cancel_callback_;
-    callback.Run(rv);
+    StatusCallback cancel_callback = std::move(cancel_callback_);
+    std::move(callback).Run(rv);
 
     // Return OK only if we succeeded to stop the operation.
-    cancel_callback.Run(rv == base::File::FILE_ERROR_ABORT ?
-                        base::File::FILE_OK :
-                        base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(cancel_callback)
+        .Run(rv == base::File::FILE_ERROR_ABORT
+                 ? base::File::FILE_OK
+                 : base::File::FILE_ERROR_INVALID_OPERATION);
   } else {
-    callback.Run(rv);
+    std::move(callback).Run(rv);
   }
 }
 
 void FileSystemOperationImpl::DidDirectoryExists(
-    const StatusCallback& callback,
+    StatusCallback callback,
     base::File::Error rv,
     const base::File::Info& file_info) {
   if (rv == base::File::FILE_OK && !file_info.is_directory)
     rv = base::File::FILE_ERROR_NOT_A_DIRECTORY;
-  callback.Run(rv);
+  std::move(callback).Run(rv);
 }
 
-void FileSystemOperationImpl::DidFileExists(
-    const StatusCallback& callback,
-    base::File::Error rv,
-    const base::File::Info& file_info) {
+void FileSystemOperationImpl::DidFileExists(StatusCallback callback,
+                                            base::File::Error rv,
+                                            const base::File::Info& file_info) {
   if (rv == base::File::FILE_OK && file_info.is_directory)
     rv = base::File::FILE_ERROR_NOT_A_FILE;
-  callback.Run(rv);
+  std::move(callback).Run(rv);
 }
 
-void FileSystemOperationImpl::DidDeleteRecursively(
-    const FileSystemURL& url,
-    const StatusCallback& callback,
-    base::File::Error rv) {
+void FileSystemOperationImpl::DidDeleteRecursively(const FileSystemURL& url,
+                                                   StatusCallback callback,
+                                                   base::File::Error rv) {
   if (rv == base::File::FILE_ERROR_INVALID_OPERATION) {
     // Recursive removal is not supported on this platform.
     DCHECK(!recursive_operation_delegate_);
     recursive_operation_delegate_.reset(new RemoveOperationDelegate(
         file_system_context(), url,
-        base::Bind(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
-                   callback)));
+        base::BindOnce(&FileSystemOperationImpl::DidFinishOperation, weak_ptr_,
+                       std::move(callback))));
     recursive_operation_delegate_->RunRecursively();
     return;
   }
 
-  callback.Run(rv);
+  std::move(callback).Run(rv);
 }
 
 void FileSystemOperationImpl::DidWrite(
@@ -576,18 +601,18 @@
     base::File::Error rv,
     int64_t bytes,
     FileWriterDelegate::WriteProgressStatus write_status) {
-  const bool complete = (
-      write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
+  const bool complete =
+      (write_status != FileWriterDelegate::SUCCESS_IO_PENDING);
   if (complete && write_status != FileWriterDelegate::ERROR_WRITE_NOT_STARTED) {
     DCHECK(operation_context_);
     operation_context_->change_observers()->Notify(
         &FileChangeObserver::OnModifyFile, url);
   }
 
-  StatusCallback cancel_callback = cancel_callback_;
+  StatusCallback cancel_callback = std::move(cancel_callback_);
   write_callback.Run(rv, bytes, complete);
   if (!cancel_callback.is_null())
-    cancel_callback.Run(base::File::FILE_OK);
+    std::move(cancel_callback).Run(base::File::FILE_OK);
 }
 
 bool FileSystemOperationImpl::SetPendingOperationType(OperationType type) {
diff --git a/storage/browser/fileapi/file_system_operation_impl.h b/storage/browser/fileapi/file_system_operation_impl.h
index cc68390..d7a6047d 100644
--- a/storage/browser/fileapi/file_system_operation_impl.h
+++ b/storage/browser/fileapi/file_system_operation_impl.h
@@ -35,66 +35,68 @@
   // FileSystemOperation overrides.
   void CreateFile(const FileSystemURL& url,
                   bool exclusive,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void CreateDirectory(const FileSystemURL& url,
                        bool exclusive,
                        bool recursive,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void Copy(const FileSystemURL& src_url,
             const FileSystemURL& dest_url,
             CopyOrMoveOption option,
             ErrorBehavior error_behavior,
             const CopyProgressCallback& progress_callback,
-            const StatusCallback& callback) override;
+            StatusCallback callback) override;
   void Move(const FileSystemURL& src_url,
             const FileSystemURL& dest_url,
             CopyOrMoveOption option,
-            const StatusCallback& callback) override;
+            StatusCallback callback) override;
   void DirectoryExists(const FileSystemURL& url,
-                       const StatusCallback& callback) override;
-  void FileExists(const FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                       StatusCallback callback) override;
+  void FileExists(const FileSystemURL& url, StatusCallback callback) override;
   void GetMetadata(const FileSystemURL& url,
                    int fields,
-                   const GetMetadataCallback& callback) override;
+                   GetMetadataCallback callback) override;
   void ReadDirectory(const FileSystemURL& url,
                      const ReadDirectoryCallback& callback) override;
   void Remove(const FileSystemURL& url,
               bool recursive,
-              const StatusCallback& callback) override;
+              StatusCallback callback) override;
+  void WriteBlob(const FileSystemURL& url,
+                 std::unique_ptr<FileWriterDelegate> writer_delegate,
+                 std::unique_ptr<BlobReader> blob_reader,
+                 const WriteCallback& callback) override;
   void Write(const FileSystemURL& url,
              std::unique_ptr<FileWriterDelegate> writer_delegate,
-             std::unique_ptr<BlobReader> blob_reader,
+             mojo::ScopedDataPipeConsumerHandle data_pipe,
              const WriteCallback& callback) override;
   void Truncate(const FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void TouchFile(const FileSystemURL& url,
                  const base::Time& last_access_time,
                  const base::Time& last_modified_time,
-                 const StatusCallback& callback) override;
+                 StatusCallback callback) override;
   void OpenFile(const FileSystemURL& url,
                 int file_flags,
-                const OpenFileCallback& callback) override;
-  void Cancel(const StatusCallback& cancel_callback) override;
+                OpenFileCallback callback) override;
+  void Cancel(StatusCallback cancel_callback) override;
   void CreateSnapshotFile(const FileSystemURL& path,
                           SnapshotFileCallback callback) override;
   void CopyInForeignFile(const base::FilePath& src_local_disk_path,
                          const FileSystemURL& dest_url,
-                         const StatusCallback& callback) override;
-  void RemoveFile(const FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                         StatusCallback callback) override;
+  void RemoveFile(const FileSystemURL& url, StatusCallback callback) override;
   void RemoveDirectory(const FileSystemURL& url,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void CopyFileLocal(const FileSystemURL& src_url,
                      const FileSystemURL& dest_url,
                      CopyOrMoveOption option,
                      const CopyFileProgressCallback& progress_callback,
-                     const StatusCallback& callback) override;
+                     StatusCallback callback) override;
   void MoveFileLocal(const FileSystemURL& src_url,
                      const FileSystemURL& dest_url,
                      CopyOrMoveOption option,
-                     const StatusCallback& callback) override;
+                     StatusCallback callback) override;
   base::File::Error SyncGetPlatformPath(const FileSystemURL& url,
                                         base::FilePath* platform_path) override;
 
@@ -112,18 +114,17 @@
 
   // Queries the quota and usage and then runs the given |task|.
   // If an error occurs during the quota query it runs |error_callback| instead.
-  void GetUsageAndQuotaThenRunTask(
-      const FileSystemURL& url,
-      const base::Closure& task,
-      const base::Closure& error_callback);
+  void GetUsageAndQuotaThenRunTask(const FileSystemURL& url,
+                                   base::OnceClosure task,
+                                   base::OnceClosure error_callback);
 
   // Called after the quota info is obtained from the quota manager
   // (which is triggered by GetUsageAndQuotaThenRunTask).
   // Sets the quota info in the operation_context_ and then runs the given
   // |task| if the returned quota status is successful, otherwise runs
   // |error_callback|.
-  void DidGetUsageAndQuotaAndRunTask(const base::Closure& task,
-                                     const base::Closure& error_callback,
+  void DidGetUsageAndQuotaAndRunTask(base::OnceClosure task,
+                                     base::OnceClosure error_callback,
                                      blink::mojom::QuotaStatusCode status,
                                      int64_t usage,
                                      int64_t quota);
@@ -131,49 +132,50 @@
   // The 'body' methods that perform the actual work (i.e. posting the
   // file task on proxy_) after the quota check.
   void DoCreateFile(const FileSystemURL& url,
-                    const StatusCallback& callback, bool exclusive);
+                    StatusCallback callback,
+                    bool exclusive);
   void DoCreateDirectory(const FileSystemURL& url,
-                         const StatusCallback& callback,
+                         StatusCallback callback,
                          bool exclusive,
                          bool recursive);
   void DoCopyFileLocal(const FileSystemURL& src,
                        const FileSystemURL& dest,
                        CopyOrMoveOption option,
                        const CopyFileProgressCallback& progress_callback,
-                       const StatusCallback& callback);
+                       StatusCallback callback);
   void DoMoveFileLocal(const FileSystemURL& src,
                        const FileSystemURL& dest,
                        CopyOrMoveOption option,
-                       const StatusCallback& callback);
+                       StatusCallback callback);
   void DoCopyInForeignFile(const base::FilePath& src_local_disk_file_path,
                            const FileSystemURL& dest,
-                           const StatusCallback& callback);
+                           StatusCallback callback);
   void DoTruncate(const FileSystemURL& url,
-                  const StatusCallback& callback,
+                  StatusCallback callback,
                   int64_t length);
   void DoOpenFile(const FileSystemURL& url,
-                  const OpenFileCallback& callback, int file_flags);
+                  OpenFileCallback callback,
+                  int file_flags);
 
   // Callback for CreateFile for |exclusive|=true cases.
-  void DidEnsureFileExistsExclusive(const StatusCallback& callback,
+  void DidEnsureFileExistsExclusive(StatusCallback callback,
                                     base::File::Error rv,
                                     bool created);
 
   // Callback for CreateFile for |exclusive|=false cases.
-  void DidEnsureFileExistsNonExclusive(const StatusCallback& callback,
+  void DidEnsureFileExistsNonExclusive(StatusCallback callback,
                                        base::File::Error rv,
                                        bool created);
 
-  void DidFinishOperation(const StatusCallback& callback,
-                          base::File::Error rv);
-  void DidDirectoryExists(const StatusCallback& callback,
+  void DidFinishOperation(StatusCallback callback, base::File::Error rv);
+  void DidDirectoryExists(StatusCallback callback,
                           base::File::Error rv,
                           const base::File::Info& file_info);
-  void DidFileExists(const StatusCallback& callback,
+  void DidFileExists(StatusCallback callback,
                      base::File::Error rv,
                      const base::File::Info& file_info);
   void DidDeleteRecursively(const FileSystemURL& url,
-                            const StatusCallback& callback,
+                            StatusCallback callback,
                             base::File::Error rv);
   void DidWrite(const FileSystemURL& url,
                 const WriteCallback& callback,
diff --git a/storage/browser/fileapi/file_system_operation_runner.cc b/storage/browser/fileapi/file_system_operation_runner.cc
index 75330e4..68701b2b 100644
--- a/storage/browser/fileapi/file_system_operation_runner.cc
+++ b/storage/browser/fileapi/file_system_operation_runner.cc
@@ -36,10 +36,9 @@
   operations_.clear();
 }
 
-OperationID FileSystemOperationRunner::CreateFile(
-    const FileSystemURL& url,
-    bool exclusive,
-    const StatusCallback& callback) {
+OperationID FileSystemOperationRunner::CreateFile(const FileSystemURL& url,
+                                                  bool exclusive,
+                                                  StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -47,13 +46,14 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
-  operation_raw->CreateFile(url, exclusive,
-                            base::Bind(&FileSystemOperationRunner::DidFinish,
-                                       weak_ptr_, id, callback));
+  operation_raw->CreateFile(
+      url, exclusive,
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -61,7 +61,7 @@
     const FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -69,14 +69,14 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->CreateDirectory(
       url, exclusive, recursive,
-      base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                 callback));
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -86,7 +86,7 @@
     CopyOrMoveOption option,
     ErrorBehavior error_behavior,
     const CopyProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(dest_url, &error));
@@ -94,7 +94,7 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, dest_url);
@@ -105,16 +105,15 @@
           ? CopyProgressCallback()
           : base::Bind(&FileSystemOperationRunner::OnCopyProgress, weak_ptr_,
                        id, progress_callback),
-      base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                 callback));
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
-OperationID FileSystemOperationRunner::Move(
-    const FileSystemURL& src_url,
-    const FileSystemURL& dest_url,
-    CopyOrMoveOption option,
-    const StatusCallback& callback) {
+OperationID FileSystemOperationRunner::Move(const FileSystemURL& src_url,
+                                            const FileSystemURL& dest_url,
+                                            CopyOrMoveOption option,
+                                            StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(dest_url, &error));
@@ -122,20 +121,20 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, dest_url);
   PrepareForWrite(id, src_url);
   operation_raw->Move(src_url, dest_url, option,
-                      base::Bind(&FileSystemOperationRunner::DidFinish,
-                                 weak_ptr_, id, callback));
+                      base::BindOnce(&FileSystemOperationRunner::DidFinish,
+                                     weak_ptr_, id, std::move(callback)));
   return id;
 }
 
 OperationID FileSystemOperationRunner::DirectoryExists(
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -143,19 +142,18 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForRead(id, url);
   operation_raw->DirectoryExists(
-      url, base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                      callback));
+      url, base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                          std::move(callback)));
   return id;
 }
 
-OperationID FileSystemOperationRunner::FileExists(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+OperationID FileSystemOperationRunner::FileExists(const FileSystemURL& url,
+                                                  StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -163,20 +161,20 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForRead(id, url);
   operation_raw->FileExists(
-      url, base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                      callback));
+      url, base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                          std::move(callback)));
   return id;
 }
 
 OperationID FileSystemOperationRunner::GetMetadata(
     const FileSystemURL& url,
     int fields,
-    const GetMetadataCallback& callback) {
+    GetMetadataCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -184,14 +182,14 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidGetMetadata(id, callback, error, base::File::Info());
+    DidGetMetadata(id, std::move(callback), error, base::File::Info());
     return id;
   }
   PrepareForRead(id, url);
   operation_raw->GetMetadata(
       url, fields,
-      base::Bind(&FileSystemOperationRunner::DidGetMetadata, weak_ptr_, id,
-                 callback));
+      base::BindOnce(&FileSystemOperationRunner::DidGetMetadata, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -216,9 +214,9 @@
   return id;
 }
 
-OperationID FileSystemOperationRunner::Remove(
-    const FileSystemURL& url, bool recursive,
-    const StatusCallback& callback) {
+OperationID FileSystemOperationRunner::Remove(const FileSystemURL& url,
+                                              bool recursive,
+                                              StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -226,13 +224,13 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->Remove(url, recursive,
-                        base::Bind(&FileSystemOperationRunner::DidFinish,
-                                   weak_ptr_, id, callback));
+                        base::BindOnce(&FileSystemOperationRunner::DidFinish,
+                                       weak_ptr_, id, std::move(callback)));
   return id;
 }
 
@@ -268,16 +266,18 @@
     blob_reader = blob->CreateReader();
 
   PrepareForWrite(id, url);
-  operation_raw->Write(url, std::move(writer_delegate), std::move(blob_reader),
-                       base::Bind(&FileSystemOperationRunner::DidWrite,
-                                  weak_ptr_, id, callback));
+  operation_raw->WriteBlob(
+      url, std::move(writer_delegate), std::move(blob_reader),
+      base::BindRepeating(&FileSystemOperationRunner::DidWrite, weak_ptr_, id,
+                          callback));
   return id;
 }
 
-OperationID FileSystemOperationRunner::Truncate(
+OperationID FileSystemOperationRunner::Write(
     const FileSystemURL& url,
-    int64_t length,
-    const StatusCallback& callback) {
+    mojo::ScopedDataPipeConsumerHandle data_pipe,
+    int64_t offset,
+    const WriteCallback& callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -285,39 +285,70 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidWrite(id, callback, error, 0, true);
+    return id;
+  }
+
+  std::unique_ptr<FileStreamWriter> writer(
+      file_system_context_->CreateFileStreamWriter(url, offset));
+  if (!writer) {
+    // Write is not supported.
+    DidWrite(id, callback, base::File::FILE_ERROR_SECURITY, 0, true);
+    return id;
+  }
+
+  std::unique_ptr<FileWriterDelegate> writer_delegate(new FileWriterDelegate(
+      std::move(writer), url.mount_option().flush_policy()));
+
+  PrepareForWrite(id, url);
+  operation_raw->Write(url, std::move(writer_delegate), std::move(data_pipe),
+                       base::BindRepeating(&FileSystemOperationRunner::DidWrite,
+                                           weak_ptr_, id, callback));
+  return id;
+}
+
+OperationID FileSystemOperationRunner::Truncate(const FileSystemURL& url,
+                                                int64_t length,
+                                                StatusCallback callback) {
+  base::File::Error error = base::File::FILE_OK;
+  std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
+      file_system_context_->CreateFileSystemOperation(url, &error));
+  FileSystemOperation* operation_raw = operation.get();
+  OperationID id = BeginOperation(std::move(operation));
+  base::AutoReset<bool> beginning(&is_beginning_operation_, true);
+  if (!operation_raw) {
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->Truncate(url, length,
-                          base::Bind(&FileSystemOperationRunner::DidFinish,
-                                     weak_ptr_, id, callback));
+                          base::BindOnce(&FileSystemOperationRunner::DidFinish,
+                                         weak_ptr_, id, std::move(callback)));
   return id;
 }
 
-void FileSystemOperationRunner::Cancel(
-    OperationID id,
-    const StatusCallback& callback) {
+void FileSystemOperationRunner::Cancel(OperationID id,
+                                       StatusCallback callback) {
   if (base::ContainsKey(finished_operations_, id)) {
     DCHECK(!base::ContainsKey(stray_cancel_callbacks_, id));
-    stray_cancel_callbacks_[id] = callback;
+    stray_cancel_callbacks_[id] = std::move(callback);
     return;
   }
 
   Operations::iterator found = operations_.find(id);
   if (found == operations_.end() || !found->second) {
     // There is no operation with |id|.
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
-  found->second->Cancel(callback);
+  found->second->Cancel(std::move(callback));
 }
 
 OperationID FileSystemOperationRunner::TouchFile(
     const FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -325,20 +356,19 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->TouchFile(url, last_access_time, last_modified_time,
-                           base::Bind(&FileSystemOperationRunner::DidFinish,
-                                      weak_ptr_, id, callback));
+                           base::BindOnce(&FileSystemOperationRunner::DidFinish,
+                                          weak_ptr_, id, std::move(callback)));
   return id;
 }
 
-OperationID FileSystemOperationRunner::OpenFile(
-    const FileSystemURL& url,
-    int file_flags,
-    const OpenFileCallback& callback) {
+OperationID FileSystemOperationRunner::OpenFile(const FileSystemURL& url,
+                                                int file_flags,
+                                                OpenFileCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -346,7 +376,8 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidOpenFile(id, callback, base::File(error), base::Closure());
+    DidOpenFile(id, std::move(callback), base::File(error),
+                base::OnceClosure());
     return id;
   }
   if (file_flags &
@@ -359,9 +390,10 @@
   } else {
     PrepareForRead(id, url);
   }
-  operation_raw->OpenFile(url, file_flags,
-                          base::Bind(&FileSystemOperationRunner::DidOpenFile,
-                                     weak_ptr_, id, callback));
+  operation_raw->OpenFile(
+      url, file_flags,
+      base::BindOnce(&FileSystemOperationRunner::DidOpenFile, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -389,7 +421,7 @@
 OperationID FileSystemOperationRunner::CopyInForeignFile(
     const base::FilePath& src_local_disk_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(dest_url, &error));
@@ -397,20 +429,19 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, dest_url);
   operation_raw->CopyInForeignFile(
       src_local_disk_path, dest_url,
-      base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                 callback));
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
-OperationID FileSystemOperationRunner::RemoveFile(
-    const FileSystemURL& url,
-    const StatusCallback& callback) {
+OperationID FileSystemOperationRunner::RemoveFile(const FileSystemURL& url,
+                                                  StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -418,19 +449,19 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->RemoveFile(
-      url, base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                      callback));
+      url, base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                          std::move(callback)));
   return id;
 }
 
 OperationID FileSystemOperationRunner::RemoveDirectory(
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(url, &error));
@@ -438,13 +469,13 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, url);
   operation_raw->RemoveDirectory(
-      url, base::Bind(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
-                      callback));
+      url, base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                          std::move(callback)));
   return id;
 }
 
@@ -453,7 +484,7 @@
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
     const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(src_url, &error));
@@ -461,14 +492,15 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForRead(id, src_url);
   PrepareForWrite(id, dest_url);
-  operation_raw->CopyFileLocal(src_url, dest_url, option, progress_callback,
-                               base::Bind(&FileSystemOperationRunner::DidFinish,
-                                          weak_ptr_, id, callback));
+  operation_raw->CopyFileLocal(
+      src_url, dest_url, option, progress_callback,
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -476,7 +508,7 @@
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   base::File::Error error = base::File::FILE_OK;
   std::unique_ptr<FileSystemOperation> operation = base::WrapUnique(
       file_system_context_->CreateFileSystemOperation(src_url, &error));
@@ -484,14 +516,15 @@
   OperationID id = BeginOperation(std::move(operation));
   base::AutoReset<bool> beginning(&is_beginning_operation_, true);
   if (!operation_raw) {
-    DidFinish(id, callback, error);
+    DidFinish(id, std::move(callback), error);
     return id;
   }
   PrepareForWrite(id, src_url);
   PrepareForWrite(id, dest_url);
-  operation_raw->MoveFileLocal(src_url, dest_url, option,
-                               base::Bind(&FileSystemOperationRunner::DidFinish,
-                                          weak_ptr_, id, callback));
+  operation_raw->MoveFileLocal(
+      src_url, dest_url, option,
+      base::BindOnce(&FileSystemOperationRunner::DidFinish, weak_ptr_, id,
+                     std::move(callback)));
   return id;
 }
 
@@ -513,32 +546,33 @@
 }
 
 void FileSystemOperationRunner::DidFinish(const OperationID id,
-                                          const StatusCallback& callback,
+                                          StatusCallback callback,
                                           base::File::Error rv) {
   if (is_beginning_operation_) {
     finished_operations_.insert(id);
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&FileSystemOperationRunner::DidFinish,
-                                  weak_ptr_, id, callback, rv));
+                                  weak_ptr_, id, std::move(callback), rv));
     return;
   }
-  callback.Run(rv);
+  std::move(callback).Run(rv);
   FinishOperation(id);
 }
 
 void FileSystemOperationRunner::DidGetMetadata(
     const OperationID id,
-    const GetMetadataCallback& callback,
+    GetMetadataCallback callback,
     base::File::Error rv,
     const base::File::Info& file_info) {
   if (is_beginning_operation_) {
     finished_operations_.insert(id);
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&FileSystemOperationRunner::DidGetMetadata,
-                                  weak_ptr_, id, callback, rv, file_info));
+        FROM_HERE,
+        base::BindOnce(&FileSystemOperationRunner::DidGetMetadata, weak_ptr_,
+                       id, std::move(callback), rv, file_info));
     return;
   }
-  callback.Run(rv, file_info);
+  std::move(callback).Run(rv, file_info);
   FinishOperation(id);
 }
 
@@ -581,18 +615,19 @@
 
 void FileSystemOperationRunner::DidOpenFile(
     const OperationID id,
-    const OpenFileCallback& callback,
+    OpenFileCallback callback,
     base::File file,
     base::OnceClosure on_close_callback) {
   if (is_beginning_operation_) {
     finished_operations_.insert(id);
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&FileSystemOperationRunner::DidOpenFile,
-                                  weak_ptr_, id, callback, std::move(file),
-                                  std::move(on_close_callback)));
+        FROM_HERE,
+        base::BindOnce(&FileSystemOperationRunner::DidOpenFile, weak_ptr_, id,
+                       std::move(callback), std::move(file),
+                       std::move(on_close_callback)));
     return;
   }
-  callback.Run(std::move(file), std::move(on_close_callback));
+  std::move(callback).Run(std::move(file), std::move(on_close_callback));
   FinishOperation(id);
 }
 
@@ -689,7 +724,8 @@
   if (found_cancel != stray_cancel_callbacks_.end()) {
     // This cancel has been requested after the operation has finished,
     // so report that we failed to stop it.
-    found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(found_cancel->second)
+        .Run(base::File::FILE_ERROR_INVALID_OPERATION);
     stray_cancel_callbacks_.erase(found_cancel);
   }
 }
diff --git a/storage/browser/fileapi/file_system_operation_runner.h b/storage/browser/fileapi/file_system_operation_runner.h
index c786c6e25..d9edf8d 100644
--- a/storage/browser/fileapi/file_system_operation_runner.h
+++ b/storage/browser/fileapi/file_system_operation_runner.h
@@ -59,12 +59,12 @@
   // in case a file is already present at the URL.
   OperationID CreateFile(const FileSystemURL& url,
                          bool exclusive,
-                         const StatusCallback& callback);
+                         StatusCallback callback);
 
   OperationID CreateDirectory(const FileSystemURL& url,
                               bool exclusive,
                               bool recursive,
-                              const StatusCallback& callback);
+                              StatusCallback callback);
 
   // Copies a file or directory from |src_url| to |dest_url|. If
   // |src_url| is a directory, the contents of |src_url| are copied to
@@ -77,7 +77,7 @@
                    CopyOrMoveOption option,
                    ErrorBehavior error_behavior,
                    const CopyProgressCallback& progress_callback,
-                   const StatusCallback& callback);
+                   StatusCallback callback);
 
   // Moves a file or directory from |src_url| to |dest_url|. A new file
   // or directory is created at |dest_url| as needed.
@@ -85,20 +85,19 @@
   OperationID Move(const FileSystemURL& src_url,
                    const FileSystemURL& dest_url,
                    CopyOrMoveOption option,
-                   const StatusCallback& callback);
+                   StatusCallback callback);
 
   // Checks if a directory is present at |url|.
   OperationID DirectoryExists(const FileSystemURL& url,
-                              const StatusCallback& callback);
+                              StatusCallback callback);
 
   // Checks if a file is present at |url|.
-  OperationID FileExists(const FileSystemURL& url,
-                         const StatusCallback& callback);
+  OperationID FileExists(const FileSystemURL& url, StatusCallback callback);
 
   // Gets the metadata of a file or directory at |url|.
   OperationID GetMetadata(const FileSystemURL& url,
                           int fields,
-                          const GetMetadataCallback& callback);
+                          GetMetadataCallback callback);
 
   // Reads contents of a directory at |url|.
   OperationID ReadDirectory(const FileSystemURL& url,
@@ -106,26 +105,33 @@
 
   // Removes a file or directory at |url|. If |recursive| is true, remove
   // all files and directories under the directory at |url| recursively.
-  OperationID Remove(const FileSystemURL& url, bool recursive,
-                     const StatusCallback& callback);
+  OperationID Remove(const FileSystemURL& url,
+                     bool recursive,
+                     StatusCallback callback);
 
-  // Writes contents of |blob_url| to |url| at |offset|.
+  // Writes contents of |blob| to |url| at |offset|.
   OperationID Write(const FileSystemURL& url,
                     std::unique_ptr<storage::BlobDataHandle> blob,
                     int64_t offset,
                     const WriteCallback& callback);
 
+  // Writes contents of |data_pipe| to |url| at |offset|.
+  OperationID Write(const FileSystemURL& url,
+                    mojo::ScopedDataPipeConsumerHandle data_pipe,
+                    int64_t offset,
+                    const WriteCallback& callback);
+
   // Truncates a file at |url| to |length|. If |length| is larger than
   // the original file size, the file will be extended, and the extended
   // part is filled with null bytes.
   OperationID Truncate(const FileSystemURL& url,
                        int64_t length,
-                       const StatusCallback& callback);
+                       StatusCallback callback);
 
   // Tries to cancel the operation |id| [we support cancelling write or
   // truncate only]. Reports failure for the current operation, then reports
   // success for the cancel operation itself via the |callback|.
-  void Cancel(OperationID id, const StatusCallback& callback);
+  void Cancel(OperationID id, StatusCallback callback);
 
   // Modifies timestamps of a file or directory at |url| with
   // |last_access_time| and |last_modified_time|. The function DOES NOT
@@ -135,7 +141,7 @@
   OperationID TouchFile(const FileSystemURL& url,
                         const base::Time& last_access_time,
                         const base::Time& last_modified_time,
-                        const StatusCallback& callback);
+                        StatusCallback callback);
 
   // Opens a file at |url| with |file_flags|, where flags are OR'ed
   // values of base::PlatformFileFlags.
@@ -146,7 +152,7 @@
   // This function is used only by Pepper as of writing.
   OperationID OpenFile(const FileSystemURL& url,
                        int file_flags,
-                       const OpenFileCallback& callback);
+                       OpenFileCallback callback);
 
   // Creates a local snapshot file for a given |url| and returns the
   // metadata and platform url of the snapshot file via |callback|.
@@ -171,7 +177,7 @@
   //
   OperationID CopyInForeignFile(const base::FilePath& src_local_disk_path,
                                 const FileSystemURL& dest_url,
-                                const StatusCallback& callback);
+                                StatusCallback callback);
 
   // Removes a single file.
   //
@@ -179,8 +185,7 @@
   // - File::FILE_ERROR_NOT_FOUND if |url| does not exist.
   // - File::FILE_ERROR_NOT_A_FILE if |url| is not a file.
   //
-  OperationID RemoveFile(const FileSystemURL& url,
-                         const StatusCallback& callback);
+  OperationID RemoveFile(const FileSystemURL& url, StatusCallback callback);
 
   // Removes a single empty directory.
   //
@@ -190,7 +195,7 @@
   // - File::FILE_ERROR_NOT_EMPTY if |url| is not empty.
   //
   OperationID RemoveDirectory(const FileSystemURL& url,
-                              const StatusCallback& callback);
+                              StatusCallback callback);
 
   // Copies a file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -211,7 +216,7 @@
                             const FileSystemURL& dest_url,
                             CopyOrMoveOption option,
                             const CopyFileProgressCallback& progress_callback,
-                            const StatusCallback& callback);
+                            StatusCallback callback);
 
   // Moves a local file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -230,7 +235,7 @@
   OperationID MoveFileLocal(const FileSystemURL& src_url,
                             const FileSystemURL& dest_url,
                             CopyOrMoveOption option,
-                            const StatusCallback& callback);
+                            StatusCallback callback);
 
   // This is called only by pepper plugin as of writing to synchronously get
   // the underlying platform path to upload a file in the sandboxed filesystem
@@ -243,10 +248,10 @@
   explicit FileSystemOperationRunner(FileSystemContext* file_system_context);
 
   void DidFinish(const OperationID id,
-                 const StatusCallback& callback,
+                 StatusCallback callback,
                  base::File::Error rv);
   void DidGetMetadata(const OperationID id,
-                      const GetMetadataCallback& callback,
+                      GetMetadataCallback callback,
                       base::File::Error rv,
                       const base::File::Info& file_info);
   void DidReadDirectory(const OperationID id,
@@ -260,7 +265,7 @@
                 int64_t bytes,
                 bool complete);
   void DidOpenFile(const OperationID id,
-                   const OpenFileCallback& callback,
+                   OpenFileCallback callback,
                    base::File file,
                    base::OnceClosure on_close_callback);
   void DidCreateSnapshot(
diff --git a/storage/browser/fileapi/file_writer_delegate.cc b/storage/browser/fileapi/file_writer_delegate.cc
index ad2b9b2..1813bc2 100644
--- a/storage/browser/fileapi/file_writer_delegate.cc
+++ b/storage/browser/fileapi/file_writer_delegate.cc
@@ -36,6 +36,7 @@
       bytes_written_(0),
       bytes_read_(0),
       io_buffer_(base::MakeRefCounted<net::IOBufferWithSize>(kReadBufSize)),
+      data_pipe_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
       weak_factory_(this) {}
 
 FileWriterDelegate::~FileWriterDelegate() = default;
@@ -66,9 +67,30 @@
   NOTREACHED();
 }
 
+void FileWriterDelegate::Start(mojo::ScopedDataPipeConsumerHandle data_pipe,
+                               const DelegateWriteCallback& write_callback) {
+  write_callback_ = write_callback;
+
+  if (!data_pipe) {
+    OnReadError(base::File::FILE_ERROR_FAILED);
+    return;
+  }
+
+  data_pipe_ = std::move(data_pipe);
+  data_pipe_watcher_.Watch(
+      data_pipe_.get(),
+      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+      MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+      base::BindRepeating(&FileWriterDelegate::OnDataPipeReady,
+                          weak_factory_.GetWeakPtr()));
+  data_pipe_watcher_.ArmOrNotify();
+}
+
 void FileWriterDelegate::Cancel() {
   // Destroy the reader and invalidate weak ptrs to prevent pending callbacks.
   blob_reader_ = nullptr;
+  data_pipe_watcher_.Cancel();
+  data_pipe_.reset();
   weak_factory_.InvalidateWeakPtrs();
 
   const int status = file_stream_writer_->Cancel(
@@ -104,24 +126,49 @@
 
 void FileWriterDelegate::Read() {
   bytes_written_ = 0;
-  BlobReader::Status status =
-      blob_reader_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_,
-                         base::BindOnce(&FileWriterDelegate::OnReadCompleted,
-                                        weak_factory_.GetWeakPtr()));
-  switch (status) {
-    case BlobReader::Status::NET_ERROR:
-      OnReadCompleted(blob_reader_->net_error());
-      return;
-    case BlobReader::Status::DONE:
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::BindOnce(&FileWriterDelegate::OnReadCompleted,
-                                    weak_factory_.GetWeakPtr(), bytes_read_));
-      return;
-    case BlobReader::Status::IO_PENDING:
-      // Do nothing.
-      return;
+  if (blob_reader_) {
+    BlobReader::Status status =
+        blob_reader_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_,
+                           base::BindOnce(&FileWriterDelegate::OnReadCompleted,
+                                          weak_factory_.GetWeakPtr()));
+    switch (status) {
+      case BlobReader::Status::NET_ERROR:
+        OnReadCompleted(blob_reader_->net_error());
+        return;
+      case BlobReader::Status::DONE:
+        base::ThreadTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE, base::BindOnce(&FileWriterDelegate::OnReadCompleted,
+                                      weak_factory_.GetWeakPtr(), bytes_read_));
+        return;
+      case BlobReader::Status::IO_PENDING:
+        // Do nothing.
+        return;
+    }
+    NOTREACHED();
+    return;
   }
+
+  DCHECK(data_pipe_);
+  uint32_t num_bytes = io_buffer_->size();
+  MojoResult result = data_pipe_->ReadData(io_buffer_->data(), &num_bytes,
+                                           MOJO_READ_DATA_FLAG_NONE);
+  if (result == MOJO_RESULT_SHOULD_WAIT) {
+    data_pipe_watcher_.ArmOrNotify();
+    return;
+  }
+  if (result == MOJO_RESULT_OK) {
+    bytes_read_ = num_bytes;
+    OnReadCompleted(bytes_read_);
+    return;
+  }
+  if (result == MOJO_RESULT_FAILED_PRECONDITION) {
+    // Pipe closed, done reading.
+    OnReadCompleted(0);
+    return;
+  }
+  // Some unknown error, this shouldn't happen.
   NOTREACHED();
+  OnReadError(base::File::FILE_ERROR_FAILED);
 }
 
 void FileWriterDelegate::OnDataReceived(int bytes_read) {
@@ -192,6 +239,8 @@
 
   // Destroy the reader and invalidate weak ptrs to prevent pending callbacks.
   blob_reader_.reset();
+  data_pipe_watcher_.Cancel();
+  data_pipe_.reset();
   weak_factory_.InvalidateWeakPtrs();
 
   if (writing_started_)
@@ -203,6 +252,8 @@
 void FileWriterDelegate::OnWriteError(base::File::Error error) {
   // Destroy the reader and invalidate weak ptrs to prevent pending callbacks.
   blob_reader_.reset();
+  data_pipe_watcher_.Cancel();
+  data_pipe_.reset();
   weak_factory_.InvalidateWeakPtrs();
 
   // Errors when writing are not recoverable, so don't bother flushing.
@@ -270,4 +321,10 @@
   write_callback_.Run(error, bytes_written, progress_status);
 }
 
+void FileWriterDelegate::OnDataPipeReady(
+    MojoResult result,
+    const mojo::HandleSignalsState& state) {
+  Read();
+}
+
 }  // namespace storage
diff --git a/storage/browser/fileapi/file_writer_delegate.h b/storage/browser/fileapi/file_writer_delegate.h
index 3671c3b..0782fb9e 100644
--- a/storage/browser/fileapi/file_writer_delegate.h
+++ b/storage/browser/fileapi/file_writer_delegate.h
@@ -14,6 +14,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/file_stream.h"
 #include "net/base/io_buffer.h"
 #include "storage/browser/blob/blob_reader.h"
@@ -44,6 +46,8 @@
 
   void Start(std::unique_ptr<BlobReader> blob_reader,
              const DelegateWriteCallback& write_callback);
+  void Start(mojo::ScopedDataPipeConsumerHandle data_pipe,
+             const DelegateWriteCallback& write_callback);
 
   // Cancels the current write operation.  This will synchronously or
   // asynchronously call the given write callback (which may result in
@@ -56,7 +60,6 @@
 
  private:
   void OnDidCalculateSize(int net_error);
-
   void Read();
   void OnReadCompleted(int bytes_read);
   void Write();
@@ -73,6 +76,9 @@
                  WriteProgressStatus progress_status,
                  int flush_error);
 
+  void OnDataPipeReady(MojoResult result,
+                       const mojo::HandleSignalsState& state);
+
   WriteProgressStatus GetCompletionStatusOnError() const;
 
   DelegateWriteCallback write_callback_;
@@ -87,8 +93,14 @@
   base::File::Error saved_read_error_ = base::File::FILE_OK;
   scoped_refptr<net::IOBufferWithSize> io_buffer_;
   scoped_refptr<net::DrainableIOBuffer> cursor_;
+
+  // Used when reading from a blob.
   std::unique_ptr<BlobReader> blob_reader_;
 
+  // Used when reading from a data pipe.
+  mojo::ScopedDataPipeConsumerHandle data_pipe_;
+  mojo::SimpleWatcher data_pipe_watcher_;
+
   base::WeakPtrFactory<FileWriterDelegate> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FileWriterDelegate);
diff --git a/storage/browser/fileapi/file_writer_impl.cc b/storage/browser/fileapi/file_writer_impl.cc
index 4f62f86a..19c2421 100644
--- a/storage/browser/fileapi/file_writer_impl.cc
+++ b/storage/browser/fileapi/file_writer_impl.cc
@@ -5,6 +5,7 @@
 #include "storage/browser/fileapi/file_writer_impl.h"
 
 #include "base/callback_helpers.h"
+#include "mojo/public/cpp/system/data_pipe_drainer.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_storage_context.h"
 
@@ -31,6 +32,25 @@
                      std::move(callback), position));
 }
 
+void FileWriterImpl::WriteStream(uint64_t position,
+                                 mojo::ScopedDataPipeConsumerHandle stream,
+                                 WriteStreamCallback callback) {
+  // FileSystemOperationRunner assumes that positions passed to Write are always
+  // valid, and will NOTREACHED() if that is not the case, so first check the
+  // size of the file to make sure the position passed in from the renderer is
+  // in fact valid.
+  // Of course the file could still change between checking its size and the
+  // write operation being started, but this is at least a lot better than the
+  // old implementation where the renderer only checks against how big it thinks
+  // the file currently is.
+  operation_runner_->GetMetadata(
+      url_, FileSystemOperation::GET_METADATA_FIELD_SIZE,
+      base::BindRepeating(&FileWriterImpl::DoWriteStreamWithFileInfo,
+                          base::Unretained(this),
+                          base::AdaptCallbackForRepeating(std::move(callback)),
+                          position, base::Passed(std::move(stream))));
+}
+
 void FileWriterImpl::Truncate(uint64_t length, TruncateCallback callback) {
   operation_runner_->Truncate(
       url_, length,
@@ -79,6 +99,23 @@
                           base::Owned(new WriteState())));
 }
 
+void FileWriterImpl::DoWriteStreamWithFileInfo(
+    WriteStreamCallback callback,
+    uint64_t position,
+    mojo::ScopedDataPipeConsumerHandle data_pipe,
+    base::File::Error result,
+    const base::File::Info& file_info) {
+  if (file_info.size < 0 || position > static_cast<uint64_t>(file_info.size)) {
+    std::move(callback).Run(base::File::FILE_ERROR_FAILED, 0);
+    return;
+  }
+  operation_runner_->Write(
+      url_, std::move(data_pipe), position,
+      base::BindRepeating(&FileWriterImpl::DidWrite, base::Unretained(this),
+                          base::AdaptCallbackForRepeating(std::move(callback)),
+                          base::Owned(new WriteState())));
+}
+
 void FileWriterImpl::DidWrite(WriteCallback callback,
                               WriteState* state,
                               base::File::Error result,
diff --git a/storage/browser/fileapi/file_writer_impl.h b/storage/browser/fileapi/file_writer_impl.h
index 5198134..3abdf1bae 100644
--- a/storage/browser/fileapi/file_writer_impl.h
+++ b/storage/browser/fileapi/file_writer_impl.h
@@ -26,6 +26,9 @@
   void Write(uint64_t position,
              blink::mojom::BlobPtr blob,
              WriteCallback callback) override;
+  void WriteStream(uint64_t position,
+                   mojo::ScopedDataPipeConsumerHandle stream,
+                   WriteStreamCallback callback) override;
   void Truncate(uint64_t length, TruncateCallback callback) override;
 
  private:
@@ -37,6 +40,11 @@
                            std::unique_ptr<BlobDataHandle> blob,
                            base::File::Error result,
                            const base::File::Info& file_info);
+  void DoWriteStreamWithFileInfo(WriteCallback callback,
+                                 uint64_t position,
+                                 mojo::ScopedDataPipeConsumerHandle data_pipe,
+                                 base::File::Error result,
+                                 const base::File::Info& file_info);
 
   struct WriteState {
     uint64_t bytes_written = 0;
diff --git a/storage/browser/fileapi/file_writer_impl_unittest.cc b/storage/browser/fileapi/file_writer_impl_unittest.cc
index 1593c0b..e2445c1 100644
--- a/storage/browser/fileapi/file_writer_impl_unittest.cc
+++ b/storage/browser/fileapi/file_writer_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/guid.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_task_environment.h"
+#include "mojo/public/cpp/system/string_data_pipe_producer.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
@@ -60,6 +61,25 @@
     return result;
   }
 
+  mojo::ScopedDataPipeConsumerHandle CreateStream(const std::string& contents) {
+    // Test with a relatively low capacity pipe to make sure it isn't all
+    // written/read in one go.
+    mojo::DataPipe pipe(16);
+    CHECK(pipe.producer_handle.is_valid());
+    auto producer = std::make_unique<mojo::StringDataPipeProducer>(
+        std::move(pipe.producer_handle));
+    auto* producer_raw = producer.get();
+    producer_raw->Write(
+        contents,
+        mojo::StringDataPipeProducer::AsyncWritingMode::
+            STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION,
+        base::BindOnce(
+            base::DoNothing::Once<std::unique_ptr<mojo::StringDataPipeProducer>,
+                                  MojoResult>(),
+            std::move(producer)));
+    return std::move(pipe.consumer_handle);
+  }
+
   std::string ReadFile(const FileSystemURL& url) {
     std::unique_ptr<FileStreamReader> reader =
         file_system_context_->CreateFileStreamReader(
@@ -80,9 +100,9 @@
     }
   }
 
-  base::File::Error WriteSync(uint64_t position,
-                              blink::mojom::BlobPtr blob,
-                              uint64_t* bytes_written_out) {
+  base::File::Error WriteBlobSync(uint64_t position,
+                                  blink::mojom::BlobPtr blob,
+                                  uint64_t* bytes_written_out) {
     base::RunLoop loop;
     base::File::Error result_out;
     writer_->Write(position, std::move(blob),
@@ -96,6 +116,24 @@
     return result_out;
   }
 
+  base::File::Error WriteStreamSync(
+      uint64_t position,
+      mojo::ScopedDataPipeConsumerHandle data_pipe,
+      uint64_t* bytes_written_out) {
+    base::RunLoop loop;
+    base::File::Error result_out;
+    writer_->WriteStream(
+        position, std::move(data_pipe),
+        base::BindLambdaForTesting(
+            [&](base::File::Error result, uint64_t bytes_written) {
+              result_out = result;
+              *bytes_written_out = bytes_written;
+              loop.Quit();
+            }));
+    loop.Run();
+    return result_out;
+  }
+
   base::File::Error TruncateSync(uint64_t length) {
     base::RunLoop loop;
     base::File::Error result_out;
@@ -108,6 +146,16 @@
     return result_out;
   }
 
+  virtual bool WriteUsingBlobs() { return true; }
+
+  base::File::Error WriteSync(uint64_t position,
+                              const std::string& contents,
+                              uint64_t* bytes_written_out) {
+    if (WriteUsingBlobs())
+      return WriteBlobSync(position, CreateBlob(contents), bytes_written_out);
+    return WriteStreamSync(position, CreateStream(contents), bytes_written_out);
+  }
+
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
@@ -120,55 +168,65 @@
   std::unique_ptr<FileWriterImpl> writer_;
 };
 
+class FileWriterImplWriteTest : public FileWriterImplTest,
+                                public testing::WithParamInterface<bool> {
+ public:
+  bool WriteUsingBlobs() override { return GetParam(); }
+};
+
+INSTANTIATE_TEST_CASE_P(FileWriterImplTest,
+                        FileWriterImplWriteTest,
+                        ::testing::Bool());
+
 TEST_F(FileWriterImplTest, WriteInvalidBlob) {
   blink::mojom::BlobPtr blob;
   MakeRequest(&blob);
 
   uint64_t bytes_written;
-  base::File::Error result = WriteSync(0, std::move(blob), &bytes_written);
+  base::File::Error result = WriteBlobSync(0, std::move(blob), &bytes_written);
   EXPECT_EQ(result, base::File::FILE_ERROR_FAILED);
   EXPECT_EQ(bytes_written, 0u);
 
   EXPECT_EQ("", ReadFile(test_url_));
 }
 
-TEST_F(FileWriterImplTest, WriteValidEmptyBlob) {
+TEST_P(FileWriterImplWriteTest, WriteValidEmptyString) {
   uint64_t bytes_written;
-  base::File::Error result = WriteSync(0, CreateBlob(""), &bytes_written);
+  base::File::Error result = WriteSync(0, "", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
   EXPECT_EQ(bytes_written, 0u);
 
   EXPECT_EQ("", ReadFile(test_url_));
 }
 
-TEST_F(FileWriterImplTest, WriteValidBlob) {
+TEST_P(FileWriterImplWriteTest, WriteValidNonEmpty) {
+  std::string test_data("abcdefghijklmnopqrstuvwxyz");
   uint64_t bytes_written;
-  base::File::Error result =
-      WriteSync(0, CreateBlob("1234567890"), &bytes_written);
+  base::File::Error result = WriteSync(0, test_data, &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
-  EXPECT_EQ(bytes_written, 10u);
+  EXPECT_EQ(bytes_written, test_data.size());
 
-  EXPECT_EQ("1234567890", ReadFile(test_url_));
+  EXPECT_EQ(test_data, ReadFile(test_url_));
 }
 
-TEST_F(FileWriterImplTest, WriteWithOffsetInFile) {
+TEST_P(FileWriterImplWriteTest, WriteWithOffsetInFile) {
   uint64_t bytes_written;
   base::File::Error result;
 
-  result = WriteSync(0, CreateBlob("1234567890"), &bytes_written);
+  result = WriteSync(0, "1234567890", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
   EXPECT_EQ(bytes_written, 10u);
 
-  result = WriteSync(4, CreateBlob("abc"), &bytes_written);
+  result = WriteSync(4, "abc", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
   EXPECT_EQ(bytes_written, 3u);
 
   EXPECT_EQ("1234abc890", ReadFile(test_url_));
 }
 
-TEST_F(FileWriterImplTest, WriteWithOffsetPastFile) {
+TEST_P(FileWriterImplWriteTest, WriteWithOffsetPastFile) {
   uint64_t bytes_written;
-  base::File::Error result = WriteSync(4, CreateBlob("abc"), &bytes_written);
+  base::File::Error result = WriteSync(4, "abc", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_ERROR_FAILED);
   EXPECT_EQ(bytes_written, 0u);
 
@@ -179,7 +237,7 @@
   uint64_t bytes_written;
   base::File::Error result;
 
-  result = WriteSync(0, CreateBlob("1234567890"), &bytes_written);
+  result = WriteSync(0, "1234567890", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
   EXPECT_EQ(bytes_written, 10u);
 
@@ -193,7 +251,7 @@
   uint64_t bytes_written;
   base::File::Error result;
 
-  result = WriteSync(0, CreateBlob("abc"), &bytes_written);
+  result = WriteSync(0, "abc", &bytes_written);
   EXPECT_EQ(result, base::File::FILE_OK);
   EXPECT_EQ(bytes_written, 3u);
 
diff --git a/storage/browser/fileapi/recursive_operation_delegate.cc b/storage/browser/fileapi/recursive_operation_delegate.cc
index c48faa1..1e8d6f9 100644
--- a/storage/browser/fileapi/recursive_operation_delegate.cc
+++ b/storage/browser/fileapi/recursive_operation_delegate.cc
@@ -33,12 +33,12 @@
 void RecursiveOperationDelegate::StartRecursiveOperation(
     const FileSystemURL& root,
     ErrorBehavior error_behavior,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(pending_directory_stack_.empty());
   DCHECK(pending_files_.empty());
 
   error_behavior_ = error_behavior;
-  callback_ = callback;
+  callback_ = std::move(callback);
 
   TryProcessFile(root);
 }
@@ -221,13 +221,13 @@
 
 void RecursiveOperationDelegate::Done(base::File::Error error) {
   if (canceled_ && error == base::File::FILE_OK) {
-    callback_.Run(base::File::FILE_ERROR_ABORT);
+    std::move(callback_).Run(base::File::FILE_ERROR_ABORT);
   } else {
     if (error_behavior_ == FileSystemOperation::ERROR_BEHAVIOR_SKIP &&
         failed_some_operations_)
-      callback_.Run(base::File::FILE_ERROR_FAILED);
+      std::move(callback_).Run(base::File::FILE_ERROR_FAILED);
     else
-      callback_.Run(error);
+      std::move(callback_).Run(error);
   }
 }
 
diff --git a/storage/browser/fileapi/recursive_operation_delegate.h b/storage/browser/fileapi/recursive_operation_delegate.h
index ae6156b..3fb79f7 100644
--- a/storage/browser/fileapi/recursive_operation_delegate.h
+++ b/storage/browser/fileapi/recursive_operation_delegate.h
@@ -43,18 +43,17 @@
   // This is called each time a file is found while recursively
   // performing an operation.
   virtual void ProcessFile(const FileSystemURL& url,
-                           const StatusCallback& callback) = 0;
+                           StatusCallback callback) = 0;
 
   // This is called each time a directory is found while recursively
   // performing an operation.
   virtual void ProcessDirectory(const FileSystemURL& url,
-                                const StatusCallback& callback) = 0;
-
+                                StatusCallback callback) = 0;
 
   // This is called each time after files and subdirectories for a
   // directory is processed while recursively performing an operation.
   virtual void PostProcessDirectory(const FileSystemURL& url,
-                                    const StatusCallback& callback) = 0;
+                                    StatusCallback callback) = 0;
 
   // Cancels the currently running operation.
   void Cancel();
@@ -111,7 +110,7 @@
   // under |root| is processed, or fired earlier when any suboperation fails.
   void StartRecursiveOperation(const FileSystemURL& root,
                                ErrorBehavior error_behavior,
-                               const StatusCallback& callback);
+                               StatusCallback callback);
 
   FileSystemContext* file_system_context() { return file_system_context_; }
   const FileSystemContext* file_system_context() const {
diff --git a/storage/browser/fileapi/recursive_operation_delegate_unittest.cc b/storage/browser/fileapi/recursive_operation_delegate_unittest.cc
index f890849..33aeaed 100644
--- a/storage/browser/fileapi/recursive_operation_delegate_unittest.cc
+++ b/storage/browser/fileapi/recursive_operation_delegate_unittest.cc
@@ -44,10 +44,10 @@
 
   LoggingRecursiveOperation(FileSystemContext* file_system_context,
                             const FileSystemURL& root,
-                            const StatusCallback& callback)
+                            StatusCallback callback)
       : storage::RecursiveOperationDelegate(file_system_context),
         root_(root),
-        callback_(callback),
+        callback_(std::move(callback)),
         weak_factory_(this) {}
   ~LoggingRecursiveOperation() override = default;
 
@@ -57,40 +57,41 @@
   void Run() override { NOTREACHED(); }
 
   void RunRecursively() override {
-    StartRecursiveOperation(
-        root_, storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT, callback_);
+    StartRecursiveOperation(root_,
+                            storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT,
+                            std::move(callback_));
   }
 
   void RunRecursivelyWithIgnoringError() {
-    StartRecursiveOperation(
-        root_, storage::FileSystemOperation::ERROR_BEHAVIOR_SKIP, callback_);
+    StartRecursiveOperation(root_,
+                            storage::FileSystemOperation::ERROR_BEHAVIOR_SKIP,
+                            std::move(callback_));
   }
 
-  void ProcessFile(const FileSystemURL& url,
-                   const StatusCallback& callback) override {
+  void ProcessFile(const FileSystemURL& url, StatusCallback callback) override {
     RecordLogEntry(LogEntry::PROCESS_FILE, url);
 
     if (error_url_.is_valid() && error_url_ == url) {
-      callback.Run(base::File::FILE_ERROR_FAILED);
+      std::move(callback).Run(base::File::FILE_ERROR_FAILED);
       return;
     }
 
     operation_runner()->GetMetadata(
         url, storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
-        base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
-                   weak_factory_.GetWeakPtr(), callback));
+        base::BindOnce(&LoggingRecursiveOperation::DidGetMetadata,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void ProcessDirectory(const FileSystemURL& url,
-                        const StatusCallback& callback) override {
+                        StatusCallback callback) override {
     RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
   }
 
   void PostProcessDirectory(const FileSystemURL& url,
-                            const StatusCallback& callback) override {
+                            StatusCallback callback) override {
     RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
   }
 
   void SetEntryToFail(const FileSystemURL& url) { error_url_ = url; }
@@ -103,17 +104,17 @@
     log_entries_.push_back(entry);
   }
 
-  void DidGetMetadata(const StatusCallback& callback,
+  void DidGetMetadata(StatusCallback callback,
                       base::File::Error result,
                       const base::File::Info& file_info) {
     if (result != base::File::FILE_OK) {
-      callback.Run(result);
+      std::move(callback).Run(result);
       return;
     }
 
-    callback.Run(file_info.is_directory ?
-                 base::File::FILE_ERROR_NOT_A_FILE :
-                 base::File::FILE_OK);
+    std::move(callback).Run(file_info.is_directory
+                                ? base::File::FILE_ERROR_NOT_A_FILE
+                                : base::File::FILE_OK);
   }
 
   FileSystemURL root_;
diff --git a/storage/browser/fileapi/remove_operation_delegate.cc b/storage/browser/fileapi/remove_operation_delegate.cc
index ba8b3a5fc..aaa5f75 100644
--- a/storage/browser/fileapi/remove_operation_delegate.cc
+++ b/storage/browser/fileapi/remove_operation_delegate.cc
@@ -13,71 +13,77 @@
 RemoveOperationDelegate::RemoveOperationDelegate(
     FileSystemContext* file_system_context,
     const FileSystemURL& url,
-    const StatusCallback& callback)
+    StatusCallback callback)
     : RecursiveOperationDelegate(file_system_context),
       url_(url),
-      callback_(callback),
-      weak_factory_(this) {
-}
+      callback_(std::move(callback)),
+      weak_factory_(this) {}
 
 RemoveOperationDelegate::~RemoveOperationDelegate() = default;
 
 void RemoveOperationDelegate::Run() {
-  operation_runner()->RemoveFile(url_, base::Bind(
-      &RemoveOperationDelegate::DidTryRemoveFile, weak_factory_.GetWeakPtr()));
+#if DCHECK_IS_ON()
+  DCHECK(!did_run_);
+  did_run_ = true;
+#endif
+  operation_runner()->RemoveFile(
+      url_, base::BindOnce(&RemoveOperationDelegate::DidTryRemoveFile,
+                           weak_factory_.GetWeakPtr()));
 }
 
 void RemoveOperationDelegate::RunRecursively() {
+#if DCHECK_IS_ON()
+  DCHECK(!did_run_);
+  did_run_ = true;
+#endif
   StartRecursiveOperation(url_, FileSystemOperation::ERROR_BEHAVIOR_ABORT,
-                          callback_);
+                          std::move(callback_));
 }
 
 void RemoveOperationDelegate::ProcessFile(const FileSystemURL& url,
-                                          const StatusCallback& callback) {
+                                          StatusCallback callback) {
   operation_runner()->RemoveFile(
-      url,
-      base::Bind(&RemoveOperationDelegate::DidRemoveFile,
-                 weak_factory_.GetWeakPtr(), callback));
+      url, base::BindOnce(&RemoveOperationDelegate::DidRemoveFile,
+                          weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void RemoveOperationDelegate::ProcessDirectory(const FileSystemURL& url,
-                                               const StatusCallback& callback) {
-  callback.Run(base::File::FILE_OK);
+                                               StatusCallback callback) {
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
-void RemoveOperationDelegate::PostProcessDirectory(
-    const FileSystemURL& url, const StatusCallback& callback) {
-  operation_runner()->RemoveDirectory(url, callback);
+void RemoveOperationDelegate::PostProcessDirectory(const FileSystemURL& url,
+                                                   StatusCallback callback) {
+  operation_runner()->RemoveDirectory(url, std::move(callback));
 }
 
 void RemoveOperationDelegate::DidTryRemoveFile(base::File::Error error) {
   if (error != base::File::FILE_ERROR_NOT_A_FILE &&
       error != base::File::FILE_ERROR_SECURITY) {
-    callback_.Run(error);
+    std::move(callback_).Run(error);
     return;
   }
   operation_runner()->RemoveDirectory(
-      url_,
-      base::Bind(&RemoveOperationDelegate::DidTryRemoveDirectory,
-                 weak_factory_.GetWeakPtr(), error));
+      url_, base::BindOnce(&RemoveOperationDelegate::DidTryRemoveDirectory,
+                           weak_factory_.GetWeakPtr(), error));
 }
 
 void RemoveOperationDelegate::DidTryRemoveDirectory(
     base::File::Error remove_file_error,
     base::File::Error remove_directory_error) {
-  callback_.Run(
-      remove_directory_error == base::File::FILE_ERROR_NOT_A_DIRECTORY ?
-      remove_file_error :
-      remove_directory_error);
+  std::move(callback_).Run(remove_directory_error ==
+                                   base::File::FILE_ERROR_NOT_A_DIRECTORY
+                               ? remove_file_error
+                               : remove_directory_error);
 }
 
-void RemoveOperationDelegate::DidRemoveFile(const StatusCallback& callback,
+void RemoveOperationDelegate::DidRemoveFile(StatusCallback callback,
                                             base::File::Error error) {
   if (error == base::File::FILE_ERROR_NOT_FOUND) {
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
     return;
   }
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 }  // namespace storage
diff --git a/storage/browser/fileapi/remove_operation_delegate.h b/storage/browser/fileapi/remove_operation_delegate.h
index 722776e..74319a5e 100644
--- a/storage/browser/fileapi/remove_operation_delegate.h
+++ b/storage/browser/fileapi/remove_operation_delegate.h
@@ -14,26 +14,27 @@
  public:
   RemoveOperationDelegate(FileSystemContext* file_system_context,
                           const FileSystemURL& url,
-                          const StatusCallback& callback);
+                          StatusCallback callback);
   ~RemoveOperationDelegate() override;
 
   // RecursiveOperationDelegate overrides:
   void Run() override;
   void RunRecursively() override;
-  void ProcessFile(const FileSystemURL& url,
-                   const StatusCallback& callback) override;
+  void ProcessFile(const FileSystemURL& url, StatusCallback callback) override;
   void ProcessDirectory(const FileSystemURL& url,
-                        const StatusCallback& callback) override;
+                        StatusCallback callback) override;
   void PostProcessDirectory(const FileSystemURL& url,
-                            const StatusCallback& callback) override;
+                            StatusCallback callback) override;
 
  private:
   void DidTryRemoveFile(base::File::Error error);
   void DidTryRemoveDirectory(base::File::Error remove_file_error,
                              base::File::Error remove_directory_error);
-  void DidRemoveFile(const StatusCallback& callback,
-                     base::File::Error error);
+  void DidRemoveFile(StatusCallback callback, base::File::Error error);
 
+#if DCHECK_IS_ON()
+  bool did_run_ = false;
+#endif
   FileSystemURL url_;
   StatusCallback callback_;
   base::WeakPtrFactory<RemoveOperationDelegate> weak_factory_;
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 961e624..0643ebab 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -353,7 +353,6 @@
 crbug.com/591099 fast/css/case-transform.html [ Failure ]
 crbug.com/835484 fast/css/focus-ring-recursive-continuations.html [ Failure ]
 crbug.com/591099 fast/css/getComputedStyle/computed-style-percentage-top-with-position-inline.html [ Failure ]
-crbug.com/835484 fast/css/outline-auto-empty-rects.html [ Failure ]
 crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
index 9919441..7bcf562b 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -56293,6 +56293,18 @@
      {}
     ]
    ],
+   "css/css-shapes/shape-outside/values/shape-outside-inset-010.html": [
+    [
+     "/css/css-shapes/shape-outside/values/shape-outside-inset-010.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square-only.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-shapes/spec-examples/shape-outside-001.html": [
     [
      "/css/css-shapes/spec-examples/shape-outside-001.html",
@@ -168235,6 +168247,31 @@
      {}
     ]
    ],
+   "referrer-policy/generic/multiple-headers-and-values.html.headers": [
+    [
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-combined.html.headers": [
+    [
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-one-invalid.html.headers": [
+    [
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-one-unknown-token.html.headers": [
+    [
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers.html.headers": [
+    [
+     {}
+    ]
+   ],
    "referrer-policy/generic/referrer-policy-test-case.js": [
     [
      {}
@@ -228288,6 +228325,14 @@
      }
     ]
    ],
+   "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach-svg.tentative.html": [
+    [
+     "/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach-svg.tentative.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
    "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html": [
     [
      "/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html",
@@ -250144,6 +250189,36 @@
      {}
     ]
    ],
+   "referrer-policy/generic/multiple-headers-and-values.html": [
+    [
+     "/referrer-policy/generic/multiple-headers-and-values.html",
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-combined.html": [
+    [
+     "/referrer-policy/generic/multiple-headers-combined.html",
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-one-invalid.html": [
+    [
+     "/referrer-policy/generic/multiple-headers-one-invalid.html",
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers-one-unknown-token.html": [
+    [
+     "/referrer-policy/generic/multiple-headers-one-unknown-token.html",
+     {}
+    ]
+   ],
+   "referrer-policy/generic/multiple-headers.html": [
+    [
+     "/referrer-policy/generic/multiple-headers.html",
+     {}
+    ]
+   ],
    "referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html": [
     [
      "/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html",
@@ -263754,6 +263829,12 @@
      {}
     ]
    ],
+   "trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html": [
+    [
+     "/trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html",
+     {}
+    ]
+   ],
    "trusted-types/Window-TrustedTypes.tentative.html": [
     [
      "/trusted-types/Window-TrustedTypes.tentative.html",
@@ -335847,6 +335928,10 @@
    "c131783d1ea3eb2992c30e54ca0d9b2c2943e188",
    "testharness"
   ],
+  "css/css-shapes/shape-outside/values/shape-outside-inset-010.html": [
+   "b82abea82a603f9a523fd8ee0a4d61cd0b7349c6",
+   "reftest"
+  ],
   "css/css-shapes/shape-outside/values/shape-outside-polygon-000.html": [
    "9ca058194a83149bc911727e8ac795cf261c7617",
    "testharness"
@@ -388287,6 +388372,10 @@
    "633b6a87d9da7784610769bb0041f0e10c27525e",
    "testharness"
   ],
+  "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach-svg.tentative.html": [
+   "0fc49e603606e9233d0b3ae59757aec149c8aaf2",
+   "testharness"
+  ],
   "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html": [
    "be680da619e8dd75f57d454268a528eba7d0d6c2",
    "testharness"
@@ -409291,6 +409380,46 @@
    "54963141b1916688fba7c8c1269a6f310efbb13a",
    "testharness"
   ],
+  "referrer-policy/generic/multiple-headers-and-values.html": [
+   "682199b917c37b9b11ef0eaa9897ebbfb50f5eb7",
+   "testharness"
+  ],
+  "referrer-policy/generic/multiple-headers-and-values.html.headers": [
+   "d1acc2f1d3cbce700865d96937e612c56e075166",
+   "support"
+  ],
+  "referrer-policy/generic/multiple-headers-combined.html": [
+   "ad02ae84bd7458c13e7621db7eadbd19a82ffbb5",
+   "testharness"
+  ],
+  "referrer-policy/generic/multiple-headers-combined.html.headers": [
+   "fc30a2a18627cf0cb485836f8d44f45beca510f2",
+   "support"
+  ],
+  "referrer-policy/generic/multiple-headers-one-invalid.html": [
+   "b1384b14a0e859d8fba0f564e6b9c51333339fc4",
+   "testharness"
+  ],
+  "referrer-policy/generic/multiple-headers-one-invalid.html.headers": [
+   "075219380414598f4535faa973fe69468fc7d37e",
+   "support"
+  ],
+  "referrer-policy/generic/multiple-headers-one-unknown-token.html": [
+   "3273c0dbedfea3c3917ff0e16f29ff2273f32352",
+   "testharness"
+  ],
+  "referrer-policy/generic/multiple-headers-one-unknown-token.html.headers": [
+   "46feffd705fe0e559b6f80a4a6b7f7bc46b26121",
+   "support"
+  ],
+  "referrer-policy/generic/multiple-headers.html": [
+   "5f6a749b4bd2003b1b434b070d436ac1a2d8d6e5",
+   "testharness"
+  ],
+  "referrer-policy/generic/multiple-headers.html.headers": [
+   "dd1dd853f2030bac5c036f693a7cf0eca6daba1a",
+   "support"
+  ],
   "referrer-policy/generic/referrer-policy-test-case.js": [
    "14ccd4e2de171e5c8b284e2ced552024b28d345d",
    "support"
@@ -424952,7 +425081,7 @@
    "testharness"
   ],
   "trusted-types/TrustedTypePolicyFactory-createPolicy-createXYZTests.tentative.html": [
-   "b20fcf2436eac17f9f558cab0c80d1eced6bb1be",
+   "a162d84cd820051d6c5868c35b58cd347b0026e5",
    "testharness"
   ],
   "trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-noNamesGiven.tentative.html": [
@@ -424971,6 +425100,10 @@
    "6d43e0bafc61f34c17d7d7b751bf69f12d035adf",
    "testharness"
   ],
+  "trusted-types/TrustedTypePolicyFactory-isXXX.tentative.html": [
+   "9b48fa7fede81b5d2e2c79d9fc115b56c759cb00",
+   "testharness"
+  ],
   "trusted-types/Window-TrustedTypes.tentative.html": [
    "8e20e492e6a8484e386d1a08f854bd9b162bd6be",
    "testharness"
@@ -425000,7 +425133,7 @@
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Element-setAttribute.tentative.html": [
-   "52e317083316435ec4b1dcc7331f1216c2a32d9a",
+   "3553f2b07685907a78368fced352867a1b3cc428",
    "testharness"
   ],
   "trusted-types/block-string-assignment-to-Element-setAttributeNS.tentative.html": [
@@ -427988,7 +428121,7 @@
    "testharness"
   ],
   "webaudio/the-audio-api/the-convolvernode-interface/convolver-setBuffer-already-has-value.html": [
-   "c8dbeb941bc48f4f3a92907cb140a29f96567057",
+   "ce2d5fcfe940b89b4ed04bc62a7be5f15131b64b",
    "testharness"
   ],
   "webaudio/the-audio-api/the-convolvernode-interface/convolver-setBuffer-null.html": [
diff --git "a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt" "b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
index 264a291..9a0eccc 100644
--- "a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
+++ "b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_exclude=\050Document_Window_HTML._\051-expected.txt"
@@ -1176,9 +1176,9 @@
 PASS SVGElement interface: attribute ontoggle
 PASS SVGElement interface: attribute onvolumechange
 PASS SVGElement interface: attribute onwaiting
-FAIL SVGElement interface: attribute oncopy assert_own_property: expected property "oncopy" missing
-FAIL SVGElement interface: attribute oncut assert_own_property: expected property "oncut" missing
-FAIL SVGElement interface: attribute onpaste assert_own_property: expected property "onpaste" missing
+PASS SVGElement interface: attribute oncopy
+PASS SVGElement interface: attribute oncut
+PASS SVGElement interface: attribute onpaste
 PASS SVGElement interface: attribute dataset
 PASS SVGElement interface: attribute nonce
 PASS SVGElement interface: attribute tabIndex
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt
index 26e4d07..e1b19c20 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https_include=HTML._-expected.txt
@@ -160,9 +160,9 @@
 PASS HTMLElement interface: attribute ontoggle
 PASS HTMLElement interface: attribute onvolumechange
 PASS HTMLElement interface: attribute onwaiting
-FAIL HTMLElement interface: attribute oncopy assert_own_property: expected property "oncopy" missing
-FAIL HTMLElement interface: attribute oncut assert_own_property: expected property "oncut" missing
-FAIL HTMLElement interface: attribute onpaste assert_own_property: expected property "onpaste" missing
+PASS HTMLElement interface: attribute oncopy
+PASS HTMLElement interface: attribute oncut
+PASS HTMLElement interface: attribute onpaste
 PASS HTMLElement interface: attribute contentEditable
 PASS HTMLElement interface: attribute isContentEditable
 PASS HTMLElement interface: attribute inputMode
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any-expected.txt
deleted file mode 100644
index 177eb92..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL It rethrows exceptions queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.serviceworker-expected.txt
deleted file mode 100644
index 177eb92..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL It rethrows exceptions queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.sharedworker-expected.txt
deleted file mode 100644
index 177eb92..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL It rethrows exceptions queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.worker-expected.txt
deleted file mode 100644
index 177eb92..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.worker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL It rethrows exceptions queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any-expected.txt
deleted file mode 100644
index d3c518a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL It exists and is a function assert_equals: expected "function" but got "undefined"
-FAIL It throws when given non-functions assert_throws: no argument function "() => queueMicrotask()" threw object "ReferenceError: queueMicrotask is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
-FAIL It calls the callback asynchronously queueMicrotask is not defined
-FAIL It does not pass any arguments queueMicrotask is not defined
-FAIL It interleaves with promises as expected queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.serviceworker-expected.txt
deleted file mode 100644
index d3c518a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL It exists and is a function assert_equals: expected "function" but got "undefined"
-FAIL It throws when given non-functions assert_throws: no argument function "() => queueMicrotask()" threw object "ReferenceError: queueMicrotask is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
-FAIL It calls the callback asynchronously queueMicrotask is not defined
-FAIL It does not pass any arguments queueMicrotask is not defined
-FAIL It interleaves with promises as expected queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.sharedworker-expected.txt
deleted file mode 100644
index d3c518a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL It exists and is a function assert_equals: expected "function" but got "undefined"
-FAIL It throws when given non-functions assert_throws: no argument function "() => queueMicrotask()" threw object "ReferenceError: queueMicrotask is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
-FAIL It calls the callback asynchronously queueMicrotask is not defined
-FAIL It does not pass any arguments queueMicrotask is not defined
-FAIL It interleaves with promises as expected queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.worker-expected.txt
deleted file mode 100644
index d3c518a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.any.worker-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL It exists and is a function assert_equals: expected "function" but got "undefined"
-FAIL It throws when given non-functions assert_throws: no argument function "() => queueMicrotask()" threw object "ReferenceError: queueMicrotask is not defined" ("ReferenceError") expected object "TypeError" ("TypeError")
-FAIL It calls the callback asynchronously queueMicrotask is not defined
-FAIL It does not pass any arguments queueMicrotask is not defined
-FAIL It interleaves with promises as expected queueMicrotask is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.window-expected.txt
deleted file mode 100644
index ea23e1e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/microtask-queuing/queue-microtask.window-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL It interleaves with MutationObservers as expected promise_test: Unhandled rejection with value: object "ReferenceError: queueMicrotask is not defined"
-FAIL It interleaves with MutationObservers and promises together as expected promise_test: Unhandled rejection with value: object "ReferenceError: queueMicrotask is not defined"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodDetails-attribute.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodDetails-attribute.https-expected.txt
deleted file mode 100644
index bc231cd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodDetails-attribute.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL Must have a methodDetails IDL attribute, which is initialized with to the methodName dictionary value PaymentMethodChangeEvent is not defined
-FAIL The methodDetails member defaults to null PaymentMethodChangeEvent is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodName-attribute.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodName-attribute.https-expected.txt
deleted file mode 100644
index 88f6565..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentMethodChangeEvent/methodName-attribute.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL Must have a methodName IDL attribute, which is initialized with to the methodName dictionary value PaymentMethodChangeEvent is not defined
-FAIL When no dictionary is passed, the methodName member defaults to the empty string PaymentMethodChangeEvent is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/idlharness.https.window-expected.txt
index a0fa472..ba43028c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/idlharness.https.window-expected.txt
@@ -16,7 +16,7 @@
 FAIL PaymentRequest interface: attribute onmerchantvalidation assert_true: The prototype object must have a property "onmerchantvalidation" expected true got false
 PASS PaymentRequest interface: attribute onshippingaddresschange
 PASS PaymentRequest interface: attribute onshippingoptionchange
-FAIL PaymentRequest interface: attribute onpaymentmethodchange assert_true: The prototype object must have a property "onpaymentmethodchange" expected true got false
+PASS PaymentRequest interface: attribute onpaymentmethodchange
 PASS PaymentRequest must be primary interface of paymentRequest
 PASS Stringification of paymentRequest
 PASS PaymentRequest interface: paymentRequest must inherit property "show([object Object])" with the proper type
@@ -30,7 +30,7 @@
 FAIL PaymentRequest interface: paymentRequest must inherit property "onmerchantvalidation" with the proper type assert_inherits: property "onmerchantvalidation" not found in prototype chain
 PASS PaymentRequest interface: paymentRequest must inherit property "onshippingaddresschange" with the proper type
 PASS PaymentRequest interface: paymentRequest must inherit property "onshippingoptionchange" with the proper type
-FAIL PaymentRequest interface: paymentRequest must inherit property "onpaymentmethodchange" with the proper type assert_inherits: property "onpaymentmethodchange" not found in prototype chain
+PASS PaymentRequest interface: paymentRequest must inherit property "onpaymentmethodchange" with the proper type
 PASS PaymentAddress interface: existence and properties of interface object
 PASS PaymentAddress interface object length
 PASS PaymentAddress interface object name
@@ -83,20 +83,20 @@
 FAIL MerchantValidationEvent interface: new MerchantValidationEvent("merchantvalidation") must inherit property "validationURL" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: MerchantValidationEvent is not defined"
 FAIL MerchantValidationEvent interface: new MerchantValidationEvent("merchantvalidation") must inherit property "complete([object Object])" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: MerchantValidationEvent is not defined"
 FAIL MerchantValidationEvent interface: calling complete([object Object]) on new MerchantValidationEvent("merchantvalidation") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: MerchantValidationEvent is not defined"
-FAIL PaymentMethodChangeEvent interface: existence and properties of interface object assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface object length assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface object name assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface: attribute methodName assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent interface: attribute methodDetails assert_own_property: self does not have own property "PaymentMethodChangeEvent" expected property "PaymentMethodChangeEvent" missing
-FAIL PaymentMethodChangeEvent must be primary interface of new PaymentMethodChangeEvent("paymentmethodchange") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
-FAIL Stringification of new PaymentMethodChangeEvent("paymentmethodchange") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
-FAIL PaymentMethodChangeEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "methodName" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
-FAIL PaymentMethodChangeEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "methodDetails" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
-FAIL PaymentRequestUpdateEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "updateWith([object Object])" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
-FAIL PaymentRequestUpdateEvent interface: calling updateWith([object Object]) on new PaymentMethodChangeEvent("paymentmethodchange") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: PaymentMethodChangeEvent is not defined"
+PASS PaymentMethodChangeEvent interface: existence and properties of interface object
+PASS PaymentMethodChangeEvent interface object length
+PASS PaymentMethodChangeEvent interface object name
+PASS PaymentMethodChangeEvent interface: existence and properties of interface prototype object
+PASS PaymentMethodChangeEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS PaymentMethodChangeEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS PaymentMethodChangeEvent interface: attribute methodName
+PASS PaymentMethodChangeEvent interface: attribute methodDetails
+PASS PaymentMethodChangeEvent must be primary interface of new PaymentMethodChangeEvent("paymentmethodchange")
+PASS Stringification of new PaymentMethodChangeEvent("paymentmethodchange")
+PASS PaymentMethodChangeEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "methodName" with the proper type
+PASS PaymentMethodChangeEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "methodDetails" with the proper type
+PASS PaymentRequestUpdateEvent interface: new PaymentMethodChangeEvent("paymentmethodchange") must inherit property "updateWith([object Object])" with the proper type
+PASS PaymentRequestUpdateEvent interface: calling updateWith([object Object]) on new PaymentMethodChangeEvent("paymentmethodchange") with too few arguments must throw TypeError
 PASS PaymentRequestUpdateEvent interface: existence and properties of interface object
 PASS PaymentRequestUpdateEvent interface object length
 PASS PaymentRequestUpdateEvent interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/onpaymentmenthodchange-attribute.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/onpaymentmenthodchange-attribute.https-expected.txt
deleted file mode 100644
index 5caf910..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/onpaymentmenthodchange-attribute.https-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-FAIL Must have a onpaymentmethodchange IDL attribute assert_idl_attribute: property "onpaymentmethodchange" not found in prototype chain
-FAIL onpaymentmethodchange attribute is a generic handler for "paymentmethodchange" assert_true: event did not fire expected true got false
-FAIL onpaymentmethodchange attribute is a handler for PaymentMethodChangeEvent PaymentMethodChangeEvent is not defined
-FAIL onpaymentmethodchange attribute and listeners both work PaymentMethodChangeEvent is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html
new file mode 100644
index 0000000..682199b9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Referrer Policy: multiple Referrer-Policy header and header values are allowed</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+
+    <script src="/referrer-policy/generic/common.js"></script>
+  </head>
+  <body>
+    <h1>Referrer Policy: multiple Referrer-Policy header and header values are allowed</h1>
+    <p></p>
+
+    <pre id="received_message">Running...</pre>
+
+    <script>
+      var test = async_test("Image uses the last recognized Referrer-Policy header value");
+      var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime();
+      var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+                urlPath;
+      queryImage(url, test.step_func(function(message) {
+        assert_equals(message.referrer, document.location.origin + "/");
+        test.done();
+      }), null, 'no-referrer', test);
+    </script>
+
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html.headers b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html.headers
new file mode 100644
index 0000000..d1acc2f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-and-values.html.headers
@@ -0,0 +1,2 @@
+Referrer-Policy: no-referrer
+Referrer-Policy: no-referrer,origin
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html
new file mode 100644
index 0000000..ad02ae84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Referrer Policy: multiple Referrer-Policy header values are allowed</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+
+    <script src="/referrer-policy/generic/common.js"></script>
+  </head>
+  <body>
+    <h1>Referrer Policy: multiple Referrer-Policy header values are allowed</h1>
+    <p></p>
+
+    <pre id="received_message">Running...</pre>
+
+    <script>
+      var test = async_test("Image uses the last recognized Referrer-Policy header value");
+      var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime();
+      var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+                urlPath;
+      queryImage(url, test.step_func(function(message) {
+        assert_equals(message.referrer, document.location.origin + "/");
+        test.done();
+      }), null, 'no-referrer', test);
+    </script>
+
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html.headers b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html.headers
new file mode 100644
index 0000000..fc30a2a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-combined.html.headers
@@ -0,0 +1 @@
+Referrer-Policy: no-referrer, origin
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html
new file mode 100644
index 0000000..b1384b1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Referrer Policy: multiple Referrer-Policy headers with one invalid</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+
+    <script src="/referrer-policy/generic/common.js"></script>
+  </head>
+  <body>
+    <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1>
+    <p></p>
+
+    <pre id="received_message">Running...</pre>
+
+    <script>
+      var test = async_test("Referrer policy header parsing fails if one header is invalid");
+      var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime();
+      var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+                urlPath;
+      queryImage(url, test.step_func(function(message) {
+        assert_equals(message.referrer, document.location.href);
+        test.done();
+      }), null, 'no-referrer', test);
+    </script>
+
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html.headers b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html.headers
new file mode 100644
index 0000000..0752193
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-invalid.html.headers
@@ -0,0 +1,2 @@
+Referrer-Policy: origin
+Referrer-Policy: origin no-referrer
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html
new file mode 100644
index 0000000..3273c0d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Referrer Policy: multiple Referrer-Policy headers with one invalid</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+
+    <script src="/referrer-policy/generic/common.js"></script>
+  </head>
+  <body>
+    <h1>Referrer Policy: multiple Referrer-Policy headers with one invalid</h1>
+    <p></p>
+
+    <pre id="received_message">Running...</pre>
+
+    <script>
+      var test = async_test("Image uses last recognized referrer policy token from Referrer-Policy headers");
+      var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime();
+      var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+                urlPath;
+      queryImage(url, test.step_func(function(message) {
+        assert_equals(message.referrer, document.location.origin + "/");
+        test.done();
+      }), null, 'no-referrer', test);
+    </script>
+
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers
new file mode 100644
index 0000000..46feffd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers-one-unknown-token.html.headers
@@ -0,0 +1,2 @@
+Referrer-Policy: no-referrer
+Referrer-Policy: origin,not-a-valid-token
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html
new file mode 100644
index 0000000..5f6a749
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Referrer Policy: multiple Referrer-Policy headers are allowed</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+
+    <script src="/referrer-policy/generic/common.js"></script>
+  </head>
+  <body>
+    <h1>Referrer Policy: multiple Referrer-Policy headers are allowed</h1>
+    <p></p>
+
+    <pre id="received_message">Running...</pre>
+
+    <script>
+      var test = async_test("Image uses the last recognized Referrer-Policy header");
+      var urlPath = '/referrer-policy/generic/subresource/image.py?cache_destroyer=' + (new Date()).getTime();
+      var url = location.protocol + "//www1." + location.hostname + ":" + location.port +
+                urlPath;
+      queryImage(url, test.step_func(function(message) {
+        assert_equals(message.referrer, document.location.origin + "/");
+        test.done();
+      }), null, 'no-referrer', test);
+    </script>
+
+    <div id="log"></div>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html.headers b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html.headers
new file mode 100644
index 0000000..dd1dd85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/referrer-policy/generic/multiple-headers.html.headers
@@ -0,0 +1,2 @@
+Referrer-Policy: no-referrer
+Referrer-Policy: origin
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt
deleted file mode 100644
index e60970b..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-FAIL oncut: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "oncut" expected true got false
-PASS oncut: the default value must be null
-PASS oncut: the content attribute must be compiled into a function as the corresponding property
-PASS oncut: the content attribute must execute when an event is dispatched
-FAIL oncopy: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "oncopy" expected true got false
-PASS oncopy: the default value must be null
-PASS oncopy: the content attribute must be compiled into a function as the corresponding property
-PASS oncopy: the content attribute must execute when an event is dispatched
-FAIL onpaste: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "onpaste" expected true got false
-PASS onpaste: the default value must be null
-PASS onpaste: the content attribute must be compiled into a function as the corresponding property
-PASS onpaste: the content attribute must execute when an event is dispatched
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html
index 5adee9f..c01883f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html
@@ -15,12 +15,6 @@
 //   makeIceTransport
 //   makeGatherAndStartTwoIceTransports
 
-function makeIceTransport(t) {
-  const iceTransport = new RTCIceTransport();
-  t.add_cleanup(() => iceTransport.stop());
-  return iceTransport;
-}
-
 test(() => {
   const iceTransport = new RTCIceTransport();
 }, 'RTCIceTransport constructor does not throw');
@@ -260,4 +254,49 @@
   ]);
 }, 'Two RTCIceTransports connect to each other');
 
+promise_test(async t => {
+  async function waitForConnectedThenSelectedCandidatePairChange(t, transport,
+      transportName) {
+    const watcher = new EventWatcher(t, localTransport,
+        [ 'statechange', 'selectedcandidatepairchange' ]);
+    await watcher.wait_for('statechange');
+    assert_equals(transport.state, 'connected',
+        `${transportName} state should be 'connected'`);
+    await watcher.wait_for('selectedcandidatepairchange');
+    const selectedCandidatePair = transport.getSelectedCandidatePair();
+    assert_not_equals(selectedCandidatePair, null,
+        `${transportName} selected candidate pair should not be null once ` +
+        'the selectedcandidatepairchange event fires');
+    assert_true(
+        transport.getLocalCandidates().some(
+            ({ candidate }) =>
+                candidate === selectedCandidatePair.local.candidate),
+        `${transportName} selected candidate pair local should be in the ` +
+        'list of local candidates');
+    assert_true(
+        transport.getRemoteCandidates().some(
+            ({ candidate }) =>
+                candidate === selectedCandidatePair.remote.candidate),
+        `${transportName} selected candidate pair local should be in the ` +
+        'list of remote candidates');
+  }
+  const [ localTransport, remoteTransport ] =
+      makeGatherAndStartTwoIceTransports(t);
+  await Promise.all([
+    waitForConnectedThenSelectedCandidatePairChange(t, localTransport,
+        'local transport'),
+    waitForConnectedThenSelectedCandidatePairChange(t, remoteTransport,
+        'remote transport'),
+  ]);
+}, 'Selected candidate pair changes once the RTCIceTransports connect.');
+
+promise_test(async t => {
+  const [ transport, ] = makeGatherAndStartTwoIceTransports(t);
+  const watcher = new EventWatcher(t, transport, 'selectedcandidatepairchange');
+  await watcher.wait_for('selectedcandidatepairchange');
+  transport.stop();
+  assert_equals(transport.getSelectedCandidatePair(), null);
+}, 'getSelectedCandidatePair() returns null once the RTCIceTransport is ' +
+    'stopped.');
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt
index 32d6255..2730fbb3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -338,7 +338,7 @@
 PASS RTCIceTransport interface: operation getRemoteParameters()
 PASS RTCIceTransport interface: attribute onstatechange
 PASS RTCIceTransport interface: attribute ongatheringstatechange
-FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_true: The prototype object must have a property "onselectedcandidatepairchange" expected true got false
+PASS RTCIceTransport interface: attribute onselectedcandidatepairchange
 FAIL RTCIceTransport must be primary interface of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
 FAIL Stringification of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
 FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "role" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/file-writer.html b/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/file-writer.html
index da351ff..3121a4c 100644
--- a/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/file-writer.html
+++ b/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/file-writer.html
@@ -69,4 +69,34 @@
     assert_equals(await getFileContents(handle), 'abc\0\0');
     assert_equals(await getFileSize(handle), 5);
 }, 'truncate() to grow a file');
+
+promise_test(async t => {
+    const handle = await createEmptyFile(t, 'write_stream');
+    const writer = await handle.createWriter();
+
+    const stream = new Response('1234567890').body;
+    await writer.write(0, stream);
+
+    assert_equals(await getFileContents(handle), '1234567890');
+    assert_equals(await getFileSize(handle), 10);
+}, 'write() called with a ReadableStream');
+
+promise_test(async t => {
+    const handle = await createEmptyFile(t, 'write_stream');
+    const handle_writer = await handle.createWriter();
+
+    const { writable, readable } = new TransformStream();
+    const write_result = handle_writer.write(0, readable);
+
+    const stream_writer = writable.getWriter();
+    stream_writer.write(new Uint8Array([0x73, 0x74, 0x72, 0x65, 0x61, 0x6D, 0x73, 0x21]));
+    garbageCollect();
+    stream_writer.write(new Uint8Array([0x21, 0x21]));
+    stream_writer.close();
+
+    await write_result;
+
+    assert_equals(await getFileContents(handle), 'streams!!!');
+    assert_equals(await getFileSize(handle), 10);
+}, 'Using a WritableStream writer to write');
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/resources/test-helpers.js b/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/resources/test-helpers.js
index be7e821..a41b448 100644
--- a/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/resources/test-helpers.js
+++ b/third_party/WebKit/LayoutTests/fast/filesystem/writable-files/resources/test-helpers.js
@@ -58,4 +58,20 @@
     const writer = await handle.createWriter();
     await writer.write(0, new Blob([contents]));
     return handle;
-}
\ No newline at end of file
+}
+
+function garbageCollect() {
+    if (self.gc) {
+        // Use --expose_gc for V8 (and Node.js)
+        // Exposed in SpiderMonkey shell as well
+        self.gc();
+    } else if (self.GCController) {
+        // Present in some WebKit development environments
+        GCController.collect();
+    } else {
+        /* eslint-disable no-console */
+        console.warn('Tests are running without the ability to do manual garbage collection. They will still work, but ' +
+            'coverage will be suboptimal.');
+        /* eslint-enable no-console */
+    }
+};
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message-expected.txt
new file mode 100644
index 0000000..8caa55bf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message-expected.txt
@@ -0,0 +1,3 @@
+Tests delivery of a push message to the service worker.
+Got message: push message
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message.js
new file mode 100644
index 0000000..447bf09
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/deliver-push-message.js
@@ -0,0 +1,26 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startURL(
+      'resources/push-message-service-worker.html',
+      `Tests delivery of a push message to the service worker.`);
+
+  async function waitForServiceWorkerActivation() {
+    let versions;
+    do {
+      const result = await dp.ServiceWorker.onceWorkerVersionUpdated();
+      versions = result.params.versions;
+    } while (!versions.length || versions[0].status !== "activated");
+    return versions[0].registrationId;
+  }
+
+  var registrationIdPromise = waitForServiceWorkerActivation();
+
+  await dp.Runtime.enable();
+  await dp.ServiceWorker.enable();
+  const registrationId = await registrationIdPromise;
+
+  dp.ServiceWorker.deliverPushMessage({origin: 'http://127.0.0.1:8000', registrationId: registrationId, data: 'push message'});
+  const message = await session.evaluateAsync('window.__messagePromise');
+  testRunner.log(`Got message: ${message}`);
+
+  testRunner.completeTest();
+});
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.html b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.html
new file mode 100644
index 0000000..b7aaed23
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Service worker for a push message test</title>
+<script>
+function installSW() {
+  navigator.serviceWorker.register('push-message-service-worker.js');
+}
+
+window.__messagePromise = new Promise(fulfill =>
+    navigator.serviceWorker.onmessage = e => fulfill(e.data));
+
+</script>
+</head>
+<body onload="installSW()"></body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.js
new file mode 100644
index 0000000..2043aaa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/service-worker/resources/push-message-service-worker.js
@@ -0,0 +1,5 @@
+self.addEventListener('push', async function (event) {
+  const clients = await self.clients.matchAll({includeUncontrolled: true});
+  for (const c of clients)
+    c.postMessage(event.data.text());
+});
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 15ab539..7df467d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3440,6 +3440,7 @@
     method createImageBitmap
     method fetch
     method importScripts
+    method queueMicrotask
     method requestAnimationFrame
     method setInterval
     method setTimeout
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index eb0a7fe5..d078b034 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 8e91e0cd..bb880ee9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index eb0a7fe5..d078b034 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
index 8348412..50b605b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index b41ad5ca..41cd85f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 0a97fc3e..6181f2d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
index 34b1906..5fbdafb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png
new file mode 100644
index 0000000..179d5f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
new file mode 100644
index 0000000..682d773
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
new file mode 100644
index 0000000..179d5f6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png
new file mode 100644
index 0000000..2dc0351
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
new file mode 100644
index 0000000..1958a56a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
new file mode 100644
index 0000000..45593ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
new file mode 100644
index 0000000..f98f8b4c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png
new file mode 100644
index 0000000..407a741
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png
new file mode 100644
index 0000000..f0509ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
new file mode 100644
index 0000000..028bbf5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index 179d5f6..7d3b5fbf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 682d773..1a31637 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index 179d5f6..7d3b5fbf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
index 2dc0351..b990a7a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index 1958a56a..bee225a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 45593ca..bc63788 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index f98f8b4c..d59c692 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
index 407a741..fb0d3ff 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
index f0509ba..a9da061b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 028bbf5..34e09e6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index 973cef02..caa9bdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 1071d5c1..837ef4c8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index 973cef02..caa9bdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
index c9491029..dbb25e1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index eb6d47e..835cae3 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 5a2db0f..9caedb9d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
index 3fb071a..cd7fed7 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 487cb801..a3f3f11 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -2439,6 +2439,7 @@
     method createImageBitmap
     method fetch
     method importScripts
+    method queueMicrotask
     method requestAnimationFrame
     method setInterval
     method setTimeout
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 1e3a8f7..1a63a79f 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -2484,6 +2484,7 @@
 [Worker]     method createImageBitmap
 [Worker]     method fetch
 [Worker]     method importScripts
+[Worker]     method queueMicrotask
 [Worker]     method requestAnimationFrame
 [Worker]     method setInterval
 [Worker]     method setTimeout
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 0b891678..6c4857b 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1524,11 +1524,8 @@
     getter onbeforecopy
     getter onbeforecut
     getter onbeforepaste
-    getter oncopy
-    getter oncut
     getter onfullscreenchange
     getter onfullscreenerror
-    getter onpaste
     getter onsearch
     getter onwebkitfullscreenchange
     getter onwebkitfullscreenerror
@@ -1602,11 +1599,8 @@
     setter onbeforecopy
     setter onbeforecut
     setter onbeforepaste
-    setter oncopy
-    setter oncut
     setter onfullscreenchange
     setter onfullscreenerror
-    setter onpaste
     setter onsearch
     setter onwebkitfullscreenchange
     setter onwebkitfullscreenerror
@@ -2107,7 +2101,9 @@
     getter onclick
     getter onclose
     getter oncontextmenu
+    getter oncopy
     getter oncuechange
+    getter oncut
     getter ondblclick
     getter ondrag
     getter ondragend
@@ -2140,6 +2136,7 @@
     getter onmouseover
     getter onmouseup
     getter onmousewheel
+    getter onpaste
     getter onpause
     getter onplay
     getter onplaying
@@ -2203,7 +2200,9 @@
     setter onclick
     setter onclose
     setter oncontextmenu
+    setter oncopy
     setter oncuechange
+    setter oncut
     setter ondblclick
     setter ondrag
     setter ondragend
@@ -2236,6 +2235,7 @@
     setter onmouseover
     setter onmouseup
     setter onmousewheel
+    setter onpaste
     setter onpause
     setter onplay
     setter onplaying
@@ -5232,7 +5232,9 @@
     getter onclick
     getter onclose
     getter oncontextmenu
+    getter oncopy
     getter oncuechange
+    getter oncut
     getter ondblclick
     getter ondrag
     getter ondragend
@@ -5265,6 +5267,7 @@
     getter onmouseover
     getter onmouseup
     getter onmousewheel
+    getter onpaste
     getter onpause
     getter onplay
     getter onplaying
@@ -5316,7 +5319,9 @@
     setter onclick
     setter onclose
     setter oncontextmenu
+    setter oncopy
     setter oncuechange
+    setter oncut
     setter ondblclick
     setter ondrag
     setter ondragend
@@ -5349,6 +5354,7 @@
     setter onmouseover
     setter onmouseup
     setter onmousewheel
+    setter onpaste
     setter onpause
     setter onplay
     setter onplaying
@@ -8722,6 +8728,7 @@
     method postMessage
     method print
     method prompt
+    method queueMicrotask
     method releaseEvents
     method requestAnimationFrame
     method requestIdleCallback
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index 36c463f3..f342eb7 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -2371,6 +2371,7 @@
 [Worker]     method createImageBitmap
 [Worker]     method fetch
 [Worker]     method importScripts
+[Worker]     method queueMicrotask
 [Worker]     method requestAnimationFrame
 [Worker]     method setInterval
 [Worker]     method setTimeout
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt
index e62ace20..3f29529e 100644
--- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -338,7 +338,7 @@
 PASS RTCIceTransport interface: operation getRemoteParameters()
 PASS RTCIceTransport interface: attribute onstatechange
 PASS RTCIceTransport interface: attribute ongatheringstatechange
-FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_true: The prototype object must have a property "onselectedcandidatepairchange" expected true got false
+PASS RTCIceTransport interface: attribute onselectedcandidatepairchange
 FAIL RTCIceTransport must be primary interface of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
 FAIL Stringification of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
 FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "role" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 3102855e8..503279c 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -3467,6 +3467,7 @@
 [Worker]     method createImageBitmap
 [Worker]     method fetch
 [Worker]     method importScripts
+[Worker]     method queueMicrotask
 [Worker]     method requestAnimationFrame
 [Worker]     method setInterval
 [Worker]     method setTimeout
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 1f829ea..c0dab6f1 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -1906,11 +1906,8 @@
     getter onbeforecopy
     getter onbeforecut
     getter onbeforepaste
-    getter oncopy
-    getter oncut
     getter onfullscreenchange
     getter onfullscreenerror
-    getter onpaste
     getter onsearch
     getter onwebkitfullscreenchange
     getter onwebkitfullscreenerror
@@ -2028,11 +2025,8 @@
     setter onbeforecopy
     setter onbeforecut
     setter onbeforepaste
-    setter oncopy
-    setter oncut
     setter onfullscreenchange
     setter onfullscreenerror
-    setter onpaste
     setter onsearch
     setter onwebkitfullscreenchange
     setter onwebkitfullscreenerror
@@ -2575,7 +2569,9 @@
     getter onclick
     getter onclose
     getter oncontextmenu
+    getter oncopy
     getter oncuechange
+    getter oncut
     getter ondblclick
     getter ondrag
     getter ondragend
@@ -2609,6 +2605,7 @@
     getter onmouseover
     getter onmouseup
     getter onmousewheel
+    getter onpaste
     getter onpause
     getter onplay
     getter onplaying
@@ -2675,7 +2672,9 @@
     setter onclick
     setter onclose
     setter oncontextmenu
+    setter oncopy
     setter oncuechange
+    setter oncut
     setter ondblclick
     setter ondrag
     setter ondragend
@@ -2709,6 +2708,7 @@
     setter onmouseover
     setter onmouseup
     setter onmousewheel
+    setter onpaste
     setter onpause
     setter onplay
     setter onplaying
@@ -5068,9 +5068,15 @@
     getter userHint
     method constructor
     setter userHint
+interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent
+    attribute @@toStringTag
+    getter methodDetails
+    getter methodName
+    method constructor
 interface PaymentRequest : EventTarget
     attribute @@toStringTag
     getter id
+    getter onpaymentmethodchange
     getter onshippingaddresschange
     getter onshippingoptionchange
     getter shippingAddress
@@ -5080,6 +5086,7 @@
     method canMakePayment
     method constructor
     method show
+    setter onpaymentmethodchange
     setter onshippingaddresschange
     setter onshippingoptionchange
 interface PaymentRequestUpdateEvent : Event
@@ -5489,6 +5496,7 @@
     getter gatheringState
     getter ongatheringstatechange
     getter onicecandidate
+    getter onselectedcandidatepairchange
     getter onstatechange
     getter role
     getter state
@@ -5504,6 +5512,7 @@
     method stop
     setter ongatheringstatechange
     setter onicecandidate
+    setter onselectedcandidatepairchange
     setter onstatechange
 interface RTCPeerConnection : EventTarget
     static method generateCertificate
@@ -5937,7 +5946,9 @@
     getter onclick
     getter onclose
     getter oncontextmenu
+    getter oncopy
     getter oncuechange
+    getter oncut
     getter ondblclick
     getter ondrag
     getter ondragend
@@ -5971,6 +5982,7 @@
     getter onmouseover
     getter onmouseup
     getter onmousewheel
+    getter onpaste
     getter onpause
     getter onplay
     getter onplaying
@@ -6024,7 +6036,9 @@
     setter onclick
     setter onclose
     setter oncontextmenu
+    setter oncopy
     setter oncuechange
+    setter oncut
     setter ondblclick
     setter ondrag
     setter ondragend
@@ -6058,6 +6072,7 @@
     setter onmouseover
     setter onmouseup
     setter onmousewheel
+    setter onpaste
     setter onpause
     setter onplay
     setter onplaying
@@ -10671,6 +10686,7 @@
     method postMessage
     method print
     method prompt
+    method queueMicrotask
     method releaseEvents
     method requestAnimationFrame
     method requestIdleCallback
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index e47ddc02..a26bbaf 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3339,6 +3339,7 @@
 [Worker]     method createImageBitmap
 [Worker]     method fetch
 [Worker]     method importScripts
+[Worker]     method queueMicrotask
 [Worker]     method requestAnimationFrame
 [Worker]     method setInterval
 [Worker]     method setTimeout
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index e322d6f..8a515fed 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -82,6 +82,9 @@
 const base::Feature kWritableFilesAPI{"WritableFilesAPI",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kMixedContentAutoupgrade{"AutoupgradeMixedContent",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 const char kAutofillPreviewStyleExperimentBgColorParameterName[] = "bg_color";
 
 const char kAutofillPreviewStyleExperimentColorParameterName[] = "color";
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 4ddbeca..9ac6f74 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -28,6 +28,7 @@
 BLINK_COMMON_EXPORT extern const base::Feature kStopInBackground;
 BLINK_COMMON_EXPORT extern const base::Feature kStopNonTimersInBackground;
 BLINK_COMMON_EXPORT extern const base::Feature kWritableFilesAPI;
+BLINK_COMMON_EXPORT extern const base::Feature kMixedContentAutoupgrade;
 
 BLINK_COMMON_EXPORT extern const char
     kAutofillPreviewStyleExperimentBgColorParameterName[];
diff --git a/third_party/blink/public/mojom/filesystem/file_writer.mojom b/third_party/blink/public/mojom/filesystem/file_writer.mojom
index 14ec83e..0f73135 100644
--- a/third_party/blink/public/mojom/filesystem/file_writer.mojom
+++ b/third_party/blink/public/mojom/filesystem/file_writer.mojom
@@ -17,6 +17,14 @@
   Write(uint64 position, Blob blob) => (mojo_base.mojom.FileError result,
                                         uint64 bytes_written);
 
+  // Write data from |stream| to the given |position| in the file being written
+  // to. Returns whether the operation succeeded and if so how many bytes were
+  // written.
+  // TODO(mek): This might need some way of reporting progress events back to
+  // the renderer.
+  WriteStream(uint64 position, handle<data_pipe_consumer> stream) =>
+        (mojo_base.mojom.FileError result, uint64 bytes_written);
+
   // Changes the length of the file to be |length|. If |length| is larger than
   // the current size of the file, the file will be extended, and the extended
   // part is filled with null bytes.
diff --git a/third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom b/third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom
index f8f8b55e..a90db3a 100644
--- a/third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom
+++ b/third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom
@@ -9,6 +9,16 @@
 import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom";
 
+// This struct contains timing information recorded in the context of a
+// controller service worker.
+struct ServiceWorkerFetchEventTiming {
+  // Recorded just before a fetch event is dispatched.
+  mojo_base.mojom.TimeTicks dispatch_event_time;
+  // Recorded when respondWith()'s promise is settled, or the fetch event
+  // dispatch finished without respondWith() being called.
+  mojo_base.mojom.TimeTicks respond_with_settled_time;
+};
+
 // Callback interface which is passed to a controller service worker through
 // DispatchFetchEvent (either via ServiceWorker or via ControllerServiceWorker
 // interface).
@@ -16,13 +26,13 @@
 interface ServiceWorkerFetchResponseCallback {
   // Responds to the request with |response|.
   OnResponse(FetchAPIResponse response,
-             mojo_base.mojom.TimeTicks dispatch_event_time);
+             ServiceWorkerFetchEventTiming timing);
   // Responds to the request with |response|. |response.blob| should be empty
   // since the body is provided as a stream.
   OnResponseStream(FetchAPIResponse response,
                    ServiceWorkerStreamHandle body_as_stream,
-                   mojo_base.mojom.TimeTicks dispatch_event_time);
+                   ServiceWorkerFetchEventTiming timing);
   // Provides no response to the request. The callee should fall back to the
   // network.
-  OnFallback(mojo_base.mojom.TimeTicks dispatch_event_time);
+  OnFallback(ServiceWorkerFetchEventTiming timing);
 };
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom
index 9d9007f..a551994 100644
--- a/third_party/blink/public/platform/web_feature.mojom
+++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2005,6 +2005,8 @@
   kBackgroundFetchRegistrationAbort = 2552,
   kBackgroundFetchRegistrationMatch = 2553,
   kBackgroundFetchRegistrationMatchAll = 2554,
+  kV8AtomicsNotify = 2555,
+  kV8AtomicsWake = 2556,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
index 80c71c1..a99c132 100644
--- a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
+++ b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
@@ -184,18 +184,21 @@
   // native fetch.
   virtual void RespondToFetchEventWithNoResponse(
       int fetch_event_id,
-      base::TimeTicks event_dispatch_time) {}
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time) {}
   // Responds to the fetch event with |response|.
   virtual void RespondToFetchEvent(int fetch_event_id,
                                    const WebServiceWorkerResponse& response,
-                                   base::TimeTicks event_dispatch_time) {}
+                                   base::TimeTicks event_dispatch_time,
+                                   base::TimeTicks respond_with_settled_time) {}
   // Responds to the fetch event with |response|, where body is
   // |body_as_stream|.
   virtual void RespondToFetchEventWithResponseStream(
       int fetch_event_id,
       const WebServiceWorkerResponse& response,
       WebServiceWorkerStreamHandle* body_as_stream,
-      base::TimeTicks event_dispatch_time) {}
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time) {}
   virtual void DidHandleFetchEvent(int fetch_event_id,
                                    mojom::ServiceWorkerEventStatus,
                                    base::TimeTicks event_dispatch_time) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
index 170c063..e615bd3 100644
--- a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
+++ b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
@@ -157,6 +157,12 @@
     case v8::Isolate::kWasmThreadOpcodes:
       blink_feature = WebFeature::kV8WasmThreadOpcodes;
       break;
+    case v8::Isolate::kAtomicsNotify:
+      blink_feature = WebFeature::kV8AtomicsNotify;
+      break;
+    case v8::Isolate::kAtomicsWake:
+      blink_feature = WebFeature::kV8AtomicsWake;
+      break;
     default:
       // This can happen if V8 has added counters that this version of Blink
       // does not know about. It's harmless.
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 4ad56d0..335bd84 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -508,6 +508,7 @@
                     "dom/accessibility_role.idl",
                     "dom/aria_attributes.idl",
                     "dom/child_node.idl",
+                    "dom/document_and_element_event_handlers.idl",
                     "dom/document_or_shadow_root.idl",
                     "dom/global_event_handlers.idl",
                     "dom/nonced_element.idl",
diff --git a/third_party/blink/renderer/core/dom/BUILD.gn b/third_party/blink/renderer/core/dom/BUILD.gn
index d1bf2dc..aa22eeb9 100644
--- a/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/third_party/blink/renderer/core/dom/BUILD.gn
@@ -51,6 +51,7 @@
     "distributed_nodes.h",
     "document.cc",
     "document.h",
+    "document_and_element_event_handlers.h",
     "document_encoding_data.cc",
     "document_encoding_data.h",
     "document_fragment.cc",
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 92bd91d..ae31cd0 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -300,10 +300,7 @@
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(freeze);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(pointerlockchange);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(pointerlockerror);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
diff --git a/third_party/blink/renderer/core/dom/document.idl b/third_party/blink/renderer/core/dom/document.idl
index 80025e0..b822ea1 100644
--- a/third_party/blink/renderer/core/dom/document.idl
+++ b/third_party/blink/renderer/core/dom/document.idl
@@ -209,10 +209,7 @@
     attribute EventHandler onbeforecopy;
     attribute EventHandler onbeforecut;
     attribute EventHandler onbeforepaste;
-    attribute EventHandler oncopy;
-    attribute EventHandler oncut;
     [RuntimeEnabled=PageLifecycle] attribute EventHandler onfreeze;
-    attribute EventHandler onpaste;
     [RuntimeEnabled=PageLifecycle] attribute EventHandler onresume;
     attribute EventHandler onsearch;
     [RuntimeEnabled=ExperimentalContentSecurityPolicyFeatures] attribute EventHandler onsecuritypolicyviolation;
@@ -220,6 +217,7 @@
 };
 
 Document implements GlobalEventHandlers;
+Document implements DocumentAndElementEventHandlers;
 Document implements ParentNode;
 Document implements NonElementParentNode;
 Document implements DocumentOrShadowRoot;
diff --git a/third_party/blink/renderer/core/dom/document_and_element_event_handlers.h b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.h
new file mode 100644
index 0000000..e09780b
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.h
@@ -0,0 +1,24 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_AND_ELEMENT_EVENT_HANDLERS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_AND_ELEMENT_EVENT_HANDLERS_H_
+
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class DocumentAndElementEventHandlers {
+  STATIC_ONLY(DocumentAndElementEventHandlers);
+
+ public:
+  DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(copy);
+  DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(cut);
+  DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(paste);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_AND_ELEMENT_EVENT_HANDLERS_H_
diff --git a/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl
new file mode 100644
index 0000000..c1b1362a
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/document_and_element_event_handlers.idl
@@ -0,0 +1,14 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#documentandelementeventhandlers
+
+[
+    LegacyTreatAsPartialInterface,
+    NoInterfaceObject // Always used on target of 'implements'
+]  interface DocumentAndElementEventHandlers {
+  attribute EventHandler oncopy;
+  attribute EventHandler oncut;
+  attribute EventHandler onpaste;
+};
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index a75da2d..f2f4183d 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -161,9 +161,6 @@
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
-  DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
 
   bool hasAttribute(const QualifiedName&) const;
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl
index 49e0f61..fc5c899 100644
--- a/third_party/blink/renderer/core/dom/element.idl
+++ b/third_party/blink/renderer/core/dom/element.idl
@@ -141,9 +141,6 @@
     attribute EventHandler onbeforecopy;
     attribute EventHandler onbeforecut;
     attribute EventHandler onbeforepaste;
-    attribute EventHandler oncopy;
-    attribute EventHandler oncut;
-    attribute EventHandler onpaste;
     attribute EventHandler onsearch;
 };
 
diff --git a/third_party/blink/renderer/core/editing/compute_layer_selection.cc b/third_party/blink/renderer/core/editing/compute_layer_selection.cc
index 4f69de9c..8efda4d 100644
--- a/third_party/blink/renderer/core/editing/compute_layer_selection.cc
+++ b/third_party/blink/renderer/core/editing/compute_layer_selection.cc
@@ -246,10 +246,8 @@
   if (!frame_selection.IsHandleVisible() || frame_selection.IsHidden())
     return {};
 
-  // TODO(yoichio): Compute SelectionInDOMTree w/o VS canonicalization.
-  // crbug.com/789870 for detail.
   const SelectionInDOMTree& selection =
-      frame_selection.ComputeVisibleSelectionInDOMTree().AsSelection();
+      frame_selection.ComputeLayoutSelection();
   if (selection.IsNone())
     return {};
   // Non-editable caret selections lack any kind of UI affordance, and
diff --git a/third_party/blink/renderer/core/editing/frame_selection.h b/third_party/blink/renderer/core/editing/frame_selection.h
index 7e9257f..e97b214 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/third_party/blink/renderer/core/editing/frame_selection.h
@@ -140,6 +140,9 @@
   void MoveCaretSelection(const IntPoint&);
 
   VisibleSelection ComputeVisibleSelectionInDOMTree() const;
+  // TODO(yoichio): Replace ComputeVisibleSelectionInDOMTree with
+  // ComputeLayoutSelection. See crbug.com/789870 for detail and tracking.
+  SelectionInDOMTree ComputeLayoutSelection() const;
   VisibleSelectionInFlatTree ComputeVisibleSelectionInFlatTree() const;
 
   // TODO(editing-dev): We should replace
diff --git a/third_party/blink/renderer/core/editing/layout_selection.cc b/third_party/blink/renderer/core/editing/layout_selection.cc
index 78a04405..2fe2e22 100644
--- a/third_party/blink/renderer/core/editing/layout_selection.cc
+++ b/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -784,14 +784,18 @@
   has_pending_selection_ = true;
 }
 
+static void AssertLayoutClean(Document* document) {
+  DCHECK(!document->NeedsLayoutTreeUpdate());
+  DCHECK_GE(document->Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
+  DCHECK(IsFlatTreeClean(*document));
+}
+
 void LayoutSelection::Commit() {
   if (!HasPendingSelection())
     return;
   has_pending_selection_ = false;
 
-  DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate());
-  DCHECK_GE(frame_selection_->GetDocument().Lifecycle().GetState(),
-            DocumentLifecycle::kLayoutClean);
+  AssertLayoutClean(&frame_selection_->GetDocument());
   DocumentLifecycle::DisallowTransitionScope disallow_transition(
       frame_selection_->GetDocument().Lifecycle());
 
@@ -875,6 +879,43 @@
                                       &visitor);
 }
 
+SelectionInDOMTree LayoutSelection::ComputeLayoutSelection() const {
+  AssertLayoutClean(&frame_selection_->GetDocument());
+  DCHECK(!has_pending_selection_);
+
+  const SelectionInDOMTree& raw_selection =
+      frame_selection_->GetSelectionInDOMTree();
+  if (raw_selection.IsNone() || raw_selection.IsCaret())
+    return raw_selection;
+
+  if (paint_range_->IsNull())
+    return {};
+  paint_range_->AssertSanity();
+  DCHECK(paint_range_->start_node);
+  DCHECK(paint_range_->end_node);
+  const Position& raw_start = raw_selection.ComputeStartPosition();
+  const Position& raw_end = raw_selection.ComputeEndPosition();
+  const Position& start = (paint_range_->start_node->IsTextNode() &&
+                           paint_range_->start_node == raw_start.AnchorNode())
+                              ? raw_start
+                              : Position::BeforeNode(*paint_range_->start_node);
+  const Position& end = (paint_range_->end_node->IsTextNode() &&
+                         paint_range_->end_node == raw_end.AnchorNode())
+                            ? raw_end
+                            : Position::AfterNode(*paint_range_->end_node);
+  const EphemeralRange range = {start, end};
+  SelectionInDOMTree::Builder builder;
+  if (raw_selection.IsBaseFirst())
+    builder.SetAsForwardSelection(range);
+  else
+    builder.SetAsBackwardSelection(range);
+  return builder.Build();
+}
+
+SelectionInDOMTree FrameSelection::ComputeLayoutSelection() const {
+  return layout_selection_->ComputeLayoutSelection();
+}
+
 void LayoutSelection::Trace(blink::Visitor* visitor) {
   visitor->Trace(frame_selection_);
   visitor->Trace(paint_range_);
diff --git a/third_party/blink/renderer/core/editing/layout_selection.h b/third_party/blink/renderer/core/editing/layout_selection.h
index c5790f8e..08deb8e1 100644
--- a/third_party/blink/renderer/core/editing/layout_selection.h
+++ b/third_party/blink/renderer/core/editing/layout_selection.h
@@ -48,6 +48,7 @@
   void SetHasPendingSelection();
   void Commit();
 
+  SelectionInDOMTree ComputeLayoutSelection() const;
   IntRect AbsoluteSelectionBounds();
   void InvalidatePaintForSelection();
 
diff --git a/third_party/blink/renderer/core/editing/layout_selection_test.cc b/third_party/blink/renderer/core/editing/layout_selection_test.cc
index b302133..8eadb3fb 100644
--- a/third_party/blink/renderer/core/editing/layout_selection_test.cc
+++ b/third_party/blink/renderer/core/editing/layout_selection_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/editing/selection_template.h"
 #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
+#include "third_party/blink/renderer/core/editing/visible_selection.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
@@ -137,6 +138,14 @@
     PrintDOMTreeInternal(Selection(), stream, *GetDocument().body(), 0u);
     return stream.str();
   }
+
+  std::string ComputeLayoutSelection(const std::string& selection_text) {
+    Selection().SetSelection(SetSelectionTextToBody(selection_text),
+                             SetSelectionOptions());
+    Selection().CommitAppearanceIfNeeded();
+    const SelectionInDOMTree& result = Selection().ComputeLayoutSelection();
+    return GetSelectionTextFromBody(result);
+  }
 };
 
 TEST_F(LayoutSelectionTest, TraverseLayoutObject) {
@@ -897,6 +906,55 @@
       DumpSelectionInfo());
 }
 
+// Confirm LayoutSelection adjustment.
+#define EXPECT_EQ_LS(input, expect) \
+  EXPECT_EQ(ComputeLayoutSelection(input), expect)
+
+TEST_F(LayoutSelectionTest, ComputeLayoutSelectionBasic) {
+  EXPECT_EQ_LS("fo^o<br>ba|r", "fo^o<br>ba|r");
+  EXPECT_EQ_LS("fo|o<br>ba^r", "fo|o<br>ba^r");
+  EXPECT_EQ_LS("foo<!--|--><br><!--^-->bar", "foo|<br>^bar");
+}
+
+TEST_F(LayoutSelectionTest, ComputeLayoutSelectionBR) {
+  EXPECT_EQ_LS("fo^o<br>|", "fo^o<br>|");
+  EXPECT_EQ_LS("fo^o<br><br>|", "fo^o<br><br>|");
+  EXPECT_EQ_LS("foo<br>^<br>|", "foo<br>^<br>|");
+  EXPECT_EQ_LS("foo<!--|--><br>", "foo|<br>");
+  EXPECT_EQ_LS("foo<br>|", "foo<br>|");
+}
+
+TEST_F(LayoutSelectionTest, ComputeLayoutSelectionCaret) {
+  EXPECT_EQ_LS("fo|o", "fo|o");
+  EXPECT_EQ_LS("<!--|-->foo", "|foo");
+  EXPECT_EQ_LS("foo<!--|-->", "foo|");
+  EXPECT_EQ_LS("<div>|</div>", "<div>|</div>");
+  EXPECT_EQ_LS("<div contenteditable><div>|</div></div>",
+               "<div contenteditable><div>|</div></div>");
+  EXPECT_EQ_LS("<div contenteditable>foo<div>|</div>bar</div>",
+               "<div contenteditable>foo<div>|</div>bar</div>");
+  EXPECT_EQ_LS("<div contenteditable>|</div>", "<div contenteditable>|</div>");
+}
+
+TEST_F(LayoutSelectionTest, ComputeLayoutSelectionEdgeIsNone) {
+  EXPECT_EQ_LS("fo|o<b style=\"display:none;\">b^ar</b>",
+               "fo|o^<b style=\"display:none;\">bar</b>");
+  EXPECT_EQ_LS("<b style=\"display:none;\">f^oo</b>ba|r",
+               "<b style=\"display:none;\">foo</b>^ba|r");
+  EXPECT_EQ_LS(
+      "<b style=\"display:none;\">f^oo</b>"
+      "bar<b style=\"display:none;\">b|az</b>",
+      "<b style=\"display:none;\">foo</b>"
+      "^bar|<b style=\"display:none;\">baz</b>");
+}
+
+TEST_F(LayoutSelectionTest, ComputeLayoutSelectionInsideNone) {
+  EXPECT_EQ_LS("foo<b style=\"display:none;\">b^a|r</b>baz",
+               "foo<b style=\"display:none;\">bar</b>baz");
+  EXPECT_EQ_LS("<b style=\"display:none;\">b|a^r</b>baz",
+               "<b style=\"display:none;\">bar</b>baz");
+}
+
 static const NGPaintFragment* FindNGPaintFragmentInternal(
     const NGPaintFragment* paint,
     const LayoutObject* layout_object) {
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 1dcdd7cd..f52729a 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -195,6 +195,7 @@
     "paste",
     "pause",
     "payerdetailchange",
+    "paymentmethodchange",
     "paymentrequest",
     "periodicsync",
     "pictureinpicturecontrolclick",
@@ -235,6 +236,7 @@
     "seeked",
     "seeking",
     "select",
+    "selectedcandidatepairchange",
     "selectionchange",
     "selectstart",
     "selectend",
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data.cc b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
index add6602..d9415b84 100644
--- a/third_party/blink/renderer/core/fetch/fetch_response_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
@@ -287,7 +287,8 @@
     : type_(type),
       status_(status),
       status_message_(status_message),
-      header_list_(FetchHeaderList::Create()) {}
+      header_list_(FetchHeaderList::Create()),
+      response_time_(base::Time::Now()) {}
 
 void FetchResponseData::ReplaceBodyStreamBuffer(BodyStreamBuffer* buffer) {
   if (type_ == Type::kBasic || type_ == Type::kCORS) {
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc b/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
index 32747bc..62e3eab 100644
--- a/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
@@ -268,4 +268,9 @@
   CheckHeaders(web_response);
 }
 
+TEST_F(FetchResponseDataTest, DefaultResponseTime) {
+  FetchResponseData* internal_response = CreateInternalResponse();
+  EXPECT_FALSE(internal_response->ResponseTime().is_null());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 32fba67..8296c76 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
 #include "third_party/blink/renderer/core/accessibility/ax_context.h"
 #include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
@@ -102,6 +103,7 @@
 #include "third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h"
 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
 #include "third_party/blink/renderer/platform/scroll/scroll_types.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -1248,6 +1250,12 @@
     document->CancelAnimationFrame(id);
 }
 
+void LocalDOMWindow::queueMicrotask(V8VoidFunction* callback) {
+  Microtask::EnqueueMicrotask(WTF::Bind(
+      &V8PersistentCallbackFunction<V8VoidFunction>::InvokeAndReportException,
+      WrapPersistent(ToV8PersistentCallbackFunction(callback)), nullptr));
+}
+
 int LocalDOMWindow::requestIdleCallback(V8IdleRequestCallback* callback,
                                         const IdleRequestOptions& options) {
   if (Document* document = this->document()) {
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 66664c4..8fa54f3d 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -73,6 +73,7 @@
 class USVStringOrTrustedURL;
 class V8FrameRequestCallback;
 class V8IdleRequestCallback;
+class V8VoidFunction;
 
 enum PageshowEventPersistence {
   kPageshowEventNotPersisted = 0,
@@ -224,6 +225,9 @@
   int webkitRequestAnimationFrame(V8FrameRequestCallback*);
   void cancelAnimationFrame(int id);
 
+  // https://html.spec.whatwg.org/#windoworworkerglobalscope-mixin
+  void queueMicrotask(V8VoidFunction*);
+
   // Idle callback extensions
   int requestIdleCallback(V8IdleRequestCallback*, const IdleRequestOptions&);
   void cancelIdleCallback(int id);
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl
index c610a10f..54ef7ac 100644
--- a/third_party/blink/renderer/core/frame/window.idl
+++ b/third_party/blink/renderer/core/frame/window.idl
@@ -104,6 +104,9 @@
 
     [CrossOrigin, CallWith=CurrentWindow, RaisesException, RuntimeEnabled=PostMessageOptions] void postMessage(any message, optional WindowPostMessageOptions options);
 
+    // https://html.spec.whatwg.org/#windoworworkerglobalscope-mixin
+    void queueMicrotask(VoidFunction callback);
+
     // Custom elements
     // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-api
     [CallWith=ScriptState] readonly attribute CustomElementRegistry customElements;
diff --git a/third_party/blink/renderer/core/html/html_element.idl b/third_party/blink/renderer/core/html/html_element.idl
index a606ed5a..e646d88 100644
--- a/third_party/blink/renderer/core/html/html_element.idl
+++ b/third_party/blink/renderer/core/html/html_element.idl
@@ -64,4 +64,5 @@
 };
 
 HTMLElement implements GlobalEventHandlers;
+HTMLElement implements DocumentAndElementEventHandlers;
 HTMLElement implements NoncedElement;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
index 9262a11a..5ee486f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
@@ -118,6 +118,20 @@
     if (!descendant_line_box->Size().IsEmpty()) {
       outline_rects->emplace_back(additional_offset,
                                   descendant_line_box->Size().ToLayoutSize());
+    } else if (descendant_line_box->Children().IsEmpty()) {
+      // Special-case for when the first continuation does not generate
+      // fragments. NGInlineLayoutAlgorithm suppresses box fragments when the
+      // line is "empty". When there is a continuation from the LayoutInline,
+      // the suppression makes such continuation not reachable. Check the
+      // continuation from LayoutInline in such case.
+      DCHECK(GetLayoutObject());
+      if (LayoutInline* first_layout_inline =
+              ToLayoutInlineOrNull(GetLayoutObject()->SlowFirstChild())) {
+        if (!first_layout_inline->IsElementContinuation()) {
+          first_layout_inline->AddOutlineRectsForChildrenAndContinuations(
+              *outline_rects, additional_offset, outline_type);
+        }
+      }
     }
   }
 }
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 8311497e..d40b6b4a 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -38,8 +38,10 @@
 
 #include <memory>
 #include "base/auto_reset.h"
+#include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -1659,8 +1661,10 @@
     return;
 
   if (!(origin_context->GetSecurityContext().GetInsecureRequestPolicy() &
-        kUpgradeInsecureRequests))
+        kUpgradeInsecureRequests) &&
+      !base::FeatureList::IsEnabled(features::kMixedContentAutoupgrade)) {
     return;
+  }
 
   // Nested frames are always upgraded on the browser process.
   if (resource_request.GetFrameType() ==
diff --git a/third_party/blink/renderer/core/svg/svg_element.idl b/third_party/blink/renderer/core/svg/svg_element.idl
index 2e01c8b3..c98affb 100644
--- a/third_party/blink/renderer/core/svg/svg_element.idl
+++ b/third_party/blink/renderer/core/svg/svg_element.idl
@@ -37,4 +37,5 @@
 };
 
 SVGElement implements GlobalEventHandlers;
+SVGElement implements DocumentAndElementEventHandlers;
 SVGElement implements NoncedElement;
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index 68c720a..50f43b9 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
 #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
 #include "third_party/blink/renderer/core/css/font_face_set_worker.h"
 #include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
@@ -58,6 +59,7 @@
 #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
 #include "third_party/blink/renderer/platform/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/instance_counters.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
@@ -493,6 +495,12 @@
                       CrossThreadBind(&RemoveURLFromMemoryCacheInternal, url));
 }
 
+void WorkerGlobalScope::queueMicrotask(V8VoidFunction* callback) {
+  Microtask::EnqueueMicrotask(WTF::Bind(
+      &V8PersistentCallbackFunction<V8VoidFunction>::InvokeAndReportException,
+      WrapPersistent(ToV8PersistentCallbackFunction(callback)), nullptr));
+}
+
 int WorkerGlobalScope::requestAnimationFrame(V8FrameRequestCallback* callback,
                                              ExceptionState& exception_state) {
   FrameRequestCallbackCollection::V8FrameCallback* frame_callback =
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h
index bbe98fd..4076260 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -58,6 +58,7 @@
 class FetchClientSettingsObjectSnapshot;
 class FontFaceSet;
 class OffscreenFontSelector;
+class V8VoidFunction;
 class WorkerLocation;
 class WorkerNavigator;
 class WorkerThread;
@@ -157,6 +158,9 @@
   // FontFaceSource on the IDL.
   FontFaceSet* fonts();
 
+  // https://html.spec.whatwg.org/#windoworworkerglobalscope-mixin
+  void queueMicrotask(V8VoidFunction*);
+
   int requestAnimationFrame(V8FrameRequestCallback* callback, ExceptionState&);
   void cancelAnimationFrame(int id);
 
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.idl b/third_party/blink/renderer/core/workers/worker_global_scope.idl
index 1e5fd34..424b2a6e 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.idl
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.idl
@@ -66,6 +66,9 @@
     // https://html.spec.whatwg.org/#windoworworkerglobalscope-mixin
     [Replaceable] readonly attribute DOMString origin;
 
+    // https://html.spec.whatwg.org/#windoworworkerglobalscope-mixin
+    void queueMicrotask(VoidFunction callback);
+
     // TODO(fserb): temporarly until we can enable the interface below.
     [RuntimeEnabled=OffscreenCanvasText] readonly attribute FontFaceSet fonts;
 
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_writer.cc b/third_party/blink/renderer/modules/filesystem/file_system_writer.cc
index ab254de4..a29a28b 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_writer.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_system_writer.cc
@@ -5,9 +5,13 @@
 #include "third_party/blink/renderer/modules/filesystem/file_system_writer.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
+#include "third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
 #include "third_party/blink/renderer/core/fileapi/file_error.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
@@ -19,7 +23,26 @@
 
 ScriptPromise FileSystemWriter::write(ScriptState* script_state,
                                       uint64_t position,
-                                      Blob* blob) {
+                                      ScriptValue data,
+                                      ExceptionState& exception_state) {
+  v8::Isolate* isolate = script_state->GetIsolate();
+  if (V8Blob::hasInstance(data.V8Value(), isolate)) {
+    Blob* blob = V8Blob::ToImpl(data.V8Value().As<v8::Object>());
+    return WriteBlob(script_state, position, blob);
+  }
+  if (!ReadableStreamOperations::IsReadableStream(script_state, data,
+                                                  exception_state)
+           .value_or(false)) {
+    if (!exception_state.HadException())
+      exception_state.ThrowTypeError("data should be a Blob or ReadableStream");
+    return ScriptPromise();
+  }
+  return WriteStream(script_state, position, data, exception_state);
+}
+
+ScriptPromise FileSystemWriter::WriteBlob(ScriptState* script_state,
+                                          uint64_t position,
+                                          Blob* blob) {
   if (!writer_ || pending_operation_) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
@@ -33,6 +56,117 @@
   return result;
 }
 
+class FileSystemWriter::StreamWriterClient
+    : public GarbageCollectedFinalized<StreamWriterClient>,
+      public FetchDataLoader::Client {
+  USING_GARBAGE_COLLECTED_MIXIN(StreamWriterClient);
+
+ public:
+  explicit StreamWriterClient(FileSystemWriter* writer) : writer_(writer) {}
+
+  void DidFetchDataLoadedDataPipe() override {
+    // WriteComplete could have been called with an error before we reach this
+    // point, in that case just return.
+    if (did_complete_)
+      return;
+    DCHECK(!did_finish_writing_to_pipe_);
+    DCHECK(writer_->pending_operation_);
+    did_finish_writing_to_pipe_ = true;
+  }
+
+  void DidFetchDataLoadFailed() override {
+    // WriteComplete could have been called with an error before we reach this
+    // point, in that case just return.
+    if (did_complete_)
+      return;
+    DCHECK(writer_->pending_operation_);
+    did_complete_ = true;
+    writer_->pending_operation_->Reject(
+        FileError::CreateDOMException(base::File::FILE_ERROR_FAILED));
+    Reset();
+  }
+
+  void Abort() override {
+    // WriteComplete could have been called with an error before we reach this
+    // point, in that case just return.
+    if (did_complete_)
+      return;
+    DCHECK(writer_->pending_operation_);
+    did_complete_ = true;
+    writer_->pending_operation_->Reject(
+        FileError::CreateDOMException(base::File::FILE_ERROR_ABORT));
+    Reset();
+  }
+
+  void WriteComplete(base::File::Error result, uint64_t bytes_written) {
+    // Early return if we already completed (with an error) before.
+    if (did_complete_)
+      return;
+    DCHECK(writer_->pending_operation_);
+    did_complete_ = true;
+    if (result != base::File::FILE_OK) {
+      writer_->pending_operation_->Reject(
+          FileError::CreateDOMException(result));
+    } else {
+      DCHECK(did_finish_writing_to_pipe_);
+      writer_->pending_operation_->Resolve();
+    }
+    Reset();
+  }
+
+  void Trace(Visitor* visitor) override {
+    Client::Trace(visitor);
+    visitor->Trace(writer_);
+  }
+
+ private:
+  void Reset() {
+    writer_->pending_operation_ = nullptr;
+    writer_->stream_loader_ = nullptr;
+  }
+
+  Member<FileSystemWriter> writer_;
+  bool did_finish_writing_to_pipe_ = false;
+  bool did_complete_ = false;
+};
+
+ScriptPromise FileSystemWriter::WriteStream(ScriptState* script_state,
+                                            uint64_t position,
+                                            ScriptValue stream,
+                                            ExceptionState& exception_state) {
+  if (!writer_ || pending_operation_) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state,
+        DOMException::Create(DOMExceptionCode::kInvalidStateError));
+  }
+  DCHECK(!stream_loader_);
+
+  auto reader = ReadableStreamOperations::GetReader(script_state, stream,
+                                                    exception_state);
+  if (exception_state.HadException())
+    return ScriptPromise();
+  auto* consumer = new ReadableStreamBytesConsumer(script_state, reader);
+
+  mojo::DataPipe pipe;
+  if (!pipe.consumer_handle.is_valid()) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+                                           "Failed to create data pipe"));
+  }
+  stream_loader_ = FetchDataLoader::CreateLoaderAsDataPipe(
+      std::move(pipe.producer_handle),
+      ExecutionContext::From(script_state)
+          ->GetTaskRunner(TaskType::kInternalDefault));
+  pending_operation_ = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise result = pending_operation_->Promise();
+  auto* client = new StreamWriterClient(this);
+  stream_loader_->Start(consumer, client);
+  writer_->WriteStream(
+      position, std::move(pipe.consumer_handle),
+      WTF::Bind(&StreamWriterClient::WriteComplete, WrapPersistent(client)));
+  return result;
+}
+
 ScriptPromise FileSystemWriter::truncate(ScriptState* script_state,
                                          uint64_t size) {
   if (!writer_ || pending_operation_) {
@@ -60,6 +194,7 @@
 void FileSystemWriter::Trace(Visitor* visitor) {
   ScriptWrappable::Trace(visitor);
   visitor->Trace(pending_operation_);
+  visitor->Trace(stream_loader_);
 }
 
 void FileSystemWriter::WriteComplete(base::File::Error result,
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_writer.h b/third_party/blink/renderer/modules/filesystem/file_system_writer.h
index f00cd9f4..6fa00725 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_writer.h
+++ b/third_party/blink/renderer/modules/filesystem/file_system_writer.h
@@ -7,13 +7,17 @@
 
 #include "third_party/blink/public/mojom/filesystem/file_writer.mojom-blink.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
 
 namespace blink {
 
 class Blob;
+class ExceptionState;
+class FetchDataLoader;
 class ScriptPromise;
 class ScriptPromiseResolver;
 class ScriptState;
+class ScriptValue;
 
 class FileSystemWriter final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -21,19 +25,31 @@
  public:
   explicit FileSystemWriter(mojom::blink::FileWriterPtr);
 
-  ScriptPromise write(ScriptState*, uint64_t position, Blob*);
+  ScriptPromise write(ScriptState*,
+                      uint64_t position,
+                      ScriptValue data,
+                      ExceptionState&);
   ScriptPromise truncate(ScriptState*, uint64_t size);
   ScriptPromise close(ScriptState*);
 
   void Trace(Visitor*) override;
 
  private:
+  class StreamWriterClient;
+
+  ScriptPromise WriteBlob(ScriptState*, uint64_t position, Blob*);
+  ScriptPromise WriteStream(ScriptState*,
+                            uint64_t position,
+                            ScriptValue stream,
+                            ExceptionState&);
+
   void WriteComplete(base::File::Error result, uint64_t bytes_written);
   void TruncateComplete(base::File::Error result);
 
   mojom::blink::FileWriterPtr writer_;
 
   Member<ScriptPromiseResolver> pending_operation_;
+  TraceWrapperMember<FetchDataLoader> stream_loader_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_writer.idl b/third_party/blink/renderer/modules/filesystem/file_system_writer.idl
index c4362be..b3e225cb 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_writer.idl
+++ b/third_party/blink/renderer/modules/filesystem/file_system_writer.idl
@@ -7,8 +7,9 @@
     NoInterfaceObject,
     RuntimeEnabled=WritableFiles
 ] interface FileSystemWriter {
-    // TODO(mek): Support other types, such as ReadableStream, by using 'any'.
-    [CallWith=ScriptState] Promise<void> write(unsigned long long position, Blob data);
+    // TODO(mek): 'any' really is 'Blob or ReadableStream', but that's not
+    // currently supported by our bindings.
+    [CallWith=ScriptState, RaisesException] Promise<void> write(unsigned long long position, any data);
     [CallWith=ScriptState] Promise<void> truncate(unsigned long long size);
 
     [CallWith=ScriptState] Promise<void> close();
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index caa18af..ad89588 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -212,6 +212,7 @@
           "payments/payment_address.idl",
           "payments/payment_instruments.idl",
           "payments/payment_manager.idl",
+          "payments/payment_method_change_event.idl",
           "payments/payment_request.idl",
           "payments/payment_request_event.idl",
           "payments/payment_request_update_event.idl",
@@ -591,6 +592,7 @@
           "payments/payment_handler_response.idl",
           "payments/payment_instrument.idl",
           "payments/payment_item.idl",
+          "payments/payment_method_change_event_init.idl",
           "payments/payment_method_data.idl",
           "payments/payment_options.idl",
           "payments/payment_request_event_init.idl",
diff --git a/third_party/blink/renderer/modules/payments/BUILD.gn b/third_party/blink/renderer/modules/payments/BUILD.gn
index 50bd846..ec0f2d7 100644
--- a/third_party/blink/renderer/modules/payments/BUILD.gn
+++ b/third_party/blink/renderer/modules/payments/BUILD.gn
@@ -31,6 +31,8 @@
     "payment_instruments.h",
     "payment_manager.cc",
     "payment_manager.h",
+    "payment_method_change_event.cc",
+    "payment_method_change_event.h",
     "payment_request.cc",
     "payment_request.h",
     "payment_request_event.cc",
diff --git a/third_party/blink/renderer/modules/payments/payment_method_change_event.cc b/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
new file mode 100644
index 0000000..7d47a10
--- /dev/null
+++ b/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/payments/payment_method_change_event.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+PaymentMethodChangeEvent::~PaymentMethodChangeEvent() = default;
+
+// static
+PaymentMethodChangeEvent* PaymentMethodChangeEvent::Create(
+    ScriptState* script_state,
+    const AtomicString& type,
+    const PaymentMethodChangeEventInit& init) {
+  return new PaymentMethodChangeEvent(script_state, type, init);
+}
+
+const String& PaymentMethodChangeEvent::methodName() const {
+  return method_name_;
+}
+
+const ScriptValue PaymentMethodChangeEvent::methodDetails(
+    ScriptState* script_state) const {
+  return ScriptValue(script_state, method_details_.V8ValueFor(script_state));
+}
+
+PaymentMethodChangeEvent::PaymentMethodChangeEvent(
+    ScriptState* script_state,
+    const AtomicString& type,
+    const PaymentMethodChangeEventInit& init)
+    : PaymentRequestUpdateEvent(ExecutionContext::From(script_state),
+                                type,
+                                init),
+      method_name_(init.methodName()),
+      method_details_(init.hasMethodDetails()
+                          ? init.methodDetails()
+                          : ScriptValue::CreateNull(script_state)) {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/payment_method_change_event.h b/third_party/blink/renderer/modules/payments/payment_method_change_event.h
new file mode 100644
index 0000000..f557cbc
--- /dev/null
+++ b/third_party/blink/renderer/modules/payments/payment_method_change_event.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_METHOD_CHANGE_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_METHOD_CHANGE_EVENT_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/payments/payment_method_change_event_init.h"
+#include "third_party/blink/renderer/modules/payments/payment_request_update_event.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ScriptState;
+
+class MODULES_EXPORT PaymentMethodChangeEvent final
+    : public PaymentRequestUpdateEvent {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  ~PaymentMethodChangeEvent() override;
+
+  static PaymentMethodChangeEvent* Create(
+      ScriptState*,
+      const AtomicString& type,
+      const PaymentMethodChangeEventInit& = PaymentMethodChangeEventInit());
+
+  const String& methodName() const;
+  const ScriptValue methodDetails(ScriptState*) const;
+
+ private:
+  PaymentMethodChangeEvent(ScriptState*,
+                           const AtomicString& type,
+                           const PaymentMethodChangeEventInit&);
+
+  String method_name_;
+  ScriptValue method_details_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_METHOD_CHANGE_EVENT_H_
diff --git a/third_party/blink/renderer/modules/payments/payment_method_change_event.idl b/third_party/blink/renderer/modules/payments/payment_method_change_event.idl
new file mode 100644
index 0000000..98e6d845
--- /dev/null
+++ b/third_party/blink/renderer/modules/payments/payment_method_change_event.idl
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/payment-request/#paymentmethodchangeevent-interface
+
+[
+    RuntimeEnabled=PaymentMethodChangeEvent,
+    ConstructorCallWith=ScriptState,
+    Constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict),
+    SecureContext,
+    Exposed=Window
+] interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
+    readonly attribute DOMString methodName;
+    [CallWith=ScriptState] readonly attribute object? methodDetails;
+};
diff --git a/third_party/blink/renderer/modules/payments/payment_method_change_event_init.idl b/third_party/blink/renderer/modules/payments/payment_method_change_event_init.idl
new file mode 100644
index 0000000..71e7140
--- /dev/null
+++ b/third_party/blink/renderer/modules/payments/payment_method_change_event_init.idl
@@ -0,0 +1,10 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/payment-request/#paymentmethodchangeeventinit-dictionary
+
+dictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
+    DOMString methodName = "";
+    object? methodDetails = null;
+};
diff --git a/third_party/blink/renderer/modules/payments/payment_request.h b/third_party/blink/renderer/modules/payments/payment_request.h
index 1aaf77c2..0b264dc9 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.h
+++ b/third_party/blink/renderer/modules/payments/payment_request.h
@@ -71,6 +71,7 @@
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(shippingaddresschange);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(shippingoptionchange);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(paymentmethodchange);
 
   ScriptPromise canMakePayment(ScriptState*);
 
diff --git a/third_party/blink/renderer/modules/payments/payment_request.idl b/third_party/blink/renderer/modules/payments/payment_request.idl
index 41e0129..f7837401 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.idl
+++ b/third_party/blink/renderer/modules/payments/payment_request.idl
@@ -25,4 +25,5 @@
 
     attribute EventHandler onshippingaddresschange;
     attribute EventHandler onshippingoptionchange;
+    [RuntimeEnabled=PaymentMethodChangeEvent] attribute EventHandler onpaymentmethodchange;
 };
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event.h b/third_party/blink/renderer/modules/payments/payment_request_update_event.h
index 62401d4..2738047 100644
--- a/third_party/blink/renderer/modules/payments/payment_request_update_event.h
+++ b/third_party/blink/renderer/modules/payments/payment_request_update_event.h
@@ -20,8 +20,8 @@
 class ExecutionContext;
 class ScriptState;
 
-class MODULES_EXPORT PaymentRequestUpdateEvent final : public Event,
-                                                       public PaymentUpdater {
+class MODULES_EXPORT PaymentRequestUpdateEvent : public Event,
+                                                 public PaymentUpdater {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(PaymentRequestUpdateEvent)
 
@@ -47,11 +47,12 @@
 
   void OnUpdateEventTimeoutForTesting();
 
- private:
+ protected:
   PaymentRequestUpdateEvent(ExecutionContext*,
                             const AtomicString& type,
                             const PaymentRequestUpdateEventInit&);
 
+ private:
   void OnUpdateEventTimeout(TimerBase*);
 
   // True after event.updateWith() was called.
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h
index a07ea25d..7735411 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h
@@ -47,6 +47,12 @@
 
     // Called asynchronously when the ICE connection state has changed.
     virtual void OnStateChanged(cricket::IceTransportState new_state) {}
+
+    // Called asynchronously when the ICE agent selects a different candidate
+    // pair for the active connection.
+    virtual void OnSelectedCandidatePairChanged(
+        const std::pair<cricket::Candidate, cricket::Candidate>&
+            selected_candidate_pair) {}
   };
 
   virtual ~IceTransportAdapter() = default;
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc
index 1fc096ec..4cdc8cb 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc
@@ -106,6 +106,8 @@
       this, &IceTransportAdapterImpl::OnCandidateGathered);
   p2p_transport_channel_->SignalStateChanged.connect(
       this, &IceTransportAdapterImpl::OnStateChanged);
+  p2p_transport_channel_->SignalNetworkRouteChanged.connect(
+      this, &IceTransportAdapterImpl::OnNetworkRouteChanged);
   // The ICE tiebreaker is used to determine which side is controlling/
   // controlled when both sides start in the same role. The number is randomly
   // generated so that each peer can calculate a.tiebreaker <= b.tiebreaker
@@ -192,4 +194,21 @@
   delegate_->OnStateChanged(p2p_transport_channel_->GetState());
 }
 
+void IceTransportAdapterImpl::OnNetworkRouteChanged(
+    absl::optional<rtc::NetworkRoute> new_network_route) {
+  const cricket::CandidatePairInterface* selected_connection =
+      p2p_transport_channel_->selected_connection();
+  if (!selected_connection) {
+    // The selected connection will only be null if the ICE connection has
+    // totally failed, at which point we'll get a StateChanged signal. The
+    // client will implicitly clear the selected candidate pair when it receives
+    // the failed state change, so we don't need to give an explicit callback
+    // here.
+    return;
+  }
+  delegate_->OnSelectedCandidatePairChanged(
+      std::make_pair(selected_connection->local_candidate(),
+                     selected_connection->remote_candidate()));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h
index 52fed69..0b92df8 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h
@@ -45,6 +45,8 @@
   void OnCandidateGathered(cricket::IceTransportInternal* transport,
                            const cricket::Candidate& candidate);
   void OnStateChanged(cricket::IceTransportInternal* transport);
+  void OnNetworkRouteChanged(
+      absl::optional<rtc::NetworkRoute> new_network_route);
 
   Delegate* const delegate_;
   std::unique_ptr<cricket::PortAllocator> port_allocator_;
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc
index 5db8163..79eba08 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc
@@ -108,4 +108,14 @@
       CrossThreadBind(&IceTransportProxy::OnStateChanged, proxy_, new_state));
 }
 
+void IceTransportHost::OnSelectedCandidatePairChanged(
+    const std::pair<cricket::Candidate, cricket::Candidate>&
+        selected_candidate_pair) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  PostCrossThreadTask(
+      *proxy_thread_, FROM_HERE,
+      CrossThreadBind(&IceTransportProxy::OnSelectedCandidatePairChanged,
+                      proxy_, selected_candidate_pair));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h
index 08ac5458..919a27f 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h
@@ -73,6 +73,9 @@
   void OnGatheringStateChanged(cricket::IceGatheringState new_state) override;
   void OnCandidateGathered(const cricket::Candidate& candidate) override;
   void OnStateChanged(cricket::IceTransportState new_state) override;
+  void OnSelectedCandidatePairChanged(
+      const std::pair<cricket::Candidate, cricket::Candidate>&
+          selected_candidate_pair) override;
 
   const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_;
   std::unique_ptr<IceTransportAdapter> transport_;
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc
index 3ff6fd7..5e0cea8b 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc
@@ -140,4 +140,11 @@
   delegate_->OnStateChanged(new_state);
 }
 
+void IceTransportProxy::OnSelectedCandidatePairChanged(
+    const std::pair<cricket::Candidate, cricket::Candidate>&
+        selected_candidate_pair) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  delegate_->OnSelectedCandidatePairChanged(selected_candidate_pair);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h
index 1b90fde..d10b866 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h
@@ -50,6 +50,9 @@
     }
     virtual void OnCandidateGathered(const cricket::Candidate& candidate) {}
     virtual void OnStateChanged(cricket::IceTransportState new_state) {}
+    virtual void OnSelectedCandidatePairChanged(
+        const std::pair<cricket::Candidate, cricket::Candidate>&
+            selected_candidate_pair) {}
   };
 
   // Construct a Proxy with the underlying ICE implementation running on the
@@ -94,6 +97,9 @@
   void OnGatheringStateChanged(cricket::IceGatheringState new_state);
   void OnCandidateGathered(const cricket::Candidate& candidate);
   void OnStateChanged(cricket::IceTransportState new_state);
+  void OnSelectedCandidatePairChanged(
+      const std::pair<cricket::Candidate, cricket::Candidate>&
+          selected_candidate_pair);
 
   const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_;
   const scoped_refptr<base::SingleThreadTaskRunner> host_thread_;
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h
index 05b1cd5..73ab10b2 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h
@@ -79,6 +79,13 @@
   STATIC_ONLY(CrossThreadCopier);
 };
 
+template <>
+struct CrossThreadCopier<std::pair<cricket::Candidate, cricket::Candidate>>
+    : public CrossThreadCopierPassThrough<
+          std::pair<cricket::Candidate, cricket::Candidate>> {
+  STATIC_ONLY(CrossThreadCopier);
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_WEB_RTC_CROSS_THREAD_COPIER_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
index 6d9af12a..6f5365d9 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -380,6 +380,7 @@
   // Stopping the consumer should cause it to disconnect.
   DCHECK(!HasConsumer());
   state_ = RTCIceTransportState::kClosed;
+  selected_candidate_pair_ = base::nullopt;
   proxy_.reset();
 }
 
@@ -455,9 +456,25 @@
     return;
   }
   state_ = local_new_state;
+  if (state_ == RTCIceTransportState::kFailed) {
+    selected_candidate_pair_ = base::nullopt;
+  }
   DispatchEvent(*Event::Create(EventTypeNames::statechange));
 }
 
+void RTCIceTransport::OnSelectedCandidatePairChanged(
+    const std::pair<cricket::Candidate, cricket::Candidate>&
+        selected_candidate_pair) {
+  RTCIceCandidate* local =
+      ConvertToRtcIceCandidate(selected_candidate_pair.first);
+  RTCIceCandidate* remote =
+      ConvertToRtcIceCandidate(selected_candidate_pair.second);
+  selected_candidate_pair_ = RTCIceCandidatePair();
+  selected_candidate_pair_->setLocal(local);
+  selected_candidate_pair_->setRemote(remote);
+  DispatchEvent(*Event::Create(EventTypeNames::selectedcandidatepairchange));
+}
+
 bool RTCIceTransport::RaiseExceptionIfClosed(
     ExceptionState& exception_state) const {
   if (IsClosed()) {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
index 364b120..2a39f0c 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
@@ -99,6 +99,7 @@
                           ExceptionState& exception_state);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(gatheringstatechange);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(selectedcandidatepairchange);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(icecandidate);
 
   // EventTarget overrides.
@@ -125,6 +126,9 @@
   void OnGatheringStateChanged(cricket::IceGatheringState new_state) override;
   void OnCandidateGathered(const cricket::Candidate& candidate) override;
   void OnStateChanged(cricket::IceTransportState new_state) override;
+  void OnSelectedCandidatePairChanged(
+      const std::pair<cricket::Candidate, cricket::Candidate>&
+          selected_candidate_pair) override;
 
   // Fills in |local_parameters_| with a random usernameFragment and a random
   // password.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl
index a2aca1f..76656b1 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl
@@ -47,7 +47,7 @@
     RTCIceParameters? getRemoteParameters();
     attribute EventHandler onstatechange;
     attribute EventHandler ongatheringstatechange;
-    // TODO(crbug.com/864871): Implement onselectedcandidatepairchange.
+    attribute EventHandler onselectedcandidatepairchange;
 
     // The following is defined in the WebRTC-ICE extension specification.
     // https://w3c.github.io/webrtc-ice/#rtcicetransport*
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc
index d205c6c..627ca32 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc
@@ -25,6 +25,7 @@
 using testing::_;
 using testing::Assign;
 using testing::AllOf;
+using testing::DoDefault;
 using testing::ElementsAre;
 using testing::Field;
 using testing::InSequence;
@@ -55,8 +56,23 @@
   return ice_parameters;
 }
 
-constexpr char kRemoteIceCandidateStr1[] =
+constexpr char kRemoteUsernameFragment2[] = "secondUsernameFragment";
+constexpr char kRemotePassword2[] = "secondPassword";
+
+RTCIceParameters CreateRemoteRTCIceParameters2() {
+  RTCIceParameters ice_parameters;
+  ice_parameters.setUsernameFragment(kRemoteUsernameFragment2);
+  ice_parameters.setPassword(kRemotePassword2);
+  return ice_parameters;
+}
+
+constexpr char kLocalIceCandidateStr1[] =
     "candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2";
+constexpr char kRemoteIceCandidateStr1[] =
+    "candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host generation 2";
+constexpr char kRemoteIceCandidateStr2[] =
+    "candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx raddr "
+    "192.168.1.5 rport 2346 generation 2";
 
 RTCIceCandidate* RTCIceCandidateFromString(V8TestingScope& scope,
                                            const String& candidate_str) {
@@ -66,6 +82,15 @@
                                  ASSERT_NO_EXCEPTION);
 }
 
+cricket::Candidate CricketCandidateFromString(
+    const std::string& candidate_str) {
+  cricket::Candidate candidate;
+  bool success =
+      webrtc::SdpDeserializeCandidate("", candidate_str, &candidate, nullptr);
+  DCHECK(success);
+  return candidate;
+}
+
 class MockIceTransportAdapterCrossThreadFactory
     : public IceTransportAdapterCrossThreadFactory {
  public:
@@ -341,4 +366,255 @@
                        ASSERT_NO_EXCEPTION);
 }
 
+// Test that receiving an OnStateChanged callback with the completed state
+// updates the RTCIceTransport state to 'connected' and fires a statechange
+// event.
+TEST_F(RTCIceTransportTest, OnStateChangedCompletedUpdatesStateAndFiresEvent) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> event_listener = CreateMockEventListener();
+  EXPECT_CALL(*event_listener, handleEvent(_, _))
+      .WillOnce(InvokeWithoutArgs(
+          [ice_transport] { EXPECT_EQ("connected", ice_transport->state()); }));
+  ice_transport->addEventListener(EventTypeNames::statechange, event_listener);
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+
+  delegate->OnStateChanged(cricket::IceTransportState::STATE_COMPLETED);
+
+  RunUntilIdle();
+}
+
+// Test that receiving an OnStateChanged callback with the failed state updates
+// the RTCIceTransport state to 'failed' and fires a statechange event.
+TEST_F(RTCIceTransportTest, OnStateChangedFailedUpdatesStateAndFiresEvent) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> event_listener = CreateMockEventListener();
+  EXPECT_CALL(*event_listener, handleEvent(_, _))
+      .WillOnce(InvokeWithoutArgs(
+          [ice_transport] { EXPECT_EQ("failed", ice_transport->state()); }));
+  ice_transport->addEventListener(EventTypeNames::statechange, event_listener);
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+
+  delegate->OnStateChanged(cricket::IceTransportState::STATE_FAILED);
+
+  RunUntilIdle();
+}
+
+// Test that calling OnSelectedCandidatePairChanged the first time fires the
+// selectedcandidatepairchange event and sets the selected candidate pair.
+TEST_F(RTCIceTransportTest, InitialOnSelectedCandidatePairChangedFiresEvent) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> event_listener = CreateMockEventListener();
+  EXPECT_CALL(*event_listener, handleEvent(_, _))
+      .WillOnce(InvokeWithoutArgs([ice_transport] {
+        base::Optional<RTCIceCandidatePair> selected_candidate_pair;
+        ice_transport->getSelectedCandidatePair(selected_candidate_pair);
+        ASSERT_TRUE(selected_candidate_pair);
+        EXPECT_EQ(ice_transport->getLocalCandidates()[0]->candidate(),
+                  selected_candidate_pair->local()->candidate());
+        EXPECT_EQ(ice_transport->getRemoteCandidates()[0]->candidate(),
+                  selected_candidate_pair->remote()->candidate());
+      }));
+  ice_transport->addEventListener(EventTypeNames::selectedcandidatepairchange,
+                                  event_listener);
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+  delegate->OnSelectedCandidatePairChanged(
+      std::make_pair(CricketCandidateFromString(kLocalIceCandidateStr1),
+                     CricketCandidateFromString(kRemoteIceCandidateStr1)));
+
+  RunUntilIdle();
+}
+
+// Test that calling OnSelectedCandidatePairChanged with a different remote
+// candidate fires the event and updates the selected candidate pair.
+TEST_F(RTCIceTransportTest,
+       OnSelectedCandidatePairChangedWithDifferentRemoteCandidateFiresEvent) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> event_listener = CreateMockEventListener();
+  EXPECT_CALL(*event_listener, handleEvent(_, _))
+      .WillOnce(DoDefault())  // First event is already tested above.
+      .WillOnce(InvokeWithoutArgs([ice_transport] {
+        base::Optional<RTCIceCandidatePair> selected_candidate_pair;
+        ice_transport->getSelectedCandidatePair(selected_candidate_pair);
+        ASSERT_TRUE(selected_candidate_pair);
+        EXPECT_EQ(ice_transport->getLocalCandidates()[0]->candidate(),
+                  selected_candidate_pair->local()->candidate());
+        EXPECT_EQ(ice_transport->getRemoteCandidates()[1]->candidate(),
+                  selected_candidate_pair->remote()->candidate());
+      }));
+  ice_transport->addEventListener(EventTypeNames::selectedcandidatepairchange,
+                                  event_listener);
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+
+  delegate->OnSelectedCandidatePairChanged(
+      std::make_pair(CricketCandidateFromString(kLocalIceCandidateStr1),
+                     CricketCandidateFromString(kRemoteIceCandidateStr1)));
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr2),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnSelectedCandidatePairChanged(
+      std::make_pair(CricketCandidateFromString(kLocalIceCandidateStr1),
+                     CricketCandidateFromString(kRemoteIceCandidateStr2)));
+
+  RunUntilIdle();
+}
+
+// Test that receiving an OnStateChange callback to the failed state once a
+// connection has been established clears the selected candidate pair without
+// firing the selectedcandidatepairchange event.
+TEST_F(RTCIceTransportTest,
+       OnStateChangeFailedAfterConnectedClearsSelectedCandidatePair) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> state_change_event_listener =
+      CreateMockEventListener();
+  EXPECT_CALL(*state_change_event_listener, handleEvent(_, _))
+      .WillOnce(DoDefault())  // First event is for 'connected'.
+      .WillOnce(InvokeWithoutArgs([ice_transport] {
+        EXPECT_EQ("failed", ice_transport->state());
+        base::Optional<RTCIceCandidatePair> selected_candidate_pair;
+        ice_transport->getSelectedCandidatePair(selected_candidate_pair);
+        EXPECT_EQ(base::nullopt, selected_candidate_pair);
+      }));
+  ice_transport->addEventListener(EventTypeNames::statechange,
+                                  state_change_event_listener);
+
+  Persistent<MockEventListener> selected_candidate_pair_change_event_listener =
+      CreateMockEventListener();
+  EXPECT_CALL(*selected_candidate_pair_change_event_listener, handleEvent(_, _))
+      .Times(1);  // First event is for the connected pair.
+  ice_transport->addEventListener(
+      EventTypeNames::selectedcandidatepairchange,
+      selected_candidate_pair_change_event_listener);
+
+  // Establish the connection
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+  delegate->OnStateChanged(cricket::IceTransportState::STATE_COMPLETED);
+  delegate->OnSelectedCandidatePairChanged(
+      std::make_pair(CricketCandidateFromString(kLocalIceCandidateStr1),
+                     CricketCandidateFromString(kRemoteIceCandidateStr1)));
+
+  // Transition to failed.
+  delegate->OnStateChanged(cricket::IceTransportState::STATE_FAILED);
+
+  RunUntilIdle();
+}
+
+// Test that receiving an OnSelectedCandidatePairChange callback after a remote
+// ICE restart still updates the selected candidate pair.
+TEST_F(RTCIceTransportTest,
+       RemoteIceRestartRaceWithSelectedCandidatePairChange) {
+  V8TestingScope scope;
+
+  IceTransportAdapter::Delegate* delegate = nullptr;
+  Persistent<RTCIceTransport> ice_transport =
+      CreateIceTransport(scope, &delegate);
+  ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+  RunUntilIdle();
+  ASSERT_TRUE(delegate);
+
+  Persistent<MockEventListener> event_listener = CreateMockEventListener();
+  EXPECT_CALL(*event_listener, handleEvent(_, _))
+      .WillOnce(InvokeWithoutArgs([ice_transport] {
+        base::Optional<RTCIceCandidatePair> selected_candidate_pair;
+        ice_transport->getSelectedCandidatePair(selected_candidate_pair);
+        ASSERT_TRUE(selected_candidate_pair);
+        EXPECT_EQ(kLocalIceCandidateStr1,
+                  selected_candidate_pair->local()->candidate());
+        EXPECT_EQ(kRemoteIceCandidateStr1,
+                  selected_candidate_pair->remote()->candidate());
+      }));
+  ice_transport->addEventListener(EventTypeNames::selectedcandidatepairchange,
+                                  event_listener);
+
+  ice_transport->addRemoteCandidate(
+      RTCIceCandidateFromString(scope, kRemoteIceCandidateStr1),
+      ASSERT_NO_EXCEPTION);
+
+  // Changing remote ICE parameters indicate a remote ICE restart. This clears
+  // the stored list of remote candidates.
+  ice_transport->start(CreateRemoteRTCIceParameters2(), "controlling",
+                       ASSERT_NO_EXCEPTION);
+
+  // These callbacks are part of the previous generation but should still take
+  // effect.
+  delegate->OnCandidateGathered(
+      CricketCandidateFromString(kLocalIceCandidateStr1));
+  delegate->OnStateChanged(cricket::IceTransportState::STATE_COMPLETED);
+  delegate->OnSelectedCandidatePairChanged(
+      std::make_pair(CricketCandidateFromString(kLocalIceCandidateStr1),
+                     CricketCandidateFromString(kRemoteIceCandidateStr1)));
+
+  RunUntilIdle();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
index 3f20138..ea7bafb6 100644
--- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
+++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -180,7 +180,8 @@
   WebServiceWorkerResponse web_response;
   web_response.SetError(error);
   ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
-      ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+      ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_,
+                            base::TimeTicks::Now());
 }
 
 void FetchRespondWithObserver::OnResponseFulfilled(
@@ -284,7 +285,8 @@
       // Handle the blob response body.
       web_response.SetBlobDataHandle(blob_data_handle);
       ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
-          ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+          ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_,
+                                base::TimeTicks::Now());
       return;
     }
     // Handle the stream response body.
@@ -302,9 +304,9 @@
         std::make_unique<WebServiceWorkerStreamHandle>(
             std::move(pipe.consumer_handle));
     ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
-        ->RespondToFetchEventWithResponseStream(event_id_, web_response,
-                                                body_stream_handle.get(),
-                                                event_dispatch_time_);
+        ->RespondToFetchEventWithResponseStream(
+            event_id_, web_response, body_stream_handle.get(),
+            event_dispatch_time_, base::TimeTicks::Now());
 
     buffer->StartLoading(FetchDataLoader::CreateLoaderAsDataPipe(
                              std::move(pipe.producer_handle), task_runner_),
@@ -317,12 +319,14 @@
     return;
   }
   ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
-      ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+      ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_,
+                            base::TimeTicks::Now());
 }
 
 void FetchRespondWithObserver::OnNoResponse() {
   ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
-      ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_);
+      ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_,
+                                          base::TimeTicks::Now());
 }
 
 FetchRespondWithObserver::FetchRespondWithObserver(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc
index 2364ec0..5810258 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc
@@ -202,25 +202,30 @@
 
 void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithNoResponse(
     int fetch_event_id,
-    base::TimeTicks event_dispatch_time) {
-  client_.RespondToFetchEventWithNoResponse(fetch_event_id,
-                                            event_dispatch_time);
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
+  client_.RespondToFetchEventWithNoResponse(fetch_event_id, event_dispatch_time,
+                                            respond_with_settled_time);
 }
 
 void ServiceWorkerGlobalScopeClient::RespondToFetchEvent(
     int fetch_event_id,
     const WebServiceWorkerResponse& response,
-    base::TimeTicks event_dispatch_time) {
-  client_.RespondToFetchEvent(fetch_event_id, response, event_dispatch_time);
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
+  client_.RespondToFetchEvent(fetch_event_id, response, event_dispatch_time,
+                              respond_with_settled_time);
 }
 
 void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithResponseStream(
     int fetch_event_id,
     const WebServiceWorkerResponse& response,
     WebServiceWorkerStreamHandle* stream_handle,
-    base::TimeTicks event_dispatch_time) {
+    base::TimeTicks event_dispatch_time,
+    base::TimeTicks respond_with_settled_time) {
   client_.RespondToFetchEventWithResponseStream(
-      fetch_event_id, response, stream_handle, event_dispatch_time);
+      fetch_event_id, response, stream_handle, event_dispatch_time,
+      respond_with_settled_time);
 }
 
 void ServiceWorkerGlobalScopeClient::RespondToAbortPaymentEvent(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h
index 60e433c..a5336ec 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h
@@ -109,16 +109,20 @@
   void DidHandleExtendableMessageEvent(int event_id,
                                        mojom::ServiceWorkerEventStatus,
                                        base::TimeTicks event_dispatch_time);
-  void RespondToFetchEventWithNoResponse(int fetch_event_id,
-                                         base::TimeTicks event_dispatch_time);
+  void RespondToFetchEventWithNoResponse(
+      int fetch_event_id,
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time);
   void RespondToFetchEvent(int fetch_event_id,
                            const WebServiceWorkerResponse&,
-                           base::TimeTicks event_dispatch_time);
+                           base::TimeTicks event_dispatch_time,
+                           base::TimeTicks respond_with_settled_time);
   void RespondToFetchEventWithResponseStream(
       int fetch_event_id,
       const WebServiceWorkerResponse&,
       WebServiceWorkerStreamHandle*,
-      base::TimeTicks event_dispatch_time);
+      base::TimeTicks event_dispatch_time,
+      base::TimeTicks respond_with_settled_time);
   void RespondToAbortPaymentEvent(int event_id,
                                   bool abort_payment,
                                   base::TimeTicks event_dispatch_time);
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
index ba64fc08..96c15bc 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -4,6 +4,9 @@
 
 #include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
 
+#include "base/metrics/histogram_base.h"
+#include "base/numerics/safe_conversions.h"
+#include "third_party/blink/renderer/platform/geometry/int_size.h"
 #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h"
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -79,6 +82,17 @@
       static_cast<int>(ColorSpaceUtilities::GetColorSpaceGamut(color_profile)));
 }
 
+void BitmapImageMetrics::CountJpegArea(const IntSize& size) {
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(
+      CustomCountHistogram, image_area_histogram,
+      ("Blink.ImageDecoders.Jpeg.Area", 1 /* min */, 8192 * 8192 /* max */,
+       100 /* bucket_count */));
+  // A base::HistogramBase::Sample may not fit |size.Area()|. Hence the use of
+  // saturated_cast.
+  image_area_histogram.Count(
+      base::saturated_cast<base::HistogramBase::Sample>(size.Area()));
+}
+
 void BitmapImageMetrics::CountJpegColorSpace(JpegColorSpace color_space) {
   DEFINE_THREAD_SAFE_STATIC_LOCAL(
       EnumerationHistogram, color_space_histogram,
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
index 09833bd..3479690 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h
@@ -14,6 +14,8 @@
 
 namespace blink {
 
+class IntSize;
+
 class PLATFORM_EXPORT BitmapImageMetrics {
   STATIC_ONLY(BitmapImageMetrics);
 
@@ -77,6 +79,7 @@
   static void CountImageJpegDensity(int image_min_side,
                                     int64_t density_centi_bpp);
   static void CountImageGammaAndGamut(const skcms_ICCProfile*);
+  static void CountJpegArea(const IntSize& size);
   static void CountJpegColorSpace(JpegColorSpace color_space);
 
  private:
diff --git a/third_party/blink/renderer/platform/image-decoders/DEPS b/third_party/blink/renderer/platform/image-decoders/DEPS
index d6e7af7d..6fee6fc4 100644
--- a/third_party/blink/renderer/platform/image-decoders/DEPS
+++ b/third_party/blink/renderer/platform/image-decoders/DEPS
@@ -7,7 +7,6 @@
 
     # Dependencies.
     "+cc/paint/image_animation_count.h",
-    "+third_party/blink/renderer/platform/histogram.h",
     "+third_party/blink/renderer/platform/geometry",
     "+third_party/blink/renderer/platform/graphics",
     "+third_party/blink/renderer/platform/histogram.h",
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
index e2287ac..8858238 100644
--- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -38,11 +38,8 @@
 #include "third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h"
 
 #include <memory>
-#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
 #include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
-#include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/platform_instrumentation.h"
 
 extern "C" {
@@ -83,24 +80,6 @@
 // JPEG only supports a denominator of 8.
 const unsigned g_scale_denomiator = 8;
 
-// Configuration for the JPEG image area histogram. See RecordJpegImageArea().
-const char* kImageAreaHistogramName = "Blink.ImageDecoders.Jpeg.Area";
-constexpr base::HistogramBase::Sample kImageAreaHistogramMin = 1;
-constexpr base::HistogramBase::Sample kImageAreaHistogramMax = 8192 * 8192;
-constexpr int32_t kImageAreaHistogramBucketCount = 100;
-
-// Records the area (total number of pixels) of a JPEG image as a UMA.
-void RecordJpegImageArea(const blink::IntSize& size) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      blink::CustomCountHistogram, image_area_histogram,
-      (kImageAreaHistogramName, kImageAreaHistogramMin, kImageAreaHistogramMax,
-       kImageAreaHistogramBucketCount));
-  // A base::HistogramBase::Sample may not fit |size.Area()|. Hence the use of
-  // saturated_cast.
-  image_area_histogram.Count(
-      base::saturated_cast<base::HistogramBase::Sample>(size.Area()));
-}
-
 // Extracts the JPEG color space of an image for UMA purposes given |info| which
 // is assumed to have gone through a jpeg_read_header(). When the color space is
 // YCbCr, we also extract the chroma subsampling. The caveat is that the
@@ -711,7 +690,7 @@
 
       case JPEG_DONE:
         // Finish decompression.
-        RecordJpegImageArea(decoder_->Size());
+        BitmapImageMetrics::CountJpegArea(decoder_->Size());
         BitmapImageMetrics::CountJpegColorSpace(
             ExtractUMAJpegColorSpace(info_));
         return jpeg_finish_decompress(&info_);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index a09f0034..07dc7fab9 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -933,6 +933,10 @@
       name: "PaymentApp",
       status: "experimental",
     },
+    {
+      name: "PaymentMethodChangeEvent",
+      status: "experimental",
+    },
     // PaymentRequest is enabled by default on Android
     {
       name: "PaymentRequest",
diff --git a/third_party/blink/tools/audit_non_blink_usage.py b/third_party/blink/tools/audit_non_blink_usage.py
index 59c7a0dd..b190a16 100755
--- a/third_party/blink/tools/audit_non_blink_usage.py
+++ b/third_party/blink/tools/audit_non_blink_usage.py
@@ -442,6 +442,7 @@
         # AtomicString or HeapVector) are used cross thread. These Blink types
         # are converted to the STL/WebRTC counterparts in the parent directory.
         'allowed': [
+            'absl::.+',
             'base::OnTaskRunnerDeleter',
             'sigslot::.+',
         ],
diff --git a/third_party/blink/tools/blinkpy/w3c/gerrit_mock.py b/third_party/blink/tools/blinkpy/w3c/gerrit_mock.py
index 726582b..5022842 100644
--- a/third_party/blink/tools/blinkpy/w3c/gerrit_mock.py
+++ b/third_party/blink/tools/blinkpy/w3c/gerrit_mock.py
@@ -12,6 +12,7 @@
 
     def __init__(self):
         self.exportable_open_cls = []
+        self.request_posted = []
 
     def query_exportable_open_cls(self):
         return self.exportable_open_cls
@@ -20,6 +21,7 @@
         return '' if raw else {}
 
     def post(self, path, data):
+        self.request_posted.append((path, data))
         return {}
 
 
diff --git a/third_party/blink/tools/blinkpy/w3c/test_exporter.py b/third_party/blink/tools/blinkpy/w3c/test_exporter.py
index 3281664e..1d726249 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_exporter.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_exporter.py
@@ -257,8 +257,10 @@
         footer += '{} {}'.format(WPT_REVISION_FOOTER, cl.current_revision_sha)
 
         if pull_request:
-            self.create_or_update_pr_from_commit(
+            pr_number = self.create_or_update_pr_from_commit(
                 commit, provisional=True, pr_number=pull_request.number, pr_footer=footer)
+            if pr_number is None:
+                return
 
             # TODO(jeffcarp): Turn PullRequest into a class with a .url method
             cl.post_comment((
@@ -272,6 +274,8 @@
             branch_name = 'chromium-export-cl-{}'.format(cl.number)
             pr_number = self.create_or_update_pr_from_commit(
                 commit, provisional=True, pr_footer=footer, pr_branch_name=branch_name)
+            if pr_number is None:
+                return
 
             cl.post_comment((
                 'Exportable changes to web-platform-tests were detected in this CL '
@@ -307,6 +311,10 @@
                 description after the commit message.
             pr_branch_name: Optional, the name of the head branch of the PR.
                 If unspecified, the current head branch of the PR will be used.
+
+        Returns:
+            The issue number (an int) of the updated/created PR, or None if no
+            change is made.
         """
         patch = commit.format_patch()
         message = commit.message()
diff --git a/third_party/blink/tools/blinkpy/w3c/test_exporter_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_exporter_unittest.py
index 70bd5a2..574be29 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_exporter_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_exporter_unittest.py
@@ -35,19 +35,35 @@
             PullRequest(title='title1', number=1234, body='', state='open', labels=[]),
         ])
         test_exporter.gerrit = MockGerritAPI()
+        test_exporter.gerrit.exportable_open_cls = [MockGerritCL(
+            data={
+                'change_id': 'I001',
+                'subject': 'subject',
+                '_number': 1234,
+                'current_revision': '1',
+                'has_review_started': True,
+                'revisions': {
+                    '1': {'commit_with_footers': 'a commit with footers'}
+                },
+                'owner': {'email': 'test@chromium.org'},
+            },
+            api=test_exporter.gerrit,
+            chromium_commit=MockChromiumCommit(self.host, subject='subject',
+                                               body='fake body', change_id='I001')
+        )]
         test_exporter.get_exportable_commits = lambda: ([
             MockChromiumCommit(self.host, position='refs/heads/master@{#458475}'),
             MockChromiumCommit(self.host, position='refs/heads/master@{#458476}'),
-            MockChromiumCommit(self.host, position='refs/heads/master@{#458477}'),
         ], [])
         success = test_exporter.main(['--credentials-json', '/tmp/credentials.json', '--dry-run'])
 
         self.assertTrue(success)
         self.assertEqual(test_exporter.wpt_github.calls, [
-            'pr_for_chromium_commit',
+            'pr_with_change_id',
             'pr_for_chromium_commit',
             'pr_for_chromium_commit',
         ])
+        self.assertEqual(len(test_exporter.gerrit.request_posted), 0)
 
     def test_creates_pull_request_for_all_exportable_commits(self):
         test_exporter = TestExporter(self.host)
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn
index dd04e9f..19b0fa5 100644
--- a/third_party/fuchsia-sdk/BUILD.gn
+++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -153,170 +153,6 @@
   ]
 }
 
-fuchsia_sdk_fidl_pkg("fonts") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-  sources = [
-    "font_provider.fidl",
-  ]
-  deps = [
-    ":mem",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("gfx") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-  sources = [
-    "commands.fidl",
-    "display_info.fidl",
-    "events.fidl",
-    "hit.fidl",
-    "nodes.fidl",
-    "renderer.fidl",
-    "resources.fidl",
-    "shapes.fidl",
-    "types.fidl",
-  ]
-  deps = [
-    ":images",
-    ":mem",
-    ":vectorial",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("images") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-  sources = [
-    "encoded_image.fidl",
-    "image_info.fidl",
-    "image_pipe.fidl",
-    "memory_type.fidl",
-    "presentation_info.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("input") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-  sources = [
-    "commands.fidl",
-    "ime_service.fidl",
-    "input_connection.fidl",
-    "input_device_registry.fidl",
-    "input_dispatcher.fidl",
-    "input_event_constants.fidl",
-    "input_events.fidl",
-    "input_reports.fidl",
-    "text_editing.fidl",
-    "text_input.fidl",
-    "usages.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("math") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-  sources = [
-    "math.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("media") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-
-  sources = [
-    "audio.fidl",
-    "audio_capturer.fidl",
-    "audio_device_enumerator.fidl",
-    "audio_renderer.fidl",
-    "gain_control.fidl",
-    "stream.fidl",
-    "stream_type.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("mem") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-
-  sources = [
-    "buffer.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("netstack") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-
-  sources = [
-    "net_address.fidl",
-    "netstack.fidl",
-  ]
-
-  deps = [
-    ":ethernet",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("ethernet") {
-  namespace = "zircon"
-  namespace_path = "zircon"
-
-  sources = [
-    "ethernet.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("oldhttp") {
-  namespace = "fuchsia.net"
-  namespace_path = "fuchsia/net"
-  sources = [
-    "http_error.fidl",
-    "http_header.fidl",
-    "http_service.fidl",
-    "url_body.fidl",
-    "url_loader.fidl",
-    "url_request.fidl",
-    "url_response.fidl",
-  ]
-  deps = [
-    ":mem",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("policy") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-  sources = [
-    "display_usage.fidl",
-    "presentation.fidl",
-    "presenter.fidl",
-  ]
-  deps = [
-    ":viewsv1",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("scenic") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-  sources = [
-    "commands.fidl",
-    "events.fidl",
-    "scenic.fidl",
-    "session.fidl",
-  ]
-  deps = [
-    ":gfx",
-    ":input",
-    ":sys",
-    ":views",
-  ]
-}
-
 fuchsia_sdk_pkg("svc") {
   sources = [
     "include/lib/svc/dir.h",
@@ -325,79 +161,6 @@
   libs = [ "svc" ]
 }
 
-fuchsia_sdk_fidl_pkg("sys") {
-  namespace = "fuchsia"
-  namespace_path = "fuchsia"
-
-  sources = [
-    "component_controller.fidl",
-    "environment.fidl",
-    "environment_controller.fidl",
-    "flat_namespace.fidl",
-    "launcher.fidl",
-    "loader.fidl",
-    "runner.fidl",
-    "service_provider.fidl",
-  ]
-  deps = [
-    ":mem",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("vectorial") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-  sources = [
-    "commands.fidl",
-    "events.fidl",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("views") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-
-  sources = [
-    "commands.fidl",
-    "events.fidl",
-  ]
-  deps = [
-    ":gfx",
-    ":images",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("viewsv1") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-
-  sources = [
-    "view_containers.fidl",
-    "view_manager.fidl",
-    "view_properties.fidl",
-    "view_provider.fidl",
-    "view_tree_token.fidl",
-    "view_trees.fidl",
-    "views.fidl",
-  ]
-  deps = [
-    ":gfx",
-    ":images",
-    ":math",
-    ":scenic",
-    ":viewsv1token",
-  ]
-}
-
-fuchsia_sdk_fidl_pkg("viewsv1token") {
-  namespace = "fuchsia.ui"
-  namespace_path = "fuchsia/ui"
-
-  sources = [
-    "view_token.fidl",
-  ]
-}
-
 fuchsia_sdk_pkg("zx") {
   sources = [
     "channel.cpp",
diff --git a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni
index b9b10054..042fa12 100644
--- a/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni
+++ b/third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni
@@ -13,8 +13,7 @@
 # Parameters:
 #   package_name - Name of the library. target_name is used if name
 #                  is not specified explicitly.
-#   namespace, namespace_path - FIDL namespace. See fidl_library.gni
-#                               for details.
+#   namespace    - FIDL namespace.
 #   sources      - List of sources relative to sdk/fidl/${name}.
 #   deps         - List of dependencies.
 template("fuchsia_sdk_fidl_pkg") {
@@ -35,20 +34,10 @@
     library_name = _package_name
 
     if (defined(invoker.namespace)) {
-      assert(defined(invoker.namespace_path),
-             "SDK packages with namespace must specify namespace_path")
       namespace = invoker.namespace
-      namespace_path = invoker.namespace_path
-
-      _library_name = "${namespace}.${_package_name}"
-    } else {
-      _library_name = _package_name
     }
 
-    sources = []
-    foreach(file, invoker.sources) {
-      sources += [ "sdk/fidl/${_library_name}/${file}" ]
-    }
+    sources = invoker.sources
   }
 }
 
diff --git a/third_party/fuchsia-sdk/gen_build_defs.py b/third_party/fuchsia-sdk/gen_build_defs.py
new file mode 100755
index 0000000..1fa21cd
--- /dev/null
+++ b/third_party/fuchsia-sdk/gen_build_defs.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# 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.
+#
+# Generates a single BUILD.gn file with build targets generated using the
+# manifest files in the SDK.
+
+import json
+import os
+import subprocess
+import sys
+
+
+# Inserted at the top of the generated BUILD.gn file.
+_GENERATED_PREAMBLE = """# DO NOT EDIT! This file was generated by
+# //third_party/fuchsia-sdk/gen_build_defs.py.
+# Any changes made to this file will be discarded.
+
+import("//third_party/fuchsia-sdk/fuchsia_sdk_pkg.gni")
+
+"""
+
+
+def SerializeListOfStrings(strings):
+  """Outputs a list of strings in GN-friendly, double-quoted format."""
+
+  return '[' + ','.join(['"{}"'.format(s) for s in strings]) + ']'
+
+
+def ConvertFidlLibrary(json):
+  """Massages the manifest data to match the format required by the GN build
+  and outputs a GN target for the FIDL library
+
+  Arguments:
+    json: The parsed manifest JSON.
+  Returns:
+    The GN target definition, represented as a string."""
+
+  json['deps'] = SerializeListOfStrings(
+      [':' + dep.split('.')[-1] for dep in json['deps']])
+  json['sources'] = SerializeListOfStrings(json['sources'])
+
+  name_tokenized = json['name'].split('.')
+  json['shortname'] = name_tokenized[-1]
+  json['namespace'] = '.'.join(name_tokenized[:-1])
+
+  return """fuchsia_sdk_fidl_pkg("{shortname}") {{
+    namespace = "{namespace}"
+    public_deps = {deps}
+    sources = {sources}
+  }}""".format(**json)
+
+
+def ConvertNoOp(json):
+  """Null implementation of a conversion function. No output is generated."""
+
+  return ""
+
+
+"""Maps manifest type strings to relevant conversion functions."""
+_CONVERSION_FUNCTION_MAP = {
+  'fidl_library': ConvertFidlLibrary,
+
+  # TODO(888753): Add conversion routines for these manifest types and migrate
+  # existing dependents of //third_party/fuchsia_sdk/BUILD.gn to use the
+  # generated targets instead. The migration can be executed incrementally.
+  'cc_source_library': ConvertNoOp,
+  'cc_prebuilt_library': ConvertNoOp,
+  'host_tool': ConvertNoOp,
+  'image': ConvertNoOp,
+  'loadable_module': ConvertNoOp,
+  'sysroot': ConvertNoOp,
+}
+
+
+def ConvertSdkManifests():
+  sdk_base_dir = os.path.join(os.path.dirname(__file__), 'sdk')
+  toplevel_meta = json.load(open(os.path.join(sdk_base_dir, 'meta',
+                                              'manifest.json')))
+
+  build_output_path = os.path.join(sdk_base_dir, 'BUILD.gn')
+  with open(build_output_path, 'w') as buildfile:
+    buildfile.write(_GENERATED_PREAMBLE)
+
+    for next_part in toplevel_meta['parts']:
+      parsed = json.load(open(os.path.join(sdk_base_dir, next_part)))
+      if 'type' not in parsed:
+        raise Exception("Couldn't find 'type' node in %s." % next_part)
+
+      convert_function = _CONVERSION_FUNCTION_MAP.get(parsed['type'])
+      if convert_function is None:
+        raise Exception('Unexpected SDK artifact type %s in %s.' %
+                        (parsed['type'], next_part))
+      buildfile.write(convert_function(parsed))
+
+
+if __name__ == '__main__':
+  sys.exit(ConvertSdkManifests())
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index dc770bee..a17246a 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Saturday September 22 2018
+Date: Saturday September 29 2018
 Branch: master
-Commit: 3448987ab20aa05716ffc4aedf6d02e23f75920b
+Commit: 2beb5c9f91e7166c2c9d01c94bf84767815121e4
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
index 4fa2dcc..beb3351 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
@@ -89,5 +89,6 @@
 .set CONFIG_FP_MB_STATS ,  0
 .set CONFIG_EMULATE_HARDWARE ,  0
 .set CONFIG_NON_GREEDY_MV ,  0
+.set CONFIG_ML_VAR_PARTITION ,  0
 .set DECODE_WIDTH_LIMIT ,  16384
 .set DECODE_HEIGHT_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
index c19d1d9..7c92a22 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
index 9fee00ef..2a02bb3a 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
@@ -89,5 +89,6 @@
 .set CONFIG_FP_MB_STATS ,  0
 .set CONFIG_EMULATE_HARDWARE ,  0
 .set CONFIG_NON_GREEDY_MV ,  0
+.set CONFIG_ML_VAR_PARTITION ,  0
 .set DECODE_WIDTH_LIMIT ,  16384
 .set DECODE_HEIGHT_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.h b/third_party/libvpx/source/config/ios/arm64/vpx_config.h
index e4de0be..3437c03 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_config.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
index 89967fe..1733c41 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
index 58b42323..1af5ae89 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
index f495ef9..9887adf 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
index c19d1d9..7c92a22 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.asm b/third_party/libvpx/source/config/linux/arm/vpx_config.asm
index 8f0a17c..13377ed 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.h b/third_party/libvpx/source/config/linux/arm/vpx_config.h
index acc4935..e699eab 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
index c7343fe..d4de564 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.h b/third_party/libvpx/source/config/linux/arm64/vpx_config.h
index e4de0be..3437c03 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.asm b/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.asm
index 342aff79..75e9f0f 100644
--- a/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.h b/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.h
index 5df6afd..3e56331e 100644
--- a/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/chromeos-arm-neon/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.asm b/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.asm
index cc2e6b3c..8863b2cb 100644
--- a/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.h b/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.h
index 1a03c79..e57b1c4 100644
--- a/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/chromeos-arm64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.asm b/third_party/libvpx/source/config/linux/generic/vpx_config.asm
index ae4cf6e..9bae4f7 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/generic/vpx_config.asm
@@ -86,6 +86,7 @@
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ CONFIG_NON_GREEDY_MV ,  0
+.equ CONFIG_ML_VAR_PARTITION ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
 .equ DECODE_HEIGHT_LIMIT ,  16384
 	.section	.note.GNU-stack,"",%progbits
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.h b/third_party/libvpx/source/config/linux/generic/vpx_config.h
index abc94bfc..9578b56 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
index 5569f05..57637ae08 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.h b/third_party/libvpx/source/config/linux/ia32/vpx_config.h
index fff9290..a65ea2d 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
index 7941761..d79a46a9 100644
--- a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
index 38c667e..9910a7ff 100644
--- a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.asm b/third_party/libvpx/source/config/linux/x64/vpx_config.asm
index 613735d8..0f7956f 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/x64/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.h b/third_party/libvpx/source/config/linux/x64/vpx_config.h
index 677a9fc..260602b 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
index 5569f05..57637ae08 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.h b/third_party/libvpx/source/config/mac/ia32/vpx_config.h
index fff9290..a65ea2d 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.asm b/third_party/libvpx/source/config/mac/x64/vpx_config.asm
index 613735d8..0f7956f 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/mac/x64/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.h b/third_party/libvpx/source/config/mac/x64/vpx_config.h
index 677a9fc..260602b 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/nacl/vpx_config.h b/third_party/libvpx/source/config/nacl/vpx_config.h
index abc94bfc..9578b56 100644
--- a/third_party/libvpx/source/config/nacl/vpx_config.h
+++ b/third_party/libvpx/source/config/nacl/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index b3f6a26..81961788 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  7
 #define VERSION_PATCH  0
-#define VERSION_EXTRA "1064-g3448987ab"
+#define VERSION_EXTRA  "1115-g2beb5c9f9"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.7.0-1064-g3448987ab"
-#define VERSION_STRING " v1.7.0-1064-g3448987ab"
+#define VERSION_STRING_NOSP "v1.7.0-1115-g2beb5c9f9"
+#define VERSION_STRING      " v1.7.0-1115-g2beb5c9f9"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.asm b/third_party/libvpx/source/config/win/ia32/vpx_config.asm
index 6c3ef6c..054b531a3 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/win/ia32/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.h b/third_party/libvpx/source/config/win/ia32/vpx_config.h
index 2d967a0..2444863 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.asm b/third_party/libvpx/source/config/win/x64/vpx_config.asm
index d104fd3f..f992b51 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/win/x64/vpx_config.asm
@@ -82,5 +82,6 @@
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define CONFIG_NON_GREEDY_MV 0
+%define CONFIG_ML_VAR_PARTITION 0
 %define DECODE_WIDTH_LIMIT 16384
 %define DECODE_HEIGHT_LIMIT 16384
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.h b/third_party/libvpx/source/config/win/x64/vpx_config.h
index 8a07c942..093f254 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_config.h
@@ -94,6 +94,7 @@
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define CONFIG_NON_GREEDY_MV 0
+#define CONFIG_ML_VAR_PARTITION 0
 #define DECODE_WIDTH_LIMIT 16384
 #define DECODE_HEIGHT_LIMIT 16384
 #endif /* VPX_CONFIG_H */
diff --git a/third_party/tcmalloc/chromium/src/debugallocation.cc b/third_party/tcmalloc/chromium/src/debugallocation.cc
index 2d311e1..6ac0ea4f 100644
--- a/third_party/tcmalloc/chromium/src/debugallocation.cc
+++ b/third_party/tcmalloc/chromium/src/debugallocation.cc
@@ -775,6 +775,17 @@
     return FromRawPointer(const_cast<void*>(p));
   }
 
+  // Return whether p points to memory returned by memalign.
+  // Requires that p be non-zero and has been checked for sanity with
+  // FromRawPointer().
+  static bool IsMemaligned(const void* p) {
+    const MallocBlock* mb = reinterpret_cast<const MallocBlock*>(
+        reinterpret_cast<const char*>(p) - MallocBlock::data_offset());
+    // If the offset is non-zero, the block was allocated by memalign
+    // (see FromRawPointer above).
+    return mb->offset_ != 0;
+  }
+
   void Check(int type) const {
     alloc_map_lock_.Lock();
     CheckLocked(type);
@@ -1287,13 +1298,20 @@
     MallocHook::InvokeNewHook(ptr, size);
     return ptr;
   }
+  MallocBlock* old = MallocBlock::FromRawPointer(ptr);
+  old->Check(MallocBlock::kMallocType);
+  if (MallocBlock::IsMemaligned(ptr)) {
+    RAW_LOG(FATAL,
+            "realloc/memalign mismatch at %p: "
+            "non-NULL pointers passed to realloc must be obtained "
+            "from malloc, calloc, or realloc",
+            ptr);
+  }
   if (size == 0) {
     MallocHook::InvokeDeleteHook(ptr);
     DebugDeallocate(ptr, MallocBlock::kMallocType, 0);
     return NULL;
   }
-  MallocBlock* old = MallocBlock::FromRawPointer(ptr);
-  old->Check(MallocBlock::kMallocType);
   MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType);
 
   // If realloc fails we are to leave the old block untouched and
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn
index aa21ecb..010a326 100644
--- a/third_party/widevine/cdm/BUILD.gn
+++ b/third_party/widevine/cdm/BUILD.gn
@@ -14,7 +14,7 @@
 
   flags = [
     "ENABLE_WIDEVINE=$enable_widevine",
-    "SHOULD_BUNDLE_WIDEVINE_CDM=$should_bundle_widevine_cdm",
+    "BUNDLE_WIDEVINE_CDM=$bundle_widevine_cdm",
     "ENABLE_WIDEVINE_CDM_COMPONENT=$enable_widevine_cdm_component",
   ]
 }
@@ -29,7 +29,7 @@
 
 # TODO(xhwang): widevine_cdm_version.h is only used in few places. Clean this up
 # so we don't need to copy it in most cases.
-if (should_bundle_widevine_cdm) {
+if (bundle_widevine_cdm) {
   if (is_chromeos) {
     widevine_cdm_version_h_file =
         "chromeos/$widevine_arch/widevine_cdm_version.h"
@@ -56,7 +56,7 @@
   widevine_cdm_version_h_file = "widevine_cdm_version.h"
 }
 
-if (should_bundle_widevine_cdm && enable_widevine_cdm_host_verification) {
+if (bundle_widevine_cdm && enable_widevine_cdm_host_verification) {
   if (is_win) {
     widevine_cdm_binary_files += [ "win/$widevine_arch/widevinecdm.dll.sig" ]
   } else if (is_mac) {
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni
index e925eed..e10d9b9 100644
--- a/third_party/widevine/cdm/widevine.gni
+++ b/third_party/widevine/cdm/widevine.gni
@@ -11,20 +11,33 @@
   enable_widevine = is_chrome_branded || is_android
 }
 
-# The Widevine CDM can be updated as a component. This only applies to platforms
-# where the CDM is a standalone library (enable_library_cdms == true). Currently
-# it's only supported on Windows and Mac. The CDM can still be bundled when it's
-# a component, see below.
-enable_widevine_cdm_component =
-    enable_widevine && enable_library_cdms && (is_win || is_mac)
+# Widevine CDM is available as a library CDM on the following platforms and
+# architectures. Notably on Android library CDM is not used and Widevine is
+# supported via Android MediaDrm API.
+# TODO(hmchen): Provide support on "arm64".
+library_widevine_cdm_available =
+    (is_chromeos && (target_cpu == "x64" || target_cpu == "arm")) ||
+    (is_desktop_linux && (target_cpu == "x86" || target_cpu == "x64")) ||
+    (is_mac && target_cpu == "x64") ||
+    (is_win && (target_cpu == "x86" || target_cpu == "x64"))
 
-# The Widevine CDM is bundled as part of Google Chrome builds.
-# TODO(hmchen): Provide prebuilt libraries for ARM64.
-should_bundle_widevine_cdm = enable_widevine && is_chrome_branded &&
-                             enable_library_cdms && target_cpu != "arm64"
+# Widevine CDM is available as a library CDM and it's supported by Chromium.
+# This does not define how the CDM will be deployed. It can be bundled or
+# component updated. See below.
+enable_library_widevine_cdm =
+    enable_widevine && enable_library_cdms && library_widevine_cdm_available
+
+# Widevine CDM can be deployed as a component. Currently only supported on Mac
+# and Windows. The CDM can be bundled regardless whether it's a component. See
+# below.
+enable_widevine_cdm_component =
+    enable_library_widevine_cdm && (is_win || is_mac)
+
+# Widevine CDM is bundled as part of Google Chrome builds.
+bundle_widevine_cdm = enable_library_widevine_cdm && is_chrome_branded
 
 enable_widevine_cdm_host_verification =
-    enable_widevine && enable_cdm_host_verification
+    enable_library_widevine_cdm && enable_cdm_host_verification
 
 template("widevine_sign_file") {
   # For official builds, generate a signature file for |file| which will
diff --git a/tools/fuchsia/local-sdk.py b/tools/fuchsia/local-sdk.py
index e5974d0..e6997a20 100755
--- a/tools/fuchsia/local-sdk.py
+++ b/tools/fuchsia/local-sdk.py
@@ -91,6 +91,10 @@
   shutil.rmtree(tempdir)
   os.chdir(original_dir)
 
+  subprocess.check_call([os.path.join(REPOSITORY_ROOT, 'third_party',
+                                      'fuchsia-sdk',
+                                      'gen_build_defs.py')])
+
   return 0
 
 
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 309c71bf..93404b06 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -17908,6 +17908,17 @@
   </description>
 </action>
 
+<action name="Signin_Signout_FromUserMenu">
+  <owner>droger@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <owner>tangltom@chromium.org</owner>
+  <description>
+    Recorded when the user is signed into Chrome, but not syncing, and clicks
+    the sign out button in the user menu. This is only recorded when Desktop
+    Identity Consistency is enabled.
+  </description>
+</action>
+
 <action name="Signin_Undo_Signin">
   <owner>gogerald@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 6d3c34fb..330d2ab 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -20265,6 +20265,8 @@
   <int value="2552" label="BackgroundFetchRegistrationAbort"/>
   <int value="2553" label="BackgroundFetchRegistrationMatch"/>
   <int value="2554" label="BackgroundFetchRegistrationMatchAll"/>
+  <int value="2555" label="V8AtomicsNotify"/>
+  <int value="2556" label="V8AtomicsWake"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -29340,6 +29342,8 @@
   <int value="-508143738" label="disable-accelerated-fixed-root-background"/>
   <int value="-506706655" label="respect-autocomplete-off-autofill"/>
   <int value="-505679399" label="FontCacheScaling:enabled"/>
+  <int value="-503430431" label="XRSandbox:enabled"/>
+  -
   <int value="-498740735" label="ArcUsbHost:disabled"/>
   <int value="-498463128" label="MacSystemShareMenu:enabled"/>
   <int value="-496119023" label="WebXR:enabled"/>
@@ -30583,6 +30587,7 @@
   <int value="1971964569" label="NewEncodeCpuLoadEstimator:disabled"/>
   <int value="1972232935" label="DisplayMoveWindowAccels:enabled"/>
   <int value="1972720114" label="WebPaymentsJustInTimePaymentApp:enabled"/>
+  <int value="1979222611" label="XRSandbox:disabled"/>
   <int value="1980011075" label="debug-packed-apps"/>
   <int value="1980648371" label="PointerEventV1SpecCapturing:enabled"/>
   <int value="1988506961" label="EnableManualSaving:enabled"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index b5dd504..b56731a 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3470,7 +3470,8 @@
   <metric name="opt_out">
     <summary>
       Set to 1 when a user clicks &quot;Show Original&quot; on a preview page
-      load.
+      load using the infobar. Set to 2 when a user opts out of a Preview using
+      the omnibox.
     </summary>
   </metric>
   <metric name="origin_opt_out">
diff --git a/ui/aura/mus/property_converter.cc b/ui/aura/mus/property_converter.cc
index 5f9c0db9..0d0e345 100644
--- a/ui/aura/mus/property_converter.cc
+++ b/ui/aura/mus/property_converter.cc
@@ -180,7 +180,7 @@
     const gfx::ImageSkia* value = window->GetProperty(image_key);
     if (value) {
       // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
-      SkBitmap bitmap = value->GetRepresentation(1.f).sk_bitmap();
+      SkBitmap bitmap = value->GetRepresentation(1.f).GetBitmap();
       *transport_value = std::make_unique<std::vector<uint8_t>>(
           mojo::ConvertTo<std::vector<uint8_t>>(bitmap));
     } else {
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index 5a9e099..c66b2a1d 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -64,6 +64,8 @@
   WindowEventDispatcher(WindowTreeHost* host, bool are_events_in_pixels);
   ~WindowEventDispatcher() override;
 
+  bool are_events_in_pixels() const { return are_events_in_pixels_; }
+
   // Stops dispatching/synthesizing mouse events.
   void Shutdown();
 
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index 27deae02..01421ff 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -1010,9 +1010,6 @@
 // Tests that touch-move events don't contribute to an in-progress scroll
 // gesture if touch-move events are being held by the dispatcher.
 TEST_P(WindowEventDispatcherTest, TouchMovesHeldOnScroll) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
-  if (GetParam() == Env::Mode::MUS)
-    return;
   EventFilterRecorder recorder;
   root_window()->AddPreTargetHandler(&recorder);
   test::TestWindowDelegate delegate;
@@ -2282,7 +2279,9 @@
 };
 
 TEST_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
+  // This test is only applicable to LOCAL mode as it's setting a device scale
+  // factor and expecting events to be transformed while routing the event
+  // directly through host(). In MUS mode the window-service does the scaling.
   if (GetParam() == Env::Mode::MUS)
     return;
 
@@ -2322,9 +2321,12 @@
 }
 
 TEST_P(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
+  // This test is only applicable to LOCAL mode as it's setting a device scale
+  // factor and expecting events to be transformed while routing the event
+  // directly through host(). In MUS mode the window-service does the scaling.
   if (GetParam() == Env::Mode::MUS)
     return;
+
   EventFilterRecorder recorder;
   root_window()->AddPreTargetHandler(&recorder);
   test::TestWindowDelegate delegate;
@@ -2394,9 +2396,12 @@
 // correctly.
 TEST_P(WindowEventDispatcherTestInHighDPI,
        EventsTransformedInRepostedEventTriggeredNestedLoop) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
+  // This test is only applicable to LOCAL mode as it's setting a device scale
+  // factor and expecting events to be transformed while routing the event
+  // directly through host(). In MUS mode the window-service does the scaling.
   if (GetParam() == Env::Mode::MUS)
     return;
+
   std::unique_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
   // Make sure the window is visible.
   RunAllPendingInMessageLoop();
@@ -2851,7 +2856,9 @@
 // cursor's position in root coordinates has changed (e.g. when the displays's
 // scale factor changed). Test that hover effects are properly updated.
 TEST_P(WindowEventDispatcherTest, OnCursorMovedToRootLocationUpdatesHover) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
+  // This test is only applicable to LOCAL mode as it's setting a device scale
+  // factor and expecting events to be transformed while routing the event
+  // directly through host(). In MUS mode the window-service does the scaling.
   if (GetParam() == Env::Mode::MUS)
     return;
 
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index a61fc13a..7edb1e5 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -1638,9 +1638,13 @@
 }
 
 TEST_P(WindowTest, TransformGesture) {
-  // TODO(sky): fails with mus. https://crbug.com/866502
+  // This test is only applicable to LOCAL mode as it's setting a transform on
+  // host() and expecting events to be transformed while routing the event
+  // directly through host(). In MUS mode the window-service does the
+  // transformation.
   if (GetParam() == Env::Mode::MUS)
     return;
+
   gfx::Size size = host()->GetBoundsInPixels().size();
 
   std::unique_ptr<GestureTrackPositionDelegate> delegate(
diff --git a/ui/base/cursor/cursor_util.cc b/ui/base/cursor/cursor_util.cc
index 5a672aa9..3735bf6 100644
--- a/ui/base/cursor/cursor_util.cc
+++ b/ui/base/cursor/cursor_util.cc
@@ -108,7 +108,7 @@
   const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
   // TODO(oshima): The cursor should use resource scale factor when
   // fractional scale factor is enabled. crbug.com/372212
-  (*bitmap) = image_rep.sk_bitmap();
+  (*bitmap) = image_rep.GetBitmap();
   ScaleAndRotateCursorBitmapAndHotpoint(
       scale / image_rep.scale(), rotation, bitmap, hotspot);
   // |image_rep| is owned by the resource bundle. So we do not need to free it.
@@ -123,7 +123,7 @@
   const gfx::ImageSkia* image =
       ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
   const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
-  SkBitmap bitmap = image_rep.sk_bitmap();
+  SkBitmap bitmap = image_rep.GetBitmap();
   int frame_width = bitmap.height();
   int frame_height = frame_width;
   int total_width = bitmap.width();
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn
index c443847d..541a0c6b 100644
--- a/ui/base/ime/BUILD.gn
+++ b/ui/base/ime/BUILD.gn
@@ -243,7 +243,7 @@
     ]
 
     deps += [
-      "//third_party/fuchsia-sdk:input",
+      "//third_party/fuchsia-sdk/sdk:input",
       "//ui/events",
       "//ui/events:dom_keycode_converter",
     ]
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index c9ef99a..734904f 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -848,7 +848,7 @@
   // we don't need/want to, but we should address this in the future if it
   // becomes an issue.
   nine_patch_layer_->SetBitmap(
-      image.GetRepresentation(device_scale_factor_).sk_bitmap());
+      image.GetRepresentation(device_scale_factor_).GetBitmap());
 }
 
 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture_in_dip) {
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 3db5568a..118d5a5 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -306,7 +306,7 @@
       "fuchsia/input_event_dispatcher.h",
       "fuchsia/input_event_dispatcher_delegate.h",
     ]
-    public_deps += [ "//third_party/fuchsia-sdk:input" ]
+    public_deps += [ "//third_party/fuchsia-sdk/sdk:input" ]
   }
 }
 
diff --git a/ui/file_manager/file_manager/foreground/css/common.css b/ui/file_manager/file_manager/foreground/css/common.css
index 7c68a1d6..3563ffe 100644
--- a/ui/file_manager/file_manager/foreground/css/common.css
+++ b/ui/file_manager/file_manager/foreground/css/common.css
@@ -193,9 +193,11 @@
 }
 
 /* Pop-up dialogs. */
+.cr-dialog-container.shown {
+  background-color: rgba(0, 0, 0, 0.6);
+}
 
 .cr-dialog-container {
-  background-color: rgba(0, 0, 0, 0.6);
   display: flex;
   height: 100%;
   left: 0;
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index dbd427ce8..10defcc 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -33,6 +33,7 @@
     <custom-style>
       <style is="custom-style">
         #search-box cr-input {
+          --cr-input-background-color: transparent;
           --cr-input-color: white;
           --cr-input-focus-color: white;
           --cr-input-container: {
@@ -40,7 +41,6 @@
           }
           --cr-input-error-display: none;
           --cr-input-input: {
-            background-color: transparent;
             border-bottom: 1px solid rgba(255, 255, 255, 0.5);
           }
           --cr-input-padding-end: 20px;
diff --git a/ui/file_manager/gallery/gallery.html b/ui/file_manager/gallery/gallery.html
index 78b537c..d0a3c48 100644
--- a/ui/file_manager/gallery/gallery.html
+++ b/ui/file_manager/gallery/gallery.html
@@ -73,12 +73,12 @@
           line-height: var(--cr-form-field-label-font-size);
           margin-bottom: 0;
         }
+        --cr-input-background-color: transparent;
         --cr-input-color: white;
         --cr-input-container: {
           border-radius: 0;
         }
         --cr-input-input: {
-          background-color: transparent;
           border-bottom: 1px solid var(--paper-grey-800);
         }
         --cr-input-padding-end: 0;
diff --git a/ui/gfx/image/image_generic.cc b/ui/gfx/image/image_generic.cc
index 3f42491..4c8510b 100644
--- a/ui/gfx/image/image_generic.cc
+++ b/ui/gfx/image/image_generic.cc
@@ -112,7 +112,7 @@
 
   scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
   if (image_skia_rep.scale() != 1.0f ||
-      !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
+      !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.GetBitmap(), false,
                                     &png_bytes->data())) {
     return NULL;
   }
diff --git a/ui/gfx/image/image_mac_unittest.mm b/ui/gfx/image/image_mac_unittest.mm
index f54b9bc4..dc26e924 100644
--- a/ui/gfx/image/image_mac_unittest.mm
+++ b/ui/gfx/image/image_mac_unittest.mm
@@ -200,10 +200,10 @@
   // Convert to ImageSkia to check pixel contents of NSImageReps.
   gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
   EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
-      bytes1x, image_skia.GetRepresentation(1.0f).sk_bitmap(),
+      bytes1x, image_skia.GetRepresentation(1.0f).GetBitmap(),
       gt::MaxColorSpaceConversionColorShift()));
-  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
-      image_skia.GetRepresentation(2.0f).sk_bitmap(),
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+      bytes2x, image_skia.GetRepresentation(2.0f).GetBitmap(),
       gt::MaxColorSpaceConversionColorShift()));
 }
 
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index 772344f9..b024849 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -63,11 +63,11 @@
 
   gfx::Size scaled_size =
       gfx::ScaleToCeiledSize(rep.pixel_size(), target_scale / rep.scale());
-  return ImageSkiaRep(skia::ImageOperations::Resize(
-      rep.sk_bitmap(),
-      skia::ImageOperations::RESIZE_LANCZOS3,
-      scaled_size.width(),
-      scaled_size.height()), target_scale);
+  return ImageSkiaRep(
+      skia::ImageOperations::Resize(rep.GetBitmap(),
+                                    skia::ImageOperations::RESIZE_LANCZOS3,
+                                    scaled_size.width(), scaled_size.height()),
+      target_scale);
 }
 
 }  // namespace
@@ -499,7 +499,7 @@
 }
 
 void ImageSkia::Init(const ImageSkiaRep& image_rep) {
-  if (image_rep.sk_bitmap().drawsNothing()) {
+  if (image_rep.GetBitmap().drawsNothing()) {
     storage_ = NULL;
     return;
   }
@@ -512,7 +512,7 @@
   if (isNull()) {
     // Callers expect a ImageSkiaRep even if it is |isNull()|.
     // TODO(pkotwicz): Fix this.
-    return NullImageRep().sk_bitmap();
+    return NullImageRep().GetBitmap();
   }
 
   // TODO(oshima): This made a few tests flaky on Windows.
@@ -523,8 +523,8 @@
 
   ImageSkiaReps::iterator it = storage_->FindRepresentation(1.0f, true);
   if (it != storage_->image_reps().end())
-    return it->sk_bitmap();
-  return NullImageRep().sk_bitmap();
+    return it->GetBitmap();
+  return NullImageRep().GetBitmap();
 }
 
 bool ImageSkia::CanRead() const {
diff --git a/ui/gfx/image/image_skia_operations.cc b/ui/gfx/image/image_skia_operations.cc
index c6928208..51743e5 100644
--- a/ui/gfx/image/image_skia_operations.cc
+++ b/ui/gfx/image/image_skia_operations.cc
@@ -119,7 +119,7 @@
       const ImageSkiaRep& first_rep,
       const ImageSkiaRep& second_rep) const override {
     SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap(
-        first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_);
+        first_rep.GetBitmap(), second_rep.GetBitmap(), alpha_);
     return ImageSkiaRep(blended, first_rep.scale());
   }
 
@@ -173,7 +173,7 @@
                          image_rep.pixel_height());
     alpha.eraseColor(SkColorSetARGB(alpha_ * 255, 0, 0, 0));
     return ImageSkiaRep(
-        SkBitmapOperations::CreateMaskedBitmap(image_rep.sk_bitmap(), alpha),
+        SkBitmapOperations::CreateMaskedBitmap(image_rep.GetBitmap(), alpha),
         image_rep.scale());
   }
 
@@ -196,7 +196,7 @@
       const ImageSkiaRep& first_rep,
       const ImageSkiaRep& second_rep) const override {
     return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap(
-        first_rep.sk_bitmap(), second_rep.sk_bitmap()),
+                            first_rep.GetBitmap(), second_rep.GetBitmap()),
                         first_rep.scale());
   }
 
@@ -223,11 +223,10 @@
     ImageSkiaRep source_rep = source_.GetRepresentation(scale);
     gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_,
                                                   dst_h_), source_rep.scale());
-    return ImageSkiaRep(
-        SkBitmapOperations::CreateTiledBitmap(
-            source_rep.sk_bitmap(),
-            bounds.x(), bounds.y(), bounds.width(), bounds.height()),
-        source_rep.scale());
+    return ImageSkiaRep(SkBitmapOperations::CreateTiledBitmap(
+                            source_rep.GetBitmap(), bounds.x(), bounds.y(),
+                            bounds.width(), bounds.height()),
+                        source_rep.scale());
   }
 
  private:
@@ -253,9 +252,9 @@
   // gfx::ImageSkiaSource overrides:
   ImageSkiaRep GetImageForScale(float scale) override {
     ImageSkiaRep image_rep = image_.GetRepresentation(scale);
-    return gfx::ImageSkiaRep(
-        SkBitmapOperations::CreateHSLShiftedBitmap(image_rep.sk_bitmap(),
-            hsl_shift_), image_rep.scale());
+    return gfx::ImageSkiaRep(SkBitmapOperations::CreateHSLShiftedBitmap(
+                                 image_rep.GetBitmap(), hsl_shift_),
+                             image_rep.scale());
   }
 
  private:
@@ -288,9 +287,9 @@
       mask_rep = mask_.GetRepresentation(1.0f);
     }
     return gfx::ImageSkiaRep(
-        SkBitmapOperations::CreateButtonBackground(color_,
-              image_rep.sk_bitmap(), mask_rep.sk_bitmap()),
-          image_rep.scale());
+        SkBitmapOperations::CreateButtonBackground(
+            color_, image_rep.GetBitmap(), mask_rep.GetBitmap()),
+        image_rep.scale());
   }
 
  private:
@@ -319,8 +318,8 @@
     SkIRect subset_bounds_in_pixel = RectToSkIRect(
         DIPToPixelBounds(subset_bounds_, image_rep.scale()));
     SkBitmap dst;
-    bool success = image_rep.sk_bitmap().extractSubset(&dst,
-                                                       subset_bounds_in_pixel);
+    bool success =
+        image_rep.GetBitmap().extractSubset(&dst, subset_bounds_in_pixel);
     DCHECK(success);
     return gfx::ImageSkiaRep(dst, image_rep.scale());
   }
@@ -354,9 +353,7 @@
 
     const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale);
     const SkBitmap resized = skia::ImageOperations::Resize(
-        image_rep.sk_bitmap(),
-        resize_method_,
-        target_pixel_size.width(),
+        image_rep.GetBitmap(), resize_method_, target_pixel_size.width(),
         target_pixel_size.height());
     return ImageSkiaRep(resized, scale);
   }
@@ -386,8 +383,7 @@
       shadows_in_pixel.push_back(shadows_in_dip_[i].Scale(scale));
 
     const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow(
-        image_rep.sk_bitmap(),
-        shadows_in_pixel);
+        image_rep.GetBitmap(), shadows_in_pixel);
     return ImageSkiaRep(shadow_bitmap, image_rep.scale());
   }
 
@@ -447,7 +443,7 @@
   ImageSkiaRep GetImageForScale(float scale) override {
     const ImageSkiaRep& image_rep = source_.GetRepresentation(scale);
     const SkBitmap rotated_bitmap =
-        SkBitmapOperations::Rotate(image_rep.sk_bitmap(), rotation_);
+        SkBitmapOperations::Rotate(image_rep.GetBitmap(), rotation_);
     return ImageSkiaRep(rotated_bitmap, image_rep.scale());
   }
 
diff --git a/ui/gfx/image/image_skia_rep.h b/ui/gfx/image/image_skia_rep.h
index 3942ad7..2595542 100644
--- a/ui/gfx/image/image_skia_rep.h
+++ b/ui/gfx/image/image_skia_rep.h
@@ -60,7 +60,7 @@
   void SetScaled();
 
   // Returns backing bitmap.
-  const SkBitmap& sk_bitmap() const { return bitmap_; }
+  const SkBitmap& GetBitmap() const { return bitmap_; }
 
 #if !defined(OS_IOS)
   const cc::PaintImage& paint_image() const { return paint_image_; }
diff --git a/ui/gfx/image/image_skia_util_ios.mm b/ui/gfx/image/image_skia_util_ios.mm
index 89b25eb..e7ac3b49 100644
--- a/ui/gfx/image/image_skia_util_ios.mm
+++ b/ui/gfx/image/image_skia_util_ios.mm
@@ -49,7 +49,7 @@
   float scale = image_skia_rep.scale();
   base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
       CGColorSpaceCreateDeviceRGB());
-  return skia::SkBitmapToUIImageWithColorSpace(image_skia_rep.sk_bitmap(),
+  return skia::SkBitmapToUIImageWithColorSpace(image_skia_rep.GetBitmap(),
                                                scale, color_space);
 }
 
diff --git a/ui/gfx/image/image_skia_util_mac.mm b/ui/gfx/image/image_skia_util_mac.mm
index b06eddf..35b3845 100644
--- a/ui/gfx/image/image_skia_util_mac.mm
+++ b/ui/gfx/image/image_skia_util_mac.mm
@@ -88,8 +88,7 @@
   std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
   for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
        it != image_reps.end(); ++it) {
-    [image addRepresentation:
-        skia::SkBitmapToNSBitmapImageRep(it->sk_bitmap())];
+    [image addRepresentation:skia::SkBitmapToNSBitmapImageRep(it->GetBitmap())];
   }
 
   [image setSize:NSMakeSize(image_skia.width(), image_skia.height())];
@@ -106,9 +105,8 @@
   std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
   for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
        it != image_reps.end(); ++it) {
-    [image addRepresentation:
-        skia::SkBitmapToNSBitmapImageRepWithColorSpace(it->sk_bitmap(),
-                                                      color_space)];
+    [image addRepresentation:skia::SkBitmapToNSBitmapImageRepWithColorSpace(
+                                 it->GetBitmap(), color_space)];
   }
 
   [image setSize:NSMakeSize(image_skia.width(), image_skia.height())];
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc
index aaad851..faa55c29 100644
--- a/ui/gfx/image/image_unittest.cc
+++ b/ui/gfx/image/image_unittest.cc
@@ -227,11 +227,11 @@
   scales.push_back(1.0f);
   scales.push_back(2.0f);
   gfx::ImageSkia image_skia = image.AsImageSkia();
-  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes1x,
-      image_skia.GetRepresentation(1.0f).sk_bitmap(),
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+      bytes1x, image_skia.GetRepresentation(1.0f).GetBitmap(),
       gt::MaxColorSpaceConversionColorShift()));
-  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
-      image_skia.GetRepresentation(2.0f).sk_bitmap(),
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+      bytes2x, image_skia.GetRepresentation(2.0f).GetBitmap(),
       gt::MaxColorSpaceConversionColorShift()));
   EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
                                             scales));
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc
index f618cee2..95cfd57f 100644
--- a/ui/gfx/image/image_unittest_util.cc
+++ b/ui/gfx/image/image_unittest_util.cc
@@ -112,7 +112,7 @@
     float scale = img1_reps[i].scale();
     const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
     if (image_rep2.scale() != scale ||
-        !AreBitmapsClose(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap(),
+        !AreBitmapsClose(img1_reps[i].GetBitmap(), image_rep2.GetBitmap(),
                          max_deviation)) {
       return false;
     }
diff --git a/ui/gfx/image/image_util.cc b/ui/gfx/image/image_util.cc
index 624620c..dc0061d 100644
--- a/ui/gfx/image/image_util.cc
+++ b/ui/gfx/image/image_util.cc
@@ -61,7 +61,7 @@
   if (image_skia_rep.scale() != 1.0f)
     return false;
 
-  const SkBitmap& bitmap = image_skia_rep.sk_bitmap();
+  const SkBitmap& bitmap = image_skia_rep.GetBitmap();
   if (!bitmap.readyToDraw())
     return false;
 
@@ -74,7 +74,7 @@
   *right = 0;
   if (!image.HasRepresentation(1.f))
     return;
-  const SkBitmap& bitmap = image.GetRepresentation(1.f).sk_bitmap();
+  const SkBitmap& bitmap = image.GetRepresentation(1.f).GetBitmap();
   if (bitmap.drawsNothing() || bitmap.isOpaque())
     return;
 
diff --git a/ui/gfx/image/mojo/image_skia_struct_traits.h b/ui/gfx/image/mojo/image_skia_struct_traits.h
index 8eabab01f..43529db 100644
--- a/ui/gfx/image/mojo/image_skia_struct_traits.h
+++ b/ui/gfx/image/mojo/image_skia_struct_traits.h
@@ -20,7 +20,7 @@
 template <>
 struct StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep> {
   static SkBitmap bitmap(const gfx::ImageSkiaRep& input) {
-    return input.sk_bitmap();
+    return input.GetBitmap();
   }
   static float scale(const gfx::ImageSkiaRep& input);
 
diff --git a/ui/gfx/image/mojo/image_traits_unittest.cc b/ui/gfx/image/mojo/image_traits_unittest.cc
index de87d86..1977989f 100644
--- a/ui/gfx/image/mojo/image_traits_unittest.cc
+++ b/ui/gfx/image/mojo/image_traits_unittest.cc
@@ -96,8 +96,8 @@
   ImageSkiaRep output(gfx::Size(1, 1), 1.0f);
   ASSERT_FALSE(output.is_null());
   service()->EchoImageSkiaRep(empty_rep, &output);
-  EXPECT_TRUE(empty_rep.sk_bitmap().drawsNothing());
-  EXPECT_TRUE(test::AreBitmapsEqual(empty_rep.sk_bitmap(), output.sk_bitmap()));
+  EXPECT_TRUE(empty_rep.GetBitmap().drawsNothing());
+  EXPECT_TRUE(test::AreBitmapsEqual(empty_rep.GetBitmap(), output.GetBitmap()));
 }
 
 TEST_F(ImageTraitsTest, ImageSkiaRep) {
@@ -108,7 +108,7 @@
 
   EXPECT_FALSE(output.is_null());
   EXPECT_EQ(image_rep.scale(), output.scale());
-  EXPECT_TRUE(test::AreBitmapsEqual(image_rep.sk_bitmap(), output.sk_bitmap()));
+  EXPECT_TRUE(test::AreBitmapsEqual(image_rep.GetBitmap(), output.GetBitmap()));
 }
 
 TEST_F(ImageTraitsTest, UnscaledImageSkiaRep) {
@@ -119,7 +119,7 @@
   EXPECT_FALSE(output.unscaled());
   service()->EchoImageSkiaRep(image_rep, &output);
   EXPECT_TRUE(output.unscaled());
-  EXPECT_TRUE(test::AreBitmapsEqual(image_rep.sk_bitmap(), output.sk_bitmap()));
+  EXPECT_TRUE(test::AreBitmapsEqual(image_rep.GetBitmap(), output.GetBitmap()));
 }
 
 TEST_F(ImageTraitsTest, NullImageSkia) {
diff --git a/ui/ozone/demo/BUILD.gn b/ui/ozone/demo/BUILD.gn
index 683e964..5b7e605 100644
--- a/ui/ozone/demo/BUILD.gn
+++ b/ui/ozone/demo/BUILD.gn
@@ -39,7 +39,7 @@
   ]
 
   if (is_fuchsia) {
-    deps += [ "//third_party/fuchsia-sdk:policy" ]
+    deps += [ "//third_party/fuchsia-sdk/sdk:policy" ]
   }
 }
 
diff --git a/ui/ozone/platform/scenic/BUILD.gn b/ui/ozone/platform/scenic/BUILD.gn
index faedc7c1..3722c13 100644
--- a/ui/ozone/platform/scenic/BUILD.gn
+++ b/ui/ozone/platform/scenic/BUILD.gn
@@ -33,12 +33,12 @@
   deps = [
     "//base",
     "//skia",
-    "//third_party/fuchsia-sdk:gfx",
-    "//third_party/fuchsia-sdk:images",
-    "//third_party/fuchsia-sdk:mem",
-    "//third_party/fuchsia-sdk:scenic",
-    "//third_party/fuchsia-sdk:viewsv1",
-    "//third_party/fuchsia-sdk:viewsv1token",
+    "//third_party/fuchsia-sdk/sdk:gfx",
+    "//third_party/fuchsia-sdk/sdk:images",
+    "//third_party/fuchsia-sdk/sdk:mem",
+    "//third_party/fuchsia-sdk/sdk:scenic",
+    "//third_party/fuchsia-sdk/sdk:viewsv1",
+    "//third_party/fuchsia-sdk/sdk:viewsv1token",
     "//ui/base",
     "//ui/display/manager",
     "//ui/events:dom_keycode_converter",
diff --git a/ui/platform_window/BUILD.gn b/ui/platform_window/BUILD.gn
index dbfac362..af5ef67 100644
--- a/ui/platform_window/BUILD.gn
+++ b/ui/platform_window/BUILD.gn
@@ -24,7 +24,7 @@
 
   if (is_fuchsia) {
     public_deps = [
-      "//third_party/fuchsia-sdk:viewsv1token",
+      "//third_party/fuchsia-sdk/sdk:viewsv1token",
     ]
   }
 }
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc
index 0c185578..1eb38138 100644
--- a/ui/views/controls/image_view.cc
+++ b/ui/views/controls/image_view.cc
@@ -21,7 +21,7 @@
 // Returns the pixels for the bitmap in |image| at scale |image_scale|.
 void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
   DCHECK_NE(0.0f, image_scale);
-  return img.GetRepresentation(image_scale).sk_bitmap().getPixels();
+  return img.GetRepresentation(image_scale).GetBitmap().getPixels();
 }
 
 }  // namespace
@@ -259,7 +259,7 @@
   gfx::Size scaled_size =
       gfx::ScaleToCeiledSize(rep.pixel_size(), scale / rep.scale());
   scaled_image_.AddRepresentation(gfx::ImageSkiaRep(
-      skia::ImageOperations::Resize(rep.sk_bitmap(),
+      skia::ImageOperations::Resize(rep.GetBitmap(),
                                     skia::ImageOperations::RESIZE_BEST,
                                     scaled_size.width(), scaled_size.height()),
       scale));
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index 74ddbc9..3923e7a 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -258,6 +258,10 @@
   // provided via other means. Providing it here would be redundant.
   // Mark the name as explicitly empty so that accessibility_checks pass.
   node_data->SetNameExplicitlyEmpty();
+  if (child_ax_tree_id_ != ui::AXTreeIDUnknown()) {
+    node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
+                                  child_ax_tree_id_);
+  }
 }
 
 gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
@@ -415,8 +419,13 @@
 }
 
 void WebView::NotifyAccessibilityWebContentsChanged() {
-  if (web_contents())
-    NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
+  content::RenderFrameHost* rfh =
+      web_contents() ? web_contents()->GetMainFrame() : nullptr;
+  if (rfh)
+    child_ax_tree_id_ = rfh->GetAXTreeID();
+  else
+    child_ax_tree_id_ = ui::AXTreeIDUnknown();
+  NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
 }
 
 std::unique_ptr<content::WebContents> WebView::CreateWebContents(
diff --git a/ui/views/controls/webview/webview.h b/ui/views/controls/webview/webview.h
index 994520b..1cd49266 100644
--- a/ui/views/controls/webview/webview.h
+++ b/ui/views/controls/webview/webview.h
@@ -211,6 +211,10 @@
   gfx::Size min_size_;
   gfx::Size max_size_;
 
+  // Tracks the child accessibility tree id which is associated with the
+  // WebContents's main RenderFrameHost.
+  ui::AXTreeID child_ax_tree_id_;
+
   DISALLOW_COPY_AND_ASSIGN(WebView);
 };
 
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc
index 4678479..4bed240 100644
--- a/ui/views/mus/mus_client.cc
+++ b/ui/views/mus/mus_client.cc
@@ -270,7 +270,7 @@
 
     // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
     gfx::ImageSkia app_icon = init_params.delegate->GetWindowAppIcon();
-    SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).sk_bitmap();
+    SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).GetBitmap();
     if (!app_bitmap.isNull()) {
       properties[WindowManager::kAppIcon_Property] =
           mojo::ConvertTo<TransportType>(app_bitmap);
@@ -278,7 +278,7 @@
 
     // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
     gfx::ImageSkia window_icon = init_params.delegate->GetWindowIcon();
-    SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).sk_bitmap();
+    SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).GetBitmap();
     if (!window_bitmap.isNull()) {
       properties[WindowManager::kWindowIcon_Property] =
           mojo::ConvertTo<TransportType>(window_bitmap);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 065d98e..453b6a5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -1933,7 +1933,7 @@
   int height = rep.GetHeight();
   data->push_back(height);
 
-  const SkBitmap& bitmap = rep.sk_bitmap();
+  const SkBitmap& bitmap = rep.GetBitmap();
 
   for (int y = 0; y < height; ++y)
     for (int x = 0; x < width; ++x)
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
index d45766b..8256304 100644
--- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
+++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
@@ -20,12 +20,11 @@
         box-sizing: border-box;
         color: var(--google-grey-700);
         font-size: 13px;
-        height: 100%;
+        height: 640px;
         line-height: 16px;
         margin: auto;
-        max-height: 640px;
-        max-width: 768px;
         padding: 60px 32px 32px 32px;
+        width: 768px;
       }
 
       iron-pages {
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html b/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
index 578e5971..a78334b5 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
@@ -35,6 +35,15 @@
         @apply --cr-input-container;
       }
 
+      #inner-input-container {
+        background-color: var(--cr-input-background-color,
+            var(--google-grey-refresh-100));
+        box-sizing: border-box;
+        padding: 0;
+
+        @apply --cr-input-inner-container;
+      }
+
       #input {
         -webkit-appearance: none;
         background-color: var(--cr-input-background-color,
diff --git a/webrunner/BUILD.gn b/webrunner/BUILD.gn
index c3f7842..7c4a04b 100644
--- a/webrunner/BUILD.gn
+++ b/webrunner/BUILD.gn
@@ -211,7 +211,6 @@
 fidl_library("fidl") {
   library_name = "web"
   namespace = "chromium"
-  namespace_path = "chromium"
 
   sources = [
     "fidl/context.fidl",
@@ -222,9 +221,9 @@
   ]
 
   public_deps = [
-    "//third_party/fuchsia-sdk:gfx",
-    "//third_party/fuchsia-sdk:sys",
-    "//third_party/fuchsia-sdk:viewsv1",
+    "//third_party/fuchsia-sdk/sdk:gfx",
+    "//third_party/fuchsia-sdk/sdk:sys",
+    "//third_party/fuchsia-sdk/sdk:viewsv1",
   ]
 }
 
diff --git a/webrunner/browser/context_impl_browsertest.cc b/webrunner/browser/context_impl_browsertest.cc
index 85f4b5d..d075a42 100644
--- a/webrunner/browser/context_impl_browsertest.cc
+++ b/webrunner/browser/context_impl_browsertest.cc
@@ -13,6 +13,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/url_constants.h"
 #include "net/cookies/cookie_store.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -33,9 +34,7 @@
 using testing::InvokeWithoutArgs;
 using testing::Mock;
 
-// Use a shorter name for NavigationEvent, because it is
-// referenced frequently in this file.
-using NavigationDetails = chromium::web::NavigationEvent;
+using chromium::web::NavigationEvent;
 
 const char kPage1Path[] = "/title1.html";
 const char kPage2Path[] = "/title2.html";
@@ -115,12 +114,14 @@
   // Navigates a |controller| to |url|, blocking until navigation is complete.
   void CheckLoadUrl(const std::string& url,
                     const std::string& expected_title,
+                    bool is_error,
                     chromium::web::NavigationController* controller) {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
                 MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, expected_title),
-                    Field(&NavigationDetails::url, url))))
+                    Field(&NavigationEvent::is_error, is_error),
+                    Field(&NavigationEvent::title, expected_title),
+                    Field(&NavigationEvent::url, url))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
     controller->LoadUrl(url, nullptr);
     run_loop.Run();
@@ -157,7 +158,28 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
 
-  CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, controller.get());
+  CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, false,
+               controller.get());
+
+  frame.Unbind();
+}
+
+// Tests that navigation errors are reported as navigation events,
+// with the original URL that caused the error.
+IN_PROC_BROWSER_TEST_F(ContextImplTest, NavigateError) {
+  chromium::web::FramePtr frame = CreateFrame();
+
+  chromium::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  CheckLoadUrl("http://unresolvable.foo.google.com/foo",
+               "unresolvable.foo.google.com/foo", true, controller.get());
+
+  CheckLoadUrl("http://unresolvable.foo.google.com/foo2",
+               "unresolvable.foo.google.com/foo2", true, controller.get());
+
+  CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, false,
+               controller.get());
 
   frame.Unbind();
 }
@@ -168,7 +190,7 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
 
-  CheckLoadUrl(kDataUrl, kDataUrl, controller.get());
+  CheckLoadUrl(kDataUrl, kDataUrl, false, controller.get());
 
   frame.Unbind();
 }
@@ -217,15 +239,15 @@
   GURL title1(embedded_test_server()->GetURL(kPage1Path));
   GURL title2(embedded_test_server()->GetURL(kPage2Path));
 
-  CheckLoadUrl(title1.spec(), kPage1Title, controller.get());
-  CheckLoadUrl(title2.spec(), kPage2Title, controller.get());
+  CheckLoadUrl(title1.spec(), kPage1Title, false, controller.get());
+  CheckLoadUrl(title2.spec(), kPage2Title, false, controller.get());
 
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
     controller->GoBack();
     run_loop.Run();
@@ -241,9 +263,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage2Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage2Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
     controller->GoForward();
     run_loop.Run();
@@ -259,8 +281,8 @@
 
 IN_PROC_BROWSER_TEST_F(ContextImplTest, ReloadFrame) {
   chromium::web::FramePtr frame = CreateFrame();
-  chromium::web::NavigationControllerPtr navigation_controller;
-  frame->GetNavigationController(navigation_controller.NewRequest());
+  chromium::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
 
   embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
       &ContextImplTest::OnServeHttpRequest, base::Unretained(this)));
@@ -269,7 +291,7 @@
   GURL url(embedded_test_server()->GetURL(kPage1Path));
 
   EXPECT_CALL(*this, OnServeHttpRequest(_));
-  CheckLoadUrl(url.spec(), kPage1Title, navigation_controller.get());
+  CheckLoadUrl(url.spec(), kPage1Title, false, controller.get());
 
   navigation_observer_.Observe(
       context_impl()->GetFrameImplForTest(&frame)->web_contents_.get());
@@ -280,7 +302,7 @@
     EXPECT_CALL(*this, OnServeHttpRequest(_));
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, url))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    navigation_controller->Reload(chromium::web::ReloadType::NO_CACHE);
+    controller->Reload(chromium::web::ReloadType::NO_CACHE);
     run_loop.Run();
     Mock::VerifyAndClearExpectations(this);
     navigation_observer_.Acknowledge();
@@ -291,7 +313,7 @@
     EXPECT_CALL(*this, OnServeHttpRequest(_));
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, url))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
-    navigation_controller->Reload(chromium::web::ReloadType::PARTIAL_CACHE);
+    controller->Reload(chromium::web::ReloadType::PARTIAL_CACHE);
     run_loop.Run();
   }
 }
@@ -322,9 +344,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
     controller->LoadUrl(title1.spec(), nullptr);
     run_loop.Run();
@@ -349,9 +371,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage2Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage2Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
     controller->LoadUrl(title2.spec(), nullptr);
     run_loop.Run();
@@ -376,9 +398,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); }));
     controller->GoBack();
     run_loop.Run();
@@ -451,9 +473,9 @@
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1));
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
     controller->LoadUrl(title1.spec(), nullptr);
     run_loop.Run();
@@ -488,9 +510,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
     controller->LoadUrl(title1.spec(), nullptr);
     run_loop.Run();
@@ -527,9 +549,9 @@
   {
     base::RunLoop run_loop;
     EXPECT_CALL(navigation_observer_,
-                MockableOnNavigationStateChanged(testing::AllOf(
-                    Field(&NavigationDetails::title, kPage1Title),
-                    Field(&NavigationDetails::url, IsSet()))))
+                MockableOnNavigationStateChanged(
+                    testing::AllOf(Field(&NavigationEvent::title, kPage1Title),
+                                   Field(&NavigationEvent::url, IsSet()))))
         .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); }));
     navigation_observer_.Acknowledge();
     run_loop.Run();
@@ -679,7 +701,8 @@
   chromium::web::NavigationControllerPtr controller;
   frame->GetNavigationController(controller.NewRequest());
 
-  CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, controller.get());
+  CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, false,
+               controller.get());
 
   frame.Unbind();
 }
diff --git a/webrunner/browser/frame_impl.cc b/webrunner/browser/frame_impl.cc
index 8227a40..ecf931ed 100644
--- a/webrunner/browser/frame_impl.cc
+++ b/webrunner/browser/frame_impl.cc
@@ -66,8 +66,10 @@
     content::NavigationEntry* entry) {
   DCHECK(entry);
   chromium::web::NavigationEntry converted;
-  converted.title = base::UTF16ToUTF8(entry->GetTitle());
+  converted.title = base::UTF16ToUTF8(entry->GetTitleForDisplay());
   converted.url = entry->GetURL().spec();
+  converted.is_error =
+      entry->GetPageType() == content::PageType::PAGE_TYPE_ERROR;
   return converted;
 }
 
@@ -91,6 +93,10 @@
     computed_event->url = new_entry.url;
   }
 
+  computed_event->is_error = new_entry.is_error;
+  if (old_entry.is_error != new_entry.is_error)
+    is_changed = true;
+
   return is_changed;
 }
 
@@ -264,11 +270,9 @@
     return;
   }
 
-  // TODO(kmarshall): Get NavigationEntry from NavigationController.
-  chromium::web::NavigationEntry current_navigation_state;
-  current_navigation_state.url = validated_url.spec();
-  current_navigation_state.title = base::UTF16ToUTF8(web_contents_->GetTitle());
-
+  chromium::web::NavigationEntry current_navigation_state =
+      ConvertContentNavigationEntry(
+          web_contents_->GetController().GetVisibleEntry());
   pending_navigation_event_is_dirty_ |=
       ComputeNavigationEvent(cached_navigation_state_, current_navigation_state,
                              &pending_navigation_event_);
diff --git a/webrunner/fidl/navigation_controller.fidl b/webrunner/fidl/navigation_controller.fidl
index 8ec8211..b781bf0 100644
--- a/webrunner/fidl/navigation_controller.fidl
+++ b/webrunner/fidl/navigation_controller.fidl
@@ -46,8 +46,9 @@
 // The Frame's navigation history can be represented as an aggregation of
 // NavigationEntries.
 struct NavigationEntry {
-  string url;    // The page's URL.
-  string title;  // The user-visible page title.
+  string url;     // The page's URL.
+  string title;   // The user-visible page title.
+  bool is_error;  // Indicates if an error occurred during this navigation.
 };
 
 enum ReloadType {
diff --git a/webrunner/fidl/navigation_event_observer.fidl b/webrunner/fidl/navigation_event_observer.fidl
index 079b918e..a0a7b70c 100644
--- a/webrunner/fidl/navigation_event_observer.fidl
+++ b/webrunner/fidl/navigation_event_observer.fidl
@@ -10,6 +10,7 @@
 struct NavigationEvent {
   string? url;
   string? title;
+  bool is_error;
 };
 
 // Interface supplied by the embedder for receiving notifications about
diff --git a/webrunner/net_http/BUILD.gn b/webrunner/net_http/BUILD.gn
index db0eeeb..5c51d980 100644
--- a/webrunner/net_http/BUILD.gn
+++ b/webrunner/net_http/BUILD.gn
@@ -21,8 +21,8 @@
   deps = [
     "//base:base",
     "//net:net",
-    "//third_party/fuchsia-sdk:oldhttp",
-    "//third_party/fuchsia-sdk:sys",
+    "//third_party/fuchsia-sdk/sdk:oldhttp",
+    "//third_party/fuchsia-sdk/sdk:sys",
   ]
 }