diff --git a/DEPS b/DEPS
index 9ed8d756..94ec2f94 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': 'd818ebf4a31724aa93fd439a2ac4195f69ae3af0',
+  'skia_revision': 'ef21d7e47963c716895684f9f397e7cbcdb845ab',
   # 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': '6856800ecfc8d4d7df19b3035fbb075c090ccd0c',
+  'v8_revision': '3166e28a2a19de790e4d7f7e5e0b756f7c5945c7',
   # 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.
@@ -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': '09646f2d0497eb4cdcf2f3843585faa9264196f4',
+  'pdfium_revision': '65f38c8fae09cf727a9ccc34587ae1ed9027b655',
   # 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': '3836c556c4c64a3820bf0656bf2b1cfcf8dbb16a',
+  'catapult_revision': '153acbd707c080919d82af77efc800b8891009bd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -540,7 +540,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a3230c43892ec837213dc2625633abf47be3ffaf',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b71f42943166f8d0e3993e65f05d2f4dc974e38b',
       'condition': 'checkout_linux',
   },
 
@@ -565,7 +565,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '621c9d28c3d08488bbd378a97f5cbfacdf5853ed',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '605dd3126a6c94eef6868fdaac977765905afb7a',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -913,7 +913,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'b56a7a2a1a622584fa9c32b1285589c24f7eec3e',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'ce3f7b384d77f66d760bf07eeadeb4b66f239c98',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -929,6 +929,9 @@
   'src/third_party/pyftpdlib/src':
     Var('chromium_git') + '/external/pyftpdlib.git' + '@' + '2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
 
+  'src/third_party/quic_trace/src':
+    Var('chromium_git') + '/external/github.com/google/quic-trace.git' + '@' + 'c9028909ba2356e073de4ea963b56fd81417a46d',
+
   'src/third_party/pywebsocket/src':
     Var('chromium_git') + '/external/github.com/google/pywebsocket.git' + '@' + '2d7b73c3acbd0f41dcab487ae5c97c6feae06ce2',
 
@@ -1032,7 +1035,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a5c263cc63ffc2cc189b5214074c8792067c1853',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '5c71e74331bd57dd94be6d66d7490c1a95154e48',
+    Var('webrtc_git') + '/src.git' + '@' + '312466a20450cc22765ed91a3ed3ca7adcad37c0',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1066,7 +1069,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e8384f5d76c307b86f2adc4d3064d4a040ac9f40',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c9b520351974c3f9cc476336b4596127386e46e4',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/app_menu/app_menu_model_adapter.cc b/ash/app_menu/app_menu_model_adapter.cc
index 16889ffc..f078e82 100644
--- a/ash/app_menu/app_menu_model_adapter.cc
+++ b/ash/app_menu/app_menu_model_adapter.cc
@@ -54,8 +54,7 @@
   root_ = CreateMenu();
   if (features::IsNotificationIndicatorEnabled()) {
     notification_menu_controller_ =
-        std::make_unique<NotificationMenuController>(app_id_, root_,
-                                                     model_.get());
+        std::make_unique<NotificationMenuController>(app_id_, root_, this);
   }
   menu_runner_ = std::make_unique<views::MenuRunner>(root_, run_types);
   menu_runner_->RunMenuAt(menu_owner_->GetWidget(), nullptr /* MenuButton */,
diff --git a/ash/app_menu/app_menu_model_adapter.h b/ash/app_menu/app_menu_model_adapter.h
index a53870f..9b41100 100644
--- a/ash/app_menu/app_menu_model_adapter.h
+++ b/ash/app_menu/app_menu_model_adapter.h
@@ -54,14 +54,13 @@
   void ExecuteCommand(int id, int mouse_event_flags) override;
   void OnMenuClosed(views::MenuItemView* menu) override;
 
+  ui::SimpleMenuModel* model() { return model_.get(); }
+
  protected:
   const std::string& app_id() const { return app_id_; }
   base::TimeTicks menu_open_time() const { return menu_open_time_; }
   ui::MenuSourceType source_type() const { return source_type_; }
 
-  ui::SimpleMenuModel* model() { return model_.get(); }
-  const ui::SimpleMenuModel* model() const { return model_.get(); }
-
   // Helper method to record ExecuteCommand() histograms.
   void RecordExecuteCommandHistogram(int command_id);
 
diff --git a/ash/app_menu/notification_item_view.cc b/ash/app_menu/notification_item_view.cc
index 82c53a4..ccabec0d 100644
--- a/ash/app_menu/notification_item_view.cc
+++ b/ash/app_menu/notification_item_view.cc
@@ -9,6 +9,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/text_elider.h"
 #include "ui/message_center/views/proportional_image_view.h"
+#include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/menu/menu_config.h"
@@ -38,14 +39,31 @@
 
 }  // namespace
 
-NotificationItemView::NotificationItemView(const base::string16& title,
-                                           const base::string16& message,
-                                           const gfx::Image& icon,
-                                           const std::string notification_id)
-    : title_(title), message_(message), notification_id_(notification_id) {
+NotificationItemView::NotificationItemView(
+    NotificationItemView::Delegate* delegate,
+    message_center::SlideOutController::Delegate* slide_out_controller_delegate,
+    const base::string16& title,
+    const base::string16& message,
+    const gfx::Image& icon,
+    const std::string& notification_id)
+    : delegate_(delegate),
+      slide_out_controller_(
+          std::make_unique<message_center::SlideOutController>(
+              this,
+              slide_out_controller_delegate)),
+      title_(title),
+      message_(message),
+      notification_id_(notification_id) {
+  DCHECK(delegate_);
+  DCHECK(slide_out_controller_delegate);
+
+  // Paint to a new layer so |slide_out_controller_| can control the opacity.
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(true);
   SetBorder(views::CreateEmptyBorder(
       gfx::Insets(kNotificationVerticalPadding, kNotificationHorizontalPadding,
                   kNotificationVerticalPadding, kIconHorizontalPadding)));
+  SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
 
   text_container_ = new views::View();
   text_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
@@ -100,4 +118,35 @@
       kProportionalIconViewSize.height());
 }
 
+bool NotificationItemView::OnMousePressed(const ui::MouseEvent& event) {
+  return true;
+}
+
+bool NotificationItemView::OnMouseDragged(const ui::MouseEvent& event) {
+  return true;
+}
+
+void NotificationItemView::OnMouseReleased(const ui::MouseEvent& event) {
+  gfx::Point location(event.location());
+  views::View::ConvertPointToScreen(this, &location);
+  if (!event.IsOnlyLeftMouseButton() ||
+      !GetBoundsInScreen().Contains(location)) {
+    return;
+  }
+
+  delegate_->ActivateNotificationAndClose(notification_id_);
+}
+
+void NotificationItemView::OnGestureEvent(ui::GestureEvent* event) {
+  // Drag gestures are handled by |slide_out_controller_|.
+  switch (event->type()) {
+    case ui::ET_GESTURE_TAP:
+      event->SetHandled();
+      delegate_->ActivateNotificationAndClose(notification_id_);
+      return;
+    default:
+      return;
+  }
+}
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_item_view.h b/ash/app_menu/notification_item_view.h
index bf08818..242ffa1 100644
--- a/ash/app_menu/notification_item_view.h
+++ b/ash/app_menu/notification_item_view.h
@@ -5,10 +5,12 @@
 #ifndef ASH_APP_MENU_NOTIFICATION_ITEM_VIEW_H_
 #define ASH_APP_MENU_NOTIFICATION_ITEM_VIEW_H_
 
+#include <memory>
 #include <string>
 
 #include "ash/app_menu/app_menu_export.h"
 #include "base/strings/string16.h"
+#include "ui/message_center/views/slide_out_controller.h"
 #include "ui/views/view.h"
 
 namespace gfx {
@@ -25,16 +27,32 @@
 // The view which contains the details of a notification.
 class APP_MENU_EXPORT NotificationItemView : public views::View {
  public:
-  NotificationItemView(const base::string16& title,
+  // Used to activate NotificationItemView.
+  class Delegate {
+   public:
+    // Activates the notification corresponding with |notification_id| and
+    // closes the menu.
+    virtual void ActivateNotificationAndClose(
+        const std::string& notification_id) = 0;
+  };
+
+  NotificationItemView(NotificationItemView::Delegate* delegate,
+                       message_center::SlideOutController::Delegate*
+                           slide_out_controller_delegate,
+                       const base::string16& title,
                        const base::string16& message,
                        const gfx::Image& icon,
-                       const std::string notification_id);
+                       const std::string& notification_id);
 
   ~NotificationItemView() override;
 
   // views::View overrides:
   gfx::Size CalculatePreferredSize() const override;
   void Layout() override;
+  bool OnMousePressed(const ui::MouseEvent& event) override;
+  bool OnMouseDragged(const ui::MouseEvent& event) override;
+  void OnMouseReleased(const ui::MouseEvent& event) override;
+  void OnGestureEvent(ui::GestureEvent* event) override;
 
   const std::string& notification_id() const { return notification_id_; }
   const base::string16& title() const { return title_; }
@@ -47,6 +65,12 @@
   // Holds the notification's icon. Owned by the views hierarchy.
   message_center::ProportionalImageView* proportional_icon_view_ = nullptr;
 
+  // Owned by AppMenuModelAdapter. Used to activate notifications.
+  Delegate* const delegate_;
+
+  // Controls the sideways gesture drag behavior.
+  std::unique_ptr<message_center::SlideOutController> slide_out_controller_;
+
   // Notification properties.
   const base::string16 title_;
   const base::string16 message_;
diff --git a/ash/app_menu/notification_menu_controller.cc b/ash/app_menu/notification_menu_controller.cc
index e45473f..8f2cfce 100644
--- a/ash/app_menu/notification_menu_controller.cc
+++ b/ash/app_menu/notification_menu_controller.cc
@@ -4,6 +4,7 @@
 
 #include "ash/app_menu/notification_menu_controller.h"
 
+#include "ash/app_menu/app_menu_model_adapter.h"
 #include "ash/app_menu/notification_menu_view.h"
 #include "ash/public/cpp/app_menu_constants.h"
 #include "ui/views/controls/menu/menu_item_view.h"
@@ -14,11 +15,12 @@
 NotificationMenuController::NotificationMenuController(
     const std::string& app_id,
     views::MenuItemView* root_menu,
-    ui::SimpleMenuModel* model)
+    AppMenuModelAdapter* app_menu_model_adapter)
     : app_id_(app_id),
       root_menu_(root_menu),
-      model_(model),
+      app_menu_model_adapter_(app_menu_model_adapter),
       message_center_observer_(this) {
+  DCHECK(app_menu_model_adapter_);
   message_center_observer_.Add(message_center::MessageCenter::Get());
   InitializeNotificationMenuView();
 }
@@ -60,9 +62,9 @@
   // |root_menu_|, and remove the entry from the model.
   const views::View* container = notification_menu_view_->parent();
   root_menu_->RemoveMenuItemAt(root_menu_->GetSubmenu()->GetIndexOf(container));
-  // TODO(newcomer): move NOTIFICATION_CONTAINER and other CommandId enums to a
-  // shared constant file in ash/public/cpp.
-  model_->RemoveItemAt(model_->GetIndexOfCommandId(NOTIFICATION_CONTAINER));
+  app_menu_model_adapter_->model()->RemoveItemAt(
+      app_menu_model_adapter_->model()->GetIndexOfCommandId(
+          NOTIFICATION_CONTAINER));
   notification_menu_view_ = nullptr;
 
   // Notify the root MenuItemView so it knows to resize and re-calculate the
@@ -70,6 +72,28 @@
   root_menu_->ChildrenChanged();
 }
 
+ui::Layer* NotificationMenuController::GetSlideOutLayer() {
+  return notification_menu_view_ ? notification_menu_view_->GetSlideOutLayer()
+                                 : nullptr;
+}
+
+void NotificationMenuController::OnSlideChanged() {}
+
+void NotificationMenuController::OnSlideOut() {
+  // Results in |this| being deleted if there are no more notifications to show.
+  // Only the displayed NotificationItemView can call OnSlideOut.
+  message_center::MessageCenter::Get()->RemoveNotification(
+      notification_menu_view_->GetDisplayedNotificationID(), true);
+}
+
+void NotificationMenuController::ActivateNotificationAndClose(
+    const std::string& notification_id) {
+  message_center::MessageCenter::Get()->ClickOnNotification(notification_id);
+
+  // Results in |this| being deleted.
+  app_menu_model_adapter_->Cancel();
+}
+
 void NotificationMenuController::InitializeNotificationMenuView() {
   DCHECK(!notification_menu_view_);
 
@@ -80,11 +104,12 @@
     return;
   }
 
-  model_->AddItem(NOTIFICATION_CONTAINER, base::string16());
+  app_menu_model_adapter_->model()->AddItem(NOTIFICATION_CONTAINER,
+                                            base::string16());
   // Add the container MenuItemView to |root_menu_|.
   views::MenuItemView* container = root_menu_->AppendMenuItem(
       NOTIFICATION_CONTAINER, base::string16(), views::MenuItemView::NORMAL);
-  notification_menu_view_ = new NotificationMenuView(app_id_);
+  notification_menu_view_ = new NotificationMenuView(this, this, app_id_);
   container->AddChildView(notification_menu_view_);
 
   for (auto* notification :
diff --git a/ash/app_menu/notification_menu_controller.h b/ash/app_menu/notification_menu_controller.h
index bfe0693..630bd53 100644
--- a/ash/app_menu/notification_menu_controller.h
+++ b/ash/app_menu/notification_menu_controller.h
@@ -6,13 +6,11 @@
 #define ASH_APP_MENU_NOTIFICATION_MENU_CONTROLLER_H_
 
 #include "ash/app_menu/app_menu_export.h"
+#include "ash/app_menu/notification_item_view.h"
 #include "base/scoped_observer.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_observer.h"
-
-namespace ui {
-class SimpleMenuModel;
-}
+#include "ui/message_center/views/slide_out_controller.h"
 
 namespace views {
 class MenuItemView;
@@ -20,17 +18,20 @@
 
 namespace ash {
 
+class AppMenuModelAdapter;
 class NotificationMenuView;
 
 // Handles adding/removing NotificationMenuView from the root MenuItemView,
 // adding the container model entry, and updating the NotificationMenuView
 // as notifications come and go.
 class APP_MENU_EXPORT NotificationMenuController
-    : public message_center::MessageCenterObserver {
+    : public message_center::MessageCenterObserver,
+      public message_center::SlideOutController::Delegate,
+      public NotificationItemView::Delegate {
  public:
   NotificationMenuController(const std::string& app_id,
                              views::MenuItemView* root_menu,
-                             ui::SimpleMenuModel* model);
+                             AppMenuModelAdapter* app_menu_model_adapter);
 
   ~NotificationMenuController() override;
 
@@ -39,6 +40,15 @@
   void OnNotificationRemoved(const std::string& notification_id,
                              bool by_user) override;
 
+  // message_center::SlideOutController::Delegate overrides:
+  ui::Layer* GetSlideOutLayer() override;
+  void OnSlideChanged() override;
+  void OnSlideOut() override;
+
+  // NotificationItemView::Delegate overrides:
+  void ActivateNotificationAndClose(
+      const std::string& notification_id) override;
+
  private:
   // Adds a container MenuItemView to |root_menu_|, adds NOTIFICATION_CONTAINER
   // to |model_|, creates and initializes NotificationMenuView, and adds
@@ -51,8 +61,8 @@
   // The top level MenuItemView. Owned by |AppMenuModelAdapter::menu_runner_|.
   views::MenuItemView* const root_menu_;
 
-  // Owned by AppMenuModelAdapter.
-  ui::SimpleMenuModel* const model_;
+  // Manages showing the menu. Owned by the view requesting a menu.
+  AppMenuModelAdapter* const app_menu_model_adapter_;
 
   // The view which shows all active notifications for |app_id_|. Owned by the
   // views hierarchy.
diff --git a/ash/app_menu/notification_menu_controller_unittest.cc b/ash/app_menu/notification_menu_controller_unittest.cc
index 1d35e5f..5c5c94b 100644
--- a/ash/app_menu/notification_menu_controller_unittest.cc
+++ b/ash/app_menu/notification_menu_controller_unittest.cc
@@ -13,7 +13,6 @@
 #include "ui/views/controls/menu/submenu_view.h"
 
 namespace ash {
-namespace test {
 namespace {
 
 constexpr char kTestAppId[] = "test-app-id";
@@ -33,6 +32,23 @@
       std::move(notification));
 }
 
+class TestAppMenuModelAdapter : public AppMenuModelAdapter {
+ public:
+  TestAppMenuModelAdapter(const std::string& app_id,
+                          std::unique_ptr<ui::SimpleMenuModel> model)
+      : AppMenuModelAdapter(app_id,
+                            std::move(model),
+                            nullptr,
+                            ui::MENU_SOURCE_TYPE_LAST,
+                            base::OnceClosure()) {}
+
+ private:
+  // AppMenuModelAdapter overrides:
+  void RecordHistogramOnMenuClosed() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(TestAppMenuModelAdapter);
+};
+
 }  // namespace
 
 class NotificationMenuControllerTest : public AshTestBase {
@@ -50,20 +66,25 @@
   }
 
   void BuildMenu() {
-    model_ = std::make_unique<ui::SimpleMenuModel>(
-        nullptr /*ui::SimpleMenuModel::Delegate not required*/);
-    model_->AddItem(0, base::ASCIIToUTF16("item 1"));
-    model_->AddItem(1, base::ASCIIToUTF16("item 2"));
+    test_app_menu_model_adapter_ = std::make_unique<TestAppMenuModelAdapter>(
+        kTestAppId,
+        std::make_unique<ui::SimpleMenuModel>(
+            nullptr /*ui::SimpleMenuModel::Delegate not required*/));
+    test_app_menu_model_adapter_->model()->AddItem(
+        0, base::ASCIIToUTF16("item 0"));
+    test_app_menu_model_adapter_->model()->AddItem(
+        1, base::ASCIIToUTF16("item 1"));
 
-    delegate_ = std::make_unique<views::MenuModelAdapter>(model_.get());
-    root_menu_item_view_ = new views::MenuItemView(delegate_.get());
+    root_menu_item_view_ =
+        new views::MenuItemView(test_app_menu_model_adapter_.get());
     host_view_ = std::make_unique<views::View>();
     host_view_->AddChildView(root_menu_item_view_);
-    delegate_->BuildMenu(root_menu_item_view_);
+    test_app_menu_model_adapter_->BuildMenu(root_menu_item_view_);
 
     notification_menu_controller_ =
         std::make_unique<NotificationMenuController>(
-            kTestAppId, root_menu_item_view_, model_.get());
+            kTestAppId, root_menu_item_view_,
+            test_app_menu_model_adapter_.get());
   }
 
   views::MenuItemView* root_menu_item_view() { return root_menu_item_view_; }
@@ -74,8 +95,7 @@
   // Allows the dtor to access the restricted views::MenuItemView dtor.
   std::unique_ptr<views::View> host_view_;
   std::unique_ptr<NotificationMenuController> notification_menu_controller_;
-  std::unique_ptr<ui::SimpleMenuModel> model_;
-  std::unique_ptr<views::MenuModelAdapter> delegate_;
+  std::unique_ptr<TestAppMenuModelAdapter> test_app_menu_model_adapter_;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationMenuControllerTest);
 };
@@ -152,5 +172,4 @@
   EXPECT_EQ(2, root_menu_item_view()->GetSubmenu()->child_count());
 }
 
-}  // namespace test
 }  // namespace ash
diff --git a/ash/app_menu/notification_menu_view.cc b/ash/app_menu/notification_menu_view.cc
index ee5237a..cfc8d35 100644
--- a/ash/app_menu/notification_menu_view.cc
+++ b/ash/app_menu/notification_menu_view.cc
@@ -15,10 +15,19 @@
 
 namespace ash {
 
-NotificationMenuView::NotificationMenuView(const std::string& app_id)
-    : app_id_(app_id) {
+NotificationMenuView::NotificationMenuView(
+
+    NotificationItemView::Delegate* notification_item_view_delegate,
+    message_center::SlideOutController::Delegate* slide_out_controller_delegate,
+    const std::string& app_id)
+    : app_id_(app_id),
+      notification_item_view_delegate_(notification_item_view_delegate),
+      slide_out_controller_delegate_(slide_out_controller_delegate) {
+  DCHECK(notification_item_view_delegate_);
+  DCHECK(slide_out_controller_delegate_);
   DCHECK(!app_id_.empty())
       << "Only context menus for applications can show notifications.";
+
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical));
 
@@ -46,6 +55,7 @@
     RemoveChildView(notification_item_views_.front().get());
 
   notification_item_views_.push_front(std::make_unique<NotificationItemView>(
+      notification_item_view_delegate_, slide_out_controller_delegate_,
       notification.title(), notification.message(), notification.icon(),
       notification.id()));
   notification_item_views_.front()->set_owned_by_client();
@@ -74,4 +84,15 @@
     AddChildView(notification_item_views_.front().get());
 }
 
+ui::Layer* NotificationMenuView::GetSlideOutLayer() {
+  if (notification_item_views_.empty())
+    return nullptr;
+  return notification_item_views_.front()->layer();
+}
+
+const std::string& NotificationMenuView::GetDisplayedNotificationID() {
+  DCHECK(!notification_item_views_.empty());
+  return notification_item_views_.front()->notification_id();
+}
+
 }  // namespace ash
diff --git a/ash/app_menu/notification_menu_view.h b/ash/app_menu/notification_menu_view.h
index 36216d8..145326f 100644
--- a/ash/app_menu/notification_menu_view.h
+++ b/ash/app_menu/notification_menu_view.h
@@ -9,6 +9,8 @@
 #include <string>
 
 #include "ash/app_menu/app_menu_export.h"
+#include "ash/app_menu/notification_item_view.h"
+#include "ui/message_center/views/slide_out_controller.h"
 #include "ui/views/view.h"
 
 namespace message_center {
@@ -18,13 +20,16 @@
 namespace ash {
 
 class NotificationMenuHeaderView;
-class NotificationItemView;
 
 // A view inserted into a container MenuItemView which shows a
 // NotificationItemView and a NotificationMenuHeaderView.
 class APP_MENU_EXPORT NotificationMenuView : public views::View {
  public:
-  explicit NotificationMenuView(const std::string& app_id);
+  explicit NotificationMenuView(
+      NotificationItemView::Delegate* notification_item_view_delegate,
+      message_center::SlideOutController::Delegate*
+          slide_out_controller_delegate,
+      const std::string& app_id);
   ~NotificationMenuView() override;
 
   // Whether |notifications_for_this_app_| is empty.
@@ -40,6 +45,12 @@
   // next one if available.
   void RemoveNotificationItemView(const std::string& notification_id);
 
+  // Gets the slide out layer, used to move the displayed NotificationItemView.
+  ui::Layer* GetSlideOutLayer();
+
+  // Gets the notification id of the displayed NotificationItemView.
+  const std::string& GetDisplayedNotificationID();
+
   // views::View overrides:
   gfx::Size CalculatePreferredSize() const override;
 
@@ -49,6 +60,13 @@
   // Identifies the app for this menu.
   const std::string app_id_;
 
+  // Owned by AppMenuModelAdapter.
+  NotificationItemView::Delegate* const notification_item_view_delegate_;
+
+  // Owned by AppMenuModelAdapter.
+  message_center::SlideOutController::Delegate* const
+      slide_out_controller_delegate_;
+
   // The deque of NotificationItemViews. The front item in the deque is the view
   // which is shown.
   std::deque<std::unique_ptr<NotificationItemView>> notification_item_views_;
diff --git a/ash/app_menu/notification_menu_view_unittest.cc b/ash/app_menu/notification_menu_view_unittest.cc
index 2fa893ef..252f08a 100644
--- a/ash/app_menu/notification_menu_view_unittest.cc
+++ b/ash/app_menu/notification_menu_view_unittest.cc
@@ -9,19 +9,57 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/gfx/transform.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/view.h"
+#include "ui/views/widget/widget_delegate.h"
 
 namespace ash {
-namespace test {
 
 namespace {
 
 // The app id used in tests.
 constexpr char kTestAppId[] = "test-app-id";
 
+class MockNotificationMenuController
+    : public message_center::SlideOutController::Delegate,
+      public NotificationItemView::Delegate {
+ public:
+  MockNotificationMenuController() = default;
+  virtual ~MockNotificationMenuController() = default;
+
+  void ActivateNotificationAndClose(
+      const std::string& notification_id) override {
+    activation_count_++;
+  }
+
+  ui::Layer* GetSlideOutLayer() override {
+    return notification_menu_view_->GetSlideOutLayer();
+  }
+
+  void OnSlideChanged() override {}
+
+  void OnSlideOut() override { slide_out_count_++; }
+
+  void set_notification_menu_view(
+      NotificationMenuView* notification_menu_view) {
+    notification_menu_view_ = notification_menu_view;
+  }
+
+  int slide_out_count_ = 0;
+  int activation_count_ = 0;
+
+  // Owned by NotificationMenuViewTest.
+  NotificationMenuView* notification_menu_view_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(MockNotificationMenuController);
+};
+
 }  // namespace
 
 class NotificationMenuViewTest : public views::ViewsTestBase {
@@ -32,10 +70,45 @@
   // views::ViewsTestBase:
   void SetUp() override {
     views::ViewsTestBase::SetUp();
-    notification_menu_view_ =
-        std::make_unique<NotificationMenuView>(kTestAppId);
+
+    zero_duration_scope_ =
+        std::make_unique<ui::ScopedAnimationDurationScaleMode>(
+            ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+
+    mock_notification_menu_controller_ =
+        std::make_unique<MockNotificationMenuController>();
+
+    notification_menu_view_ = std::make_unique<NotificationMenuView>(
+        mock_notification_menu_controller_.get(),
+        mock_notification_menu_controller_.get(), kTestAppId);
+    notification_menu_view_->set_owned_by_client();
+
+    // Set the NotificationMenuView so |mock_notification_menu_controller_|
+    // can get the slide out layer. In production NotificationMenuController is
+    // the NotificationItemViewDelegate, and it gets a reference to
+    // NotificationMenuView when it is created.
+    mock_notification_menu_controller_->set_notification_menu_view(
+        notification_menu_view());
+
     test_api_ = std::make_unique<NotificationMenuViewTestAPI>(
         notification_menu_view_.get());
+
+    widget_ = std::make_unique<views::Widget>();
+    views::Widget::InitParams init_params(
+        CreateParams(views::Widget::InitParams::TYPE_POPUP));
+    init_params.ownership =
+        views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    init_params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+    widget_->Init(init_params);
+    widget_->SetContentsView(notification_menu_view_.get());
+    widget_->SetSize(notification_menu_view_->GetPreferredSize());
+    widget_->Show();
+    widget_->Activate();
+  }
+
+  void TearDown() override {
+    widget_->Close();
+    views::ViewsTestBase::TearDown();
   }
 
   message_center::Notification AddNotification(
@@ -50,6 +123,7 @@
         notifier_id, message_center::RichNotificationData(),
         nullptr /* delegate */);
     notification_menu_view_->AddNotificationItemView(notification);
+    notification_menu_view_->Layout();
     return notification;
   }
 
@@ -64,15 +138,54 @@
     EXPECT_EQ(item_view->message(), notification.message());
   }
 
+  void BeginScroll() {
+    DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
+  }
+
+  void EndScroll() {
+    DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+  }
+
+  void ScrollBy(int dx) {
+    DispatchGesture(
+        ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, dx, 0));
+  }
+
+  void DispatchGesture(const ui::GestureEventDetails& details) {
+    ui::test::EventGenerator generator(
+        notification_menu_view_->GetWidget()->GetNativeWindow());
+
+    ui::GestureEvent event(
+        0,
+        test_api()->GetDisplayedNotificationItemView()->GetBoundsInScreen().y(),
+        0, ui::EventTimeForNow(), details);
+    generator.Dispatch(&event);
+  }
+
+  float GetSlideAmount() const {
+    return notification_menu_view_->GetSlideOutLayer()
+        ->transform()
+        .To2dTranslation()
+        .x();
+  }
+
   NotificationMenuView* notification_menu_view() {
     return notification_menu_view_.get();
   }
 
   NotificationMenuViewTestAPI* test_api() { return test_api_.get(); }
 
+  MockNotificationMenuController* mock_notification_menu_controller() {
+    return mock_notification_menu_controller_.get();
+  }
+
  private:
+  std::unique_ptr<MockNotificationMenuController>
+      mock_notification_menu_controller_;
   std::unique_ptr<NotificationMenuView> notification_menu_view_;
   std::unique_ptr<NotificationMenuViewTestAPI> test_api_;
+  std::unique_ptr<views::Widget> widget_;
+  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_scope_;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationMenuViewTest);
 };
@@ -132,5 +245,92 @@
   CheckDisplayedNotification(notification_1);
 }
 
-}  // namespace test
+// Tests that the displayed NotificationItemView is only dismissed when dragged
+// beyond the threshold.
+TEST_F(NotificationMenuViewTest, SlideOut) {
+  AddNotification("notification_id", base::ASCIIToUTF16("title"),
+                  base::ASCIIToUTF16("message"));
+
+  EXPECT_EQ(0, mock_notification_menu_controller()->slide_out_count_);
+
+  BeginScroll();
+  // Scroll by a small amount, the notification should move but not slide out.
+  ScrollBy(-10);
+  EXPECT_EQ(0, mock_notification_menu_controller()->slide_out_count_);
+  EXPECT_EQ(-10.f, GetSlideAmount());
+
+  // End the scroll gesture, the notifications should return to its resting
+  // place.
+  EndScroll();
+  EXPECT_EQ(0, mock_notification_menu_controller()->slide_out_count_);
+  EXPECT_EQ(0.f, GetSlideAmount());
+
+  BeginScroll();
+  // Scroll beyond the threshold but do not release the gesture scroll.
+  ScrollBy(-200);
+  EXPECT_EQ(-200.f, GetSlideAmount());
+  // Release the gesture, the notification should slide out.
+  EndScroll();
+  EXPECT_EQ(1, mock_notification_menu_controller()->slide_out_count_);
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+}
+
+// Tests that tapping a notification activates it.
+TEST_F(NotificationMenuViewTest, TapNotification) {
+  AddNotification("notification_id", base::ASCIIToUTF16("title"),
+                  base::ASCIIToUTF16("message"));
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+  DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_TAP));
+
+  EXPECT_EQ(1, mock_notification_menu_controller()->activation_count_);
+}
+
+// Tests that an in bounds mouse release activates a notification.
+TEST_F(NotificationMenuViewTest, ClickNotification) {
+  AddNotification("notification_id", base::ASCIIToUTF16("title"),
+                  base::ASCIIToUTF16("message"));
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+
+  const gfx::Point cursor_location = test_api()
+                                         ->GetDisplayedNotificationItemView()
+                                         ->GetBoundsInScreen()
+                                         .origin();
+  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, cursor_location, cursor_location,
+                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+                       ui::EF_NONE);
+  notification_menu_view()->GetWidget()->OnMouseEvent(&press);
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+
+  ui::MouseEvent release(ui::ET_MOUSE_RELEASED, cursor_location,
+                         cursor_location, ui::EventTimeForNow(),
+                         ui::EF_LEFT_MOUSE_BUTTON, ui::EF_NONE);
+  notification_menu_view()->GetWidget()->OnMouseEvent(&release);
+  EXPECT_EQ(1, mock_notification_menu_controller()->activation_count_);
+}
+
+// Tests that an out of bounds mouse release does not activate a notification.
+TEST_F(NotificationMenuViewTest, OutOfBoundsClick) {
+  AddNotification("notification_id", base::ASCIIToUTF16("title"),
+                  base::ASCIIToUTF16("message"));
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+
+  const gfx::Point cursor_location = test_api()
+                                         ->GetDisplayedNotificationItemView()
+                                         ->GetBoundsInScreen()
+                                         .origin();
+  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, cursor_location, cursor_location,
+                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+                       ui::EF_NONE);
+  notification_menu_view()->GetWidget()->OnMouseEvent(&press);
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+
+  const gfx::Point out_of_bounds;
+  ui::MouseEvent out_of_bounds_release(ui::ET_MOUSE_RELEASED, out_of_bounds,
+                                       out_of_bounds, ui::EventTimeForNow(),
+                                       ui::EF_LEFT_MOUSE_BUTTON, ui::EF_NONE);
+  notification_menu_view()->GetWidget()->OnMouseEvent(&out_of_bounds_release);
+
+  EXPECT_EQ(0, mock_notification_menu_controller()->activation_count_);
+}
+
 }  // namespace ash
diff --git a/ash/frame/caption_buttons/frame_caption_button.h b/ash/frame/caption_buttons/frame_caption_button.h
index 99b3f5d..99ad84d 100644
--- a/ash/frame/caption_buttons/frame_caption_button.h
+++ b/ash/frame/caption_buttons/frame_caption_button.h
@@ -25,7 +25,11 @@
 class ASH_EXPORT FrameCaptionButton : public views::Button {
  public:
   enum Animate { ANIMATE_YES, ANIMATE_NO };
-  enum class ColorMode { kDefault, kThemed };
+
+  enum class ColorMode {
+    kDefault,  // Most windows.
+    kThemed,   // Windows that have been themed by PWA manifest.
+  };
 
   static const char kViewClassName[];
 
diff --git a/ash/frame/default_frame_header.cc b/ash/frame/default_frame_header.cc
index ce37b32..b6b9bb7d 100644
--- a/ash/frame/default_frame_header.cc
+++ b/ash/frame/default_frame_header.cc
@@ -101,11 +101,6 @@
 
 DefaultFrameHeader::~DefaultFrameHeader() = default;
 
-void DefaultFrameHeader::SetThemeColor(SkColor theme_color) {
-  set_button_color_mode(FrameCaptionButton::ColorMode::kThemed);
-  SetFrameColorsImpl(theme_color, theme_color);
-}
-
 void DefaultFrameHeader::SetWidthInPixels(int width_in_pixels) {
   if (width_in_pixels_ == width_in_pixels)
     return;
@@ -144,24 +139,6 @@
 
 void DefaultFrameHeader::DoSetFrameColors(SkColor active_frame_color,
                                           SkColor inactive_frame_color) {
-  set_button_color_mode(FrameCaptionButton::ColorMode::kDefault);
-  SetFrameColorsImpl(active_frame_color, inactive_frame_color);
-}
-
-AshLayoutSize DefaultFrameHeader::GetButtonLayoutSize() const {
-  return AshLayoutSize::kNonBrowserCaption;
-}
-
-SkColor DefaultFrameHeader::GetTitleColor() const {
-  return color_utils::IsDark(GetCurrentFrameColor()) ? kLightTitleTextColor
-                                                     : kTitleTextColor;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DefaultFrameHeader, private:
-
-void DefaultFrameHeader::SetFrameColorsImpl(SkColor active_frame_color,
-                                            SkColor inactive_frame_color) {
   bool updated = false;
   if (active_frame_color_.target_color() != active_frame_color) {
     active_frame_color_.SetTargetColor(active_frame_color);
@@ -178,6 +155,18 @@
   }
 }
 
+AshLayoutSize DefaultFrameHeader::GetButtonLayoutSize() const {
+  return AshLayoutSize::kNonBrowserCaption;
+}
+
+SkColor DefaultFrameHeader::GetTitleColor() const {
+  return color_utils::IsDark(GetCurrentFrameColor()) ? kLightTitleTextColor
+                                                     : kTitleTextColor;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DefaultFrameHeader, private:
+
 SkColor DefaultFrameHeader::GetCurrentFrameColor() const {
   return mode() == MODE_ACTIVE ? active_frame_color_.target_color()
                                : inactive_frame_color_.target_color();
diff --git a/ash/frame/default_frame_header.h b/ash/frame/default_frame_header.h
index c8e1e90..1c176ac 100644
--- a/ash/frame/default_frame_header.h
+++ b/ash/frame/default_frame_header.h
@@ -26,8 +26,6 @@
                      FrameCaptionButtonContainerView* caption_button_container);
   ~DefaultFrameHeader() override;
 
-  void SetThemeColor(SkColor theme_color);
-
   SkColor active_frame_color_for_testing() {
     return active_frame_color_.target_color();
   }
@@ -48,10 +46,6 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, FrameColors);
 
-  // Updates the frame colors and ensures buttons are up to date.
-  void SetFrameColorsImpl(SkColor active_frame_color,
-                          SkColor inactive_frame_color);
-
   gfx::SlideAnimation* GetAnimationForActiveFrameColorForTest();
   SkColor GetActiveFrameColorForPaintForTest();
 
@@ -72,7 +66,6 @@
     gfx::SlideAnimation animation_;
     SkColor start_color_ = kDefaultFrameColor;
     SkColor target_color_ = kDefaultFrameColor;
-    ;
     SkColor current_color_ = kDefaultFrameColor;
 
     DISALLOW_COPY_AND_ASSIGN(ColorAnimator);
diff --git a/ash/frame/frame_header.cc b/ash/frame/frame_header.cc
index e84e766..d9bf452 100644
--- a/ash/frame/frame_header.cc
+++ b/ash/frame/frame_header.cc
@@ -9,6 +9,7 @@
 #include "ash/frame/frame_header_util.h"
 #include "ash/public/cpp/ash_layout_constants.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "base/logging.h"  // DCHECK
 #include "ui/gfx/canvas.h"
@@ -114,7 +115,7 @@
 void FrameHeader::SetBackButton(FrameCaptionButton* back_button) {
   back_button_ = back_button;
   if (back_button_) {
-    back_button_->SetColorMode(button_color_mode_);
+    back_button_->SetColorMode(GetButtonColorMode());
     back_button_->SetBackgroundColor(GetCurrentFrameColor());
     back_button_->SetImage(CAPTION_BUTTON_ICON_BACK,
                            FrameCaptionButton::ANIMATE_NO,
@@ -158,10 +159,12 @@
 }
 
 void FrameHeader::UpdateCaptionButtonColors() {
-  caption_button_container_->SetColorMode(button_color_mode_);
+  auto button_color_mode = GetButtonColorMode();
+
+  caption_button_container_->SetColorMode(button_color_mode);
   caption_button_container_->SetBackgroundColor(GetCurrentFrameColor());
   if (back_button_) {
-    back_button_->SetColorMode(button_color_mode_);
+    back_button_->SetColorMode(button_color_mode);
     back_button_->SetBackgroundColor(GetCurrentFrameColor());
   }
 }
@@ -250,4 +253,11 @@
       left_view, caption_button_container_, GetHeaderHeight()));
 }
 
+FrameCaptionButton::ColorMode FrameHeader::GetButtonColorMode() {
+  return target_widget()->GetNativeWindow()->GetProperty(
+             ash::kFrameIsThemedByHostedAppKey)
+             ? FrameCaptionButton::ColorMode::kThemed
+             : FrameCaptionButton::ColorMode::kDefault;
+}
+
 }  // namespace ash
diff --git a/ash/frame/frame_header.h b/ash/frame/frame_header.h
index 1a86b47..1120e99 100644
--- a/ash/frame/frame_header.h
+++ b/ash/frame/frame_header.h
@@ -100,10 +100,6 @@
   void SetCaptionButtonContainer(
       FrameCaptionButtonContainerView* caption_button_container);
 
-  void set_button_color_mode(FrameCaptionButton::ColorMode button_color_mode) {
-    button_color_mode_ = button_color_mode;
-  }
-
   views::View* view() { return view_; }
 
   FrameCaptionButtonContainerView* caption_button_container() {
@@ -135,6 +131,8 @@
 
   gfx::Rect GetTitleBounds() const;
 
+  FrameCaptionButton::ColorMode GetButtonColorMode();
+
   // The widget that the caption buttons act on. This can be different from
   // |view_|'s widget.
   views::Widget* target_widget_;
@@ -143,8 +141,6 @@
   views::View* view_;
   FrameCaptionButton* back_button_ = nullptr;  // May remain nullptr.
   views::View* left_header_view_ = nullptr;    // May remain nullptr.
-  FrameCaptionButton::ColorMode button_color_mode_ =
-      FrameCaptionButton::ColorMode::kDefault;
   FrameCaptionButtonContainerView* caption_button_container_ = nullptr;
 
   // The height of the header to paint.
diff --git a/ash/public/cpp/mus_property_mirror_ash.cc b/ash/public/cpp/mus_property_mirror_ash.cc
index 4d1090e..f630ffb 100644
--- a/ash/public/cpp/mus_property_mirror_ash.cc
+++ b/ash/public/cpp/mus_property_mirror_ash.cc
@@ -87,6 +87,9 @@
     MirrorOwnedProperty(window, root_window, kFrameImageOverlayActiveKey);
   } else if (key == kFrameImageOverlayInactiveKey) {
     MirrorOwnedProperty(window, root_window, kFrameImageOverlayInactiveKey);
+  } else if (key == kFrameIsThemedByHostedAppKey) {
+    root_window->SetProperty(kFrameIsThemedByHostedAppKey,
+                             window->GetProperty(kFrameIsThemedByHostedAppKey));
   }
 }
 
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc
index c6c1e9bd..8b73a12 100644
--- a/ash/public/cpp/window_properties.cc
+++ b/ash/public/cpp/window_properties.cc
@@ -60,6 +60,9 @@
       ui::mojom::WindowManager::kFrameInactiveColor_Property,
       aura::PropertyConverter::CreateAcceptAnyValueCallback());
   property_converter->RegisterPrimitiveProperty(
+      kFrameIsThemedByHostedAppKey, mojom::kFrameIsThemedByHostedApp_Property,
+      aura::PropertyConverter::CreateAcceptAnyValueCallback());
+  property_converter->RegisterPrimitiveProperty(
       kHideShelfWhenFullscreenKey, mojom::kHideShelfWhenFullscreen_Property,
       aura::PropertyConverter::CreateAcceptAnyValueCallback());
   property_converter->RegisterPrimitiveProperty(
@@ -150,6 +153,7 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(SkColor,
                              kFrameInactiveColorKey,
                              kDefaultFrameColor);
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kFrameIsThemedByHostedAppKey, false);
 DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowPinType,
                              kWindowPinTypeKey,
                              mojom::WindowPinType::NONE);
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h
index e6a59d8..4ab5200c 100644
--- a/ash/public/cpp/window_properties.h
+++ b/ash/public/cpp/window_properties.h
@@ -159,6 +159,11 @@
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<SkColor>* const
     kFrameInactiveColorKey;
 
+// True when the frame colors were provided by a hosted app, i.e. by a
+// progressive web app manifest.
+ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
+    kFrameIsThemedByHostedAppKey;
+
 // A property key to store ash::WindowPinType for a window.
 // When setting this property to PINNED or TRUSTED_PINNED, the window manager
 // will try to fullscreen the window and pin it on the top of the screen. If the
diff --git a/ash/public/interfaces/window_properties.mojom b/ash/public/interfaces/window_properties.mojom
index 8df757b..fdc8524 100644
--- a/ash/public/interfaces/window_properties.mojom
+++ b/ash/public/interfaces/window_properties.mojom
@@ -27,6 +27,10 @@
 const string kFrameImageOverlayInactive_Property =
     "ash:frame-image-overlay-inactive";
 
+// A boolean that tells Ash whether the frame's colors come from a PWA manifest.
+const string kFrameIsThemedByHostedApp_Property =
+    "ash:frame-is-themed-by-hosted-app";
+
 // True if the shelf should be hidden when this window is put into fullscreen.
 // Exposed because some windows want to explicitly opt-out of this.
 const string kHideShelfWhenFullscreen_Property =
diff --git a/ash/window_manager.cc b/ash/window_manager.cc
index cbaccef..a27003d 100644
--- a/ash/window_manager.cc
+++ b/ash/window_manager.cc
@@ -455,7 +455,7 @@
       NonClientFrameController::Get(window);
   if (!non_client_frame_controller)
     return;
-  non_client_frame_controller->SetClientArea(insets, additional_client_areas);
+  non_client_frame_controller->SetClientArea(insets);
 }
 
 bool WindowManager::IsWindowActive(aura::Window* window) {
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc
index c428fac..e19f7e87 100644
--- a/ash/wm/non_client_frame_controller.cc
+++ b/ash/wm/non_client_frame_controller.cc
@@ -379,11 +379,7 @@
   return GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).width() * 3;
 }
 
-void NonClientFrameController::SetClientArea(
-    const gfx::Insets& insets,
-    const std::vector<gfx::Rect>& additional_client_areas) {
-  client_area_insets_ = insets;
-  additional_client_areas_ = additional_client_areas;
+void NonClientFrameController::SetClientArea(const gfx::Insets& insets) {
   static_cast<WmNativeWidgetAura*>(widget_->native_widget())
       ->SetHeaderHeight(insets.top());
 }
diff --git a/ash/wm/non_client_frame_controller.h b/ash/wm/non_client_frame_controller.h
index f2c19e8..17c041d5 100644
--- a/ash/wm/non_client_frame_controller.h
+++ b/ash/wm/non_client_frame_controller.h
@@ -77,8 +77,7 @@
     return window_manager_client_;
   }
 
-  void SetClientArea(const gfx::Insets& insets,
-                     const std::vector<gfx::Rect>& additional_client_areas);
+  void SetClientArea(const gfx::Insets& insets);
 
   // Stores |cursor| as this window's active cursor. It does not actually update
   // the active cursor by calling into CursorManager, but will update the return
@@ -119,9 +118,6 @@
 
   bool did_init_native_widget_ = false;
 
-  gfx::Insets client_area_insets_;
-  std::vector<gfx::Rect> additional_client_areas_;
-
   DISALLOW_COPY_AND_ASSIGN(NonClientFrameController);
 };
 
diff --git a/base/android/callback_android.cc b/base/android/callback_android.cc
index d0f8e9ce..7143664 100644
--- a/base/android/callback_android.cc
+++ b/base/android/callback_android.cc
@@ -12,17 +12,17 @@
 namespace base {
 namespace android {
 
-void RunCallbackAndroid(const JavaRef<jobject>& callback,
-                        const JavaRef<jobject>& arg) {
+void RunObjectCallbackAndroid(const JavaRef<jobject>& callback,
+                              const JavaRef<jobject>& arg) {
   Java_Helper_onObjectResultFromNative(AttachCurrentThread(), callback, arg);
 }
 
-void RunCallbackAndroid(const JavaRef<jobject>& callback, bool arg) {
+void RunBooleanCallbackAndroid(const JavaRef<jobject>& callback, bool arg) {
   Java_Helper_onBooleanResultFromNative(AttachCurrentThread(), callback,
                                         static_cast<jboolean>(arg));
 }
 
-void RunCallbackAndroid(const JavaRef<jobject>& callback, int arg) {
+void RunIntCallbackAndroid(const JavaRef<jobject>& callback, int arg) {
   Java_Helper_onIntResultFromNative(AttachCurrentThread(), callback, arg);
 }
 
@@ -33,8 +33,8 @@
   Java_Helper_onObjectResultFromNative(env, callback, java_string);
 }
 
-void RunCallbackAndroid(const JavaRef<jobject>& callback,
-                        const std::vector<uint8_t>& arg) {
+void RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback,
+                                 const std::vector<uint8_t>& arg) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, arg);
   Java_Helper_onObjectResultFromNative(env, callback, j_bytes);
diff --git a/base/android/callback_android.h b/base/android/callback_android.h
index c4d1b33..8a14c1f 100644
--- a/base/android/callback_android.h
+++ b/base/android/callback_android.h
@@ -6,6 +6,7 @@
 #define BASE_ANDROID_CALLBACK_ANDROID_H_
 
 #include <jni.h>
+#include <string>
 #include <vector>
 
 #include "base/android/scoped_java_ref.h"
@@ -16,19 +17,20 @@
 namespace base {
 namespace android {
 
-void BASE_EXPORT RunCallbackAndroid(const JavaRef<jobject>& callback,
-                                    const JavaRef<jobject>& arg);
+void BASE_EXPORT RunObjectCallbackAndroid(const JavaRef<jobject>& callback,
+                                          const JavaRef<jobject>& arg);
 
-void BASE_EXPORT RunCallbackAndroid(const JavaRef<jobject>& callback,
-                                    bool arg);
+void BASE_EXPORT RunBooleanCallbackAndroid(const JavaRef<jobject>& callback,
+                                           bool arg);
 
-void BASE_EXPORT RunCallbackAndroid(const JavaRef<jobject>& callback, int arg);
+void BASE_EXPORT RunIntCallbackAndroid(const JavaRef<jobject>& callback,
+                                       int arg);
 
 void BASE_EXPORT RunStringCallbackAndroid(const JavaRef<jobject>& callback,
                                           const std::string& arg);
 
-void BASE_EXPORT RunCallbackAndroid(const JavaRef<jobject>& callback,
-                                    const std::vector<uint8_t>& arg);
+void BASE_EXPORT RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback,
+                                             const std::vector<uint8_t>& arg);
 
 }  // namespace android
 }  // namespace base
diff --git a/base/profiler/native_stack_sampler.h b/base/profiler/native_stack_sampler.h
index 758e195..5d7e9b0 100644
--- a/base/profiler/native_stack_sampler.h
+++ b/base/profiler/native_stack_sampler.h
@@ -65,7 +65,7 @@
   // Records a set of internal frames and returns them.
   virtual std::vector<StackSamplingProfiler::InternalFrame> RecordStackFrames(
       StackBuffer* stackbuffer,
-      StackSamplingProfiler::SamplingProfileBuilder* profile_builder) = 0;
+      StackSamplingProfiler::ProfileBuilder* profile_builder) = 0;
 
  protected:
   NativeStackSampler();
diff --git a/base/profiler/native_stack_sampler_mac.cc b/base/profiler/native_stack_sampler_mac.cc
index 3e88d79..d45c7a8c 100644
--- a/base/profiler/native_stack_sampler_mac.cc
+++ b/base/profiler/native_stack_sampler_mac.cc
@@ -37,7 +37,7 @@
 using InternalFrame = StackSamplingProfiler::InternalFrame;
 using Module = StackSamplingProfiler::Module;
 using InternalModule = StackSamplingProfiler::InternalModule;
-using SamplingProfileBuilder = StackSamplingProfiler::SamplingProfileBuilder;
+using ProfileBuilder = StackSamplingProfiler::ProfileBuilder;
 
 namespace {
 
@@ -348,7 +348,7 @@
   void ProfileRecordingStarting() override;
   std::vector<InternalFrame> RecordStackFrames(
       StackBuffer* stack_buffer,
-      SamplingProfileBuilder* profile_builder) override;
+      ProfileBuilder* profile_builder) override;
 
  private:
   // Returns the InternalModule containing |instruction_pointer|, adding it to
@@ -413,7 +413,7 @@
 
 std::vector<InternalFrame> NativeStackSamplerMac::RecordStackFrames(
     StackBuffer* stack_buffer,
-    SamplingProfileBuilder* profile_builder) {
+    ProfileBuilder* profile_builder) {
   x86_thread_state64_t thread_state;
 
   const std::vector<InternalFrame> empty_internal_frames;
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc
index 2207d9f..b9b1773 100644
--- a/base/profiler/native_stack_sampler_win.cc
+++ b/base/profiler/native_stack_sampler_win.cc
@@ -36,7 +36,7 @@
 using InternalFrame = StackSamplingProfiler::InternalFrame;
 using Module = StackSamplingProfiler::Module;
 using InternalModule = StackSamplingProfiler::InternalModule;
-using SamplingProfileBuilder = StackSamplingProfiler::SamplingProfileBuilder;
+using ProfileBuilder = StackSamplingProfiler::ProfileBuilder;
 
 // Stack recording functions --------------------------------------------------
 
@@ -333,7 +333,7 @@
     void* stack_copy_buffer,
     size_t stack_copy_buffer_size,
     std::vector<RecordedFrame>* stack,
-    SamplingProfileBuilder* profile_builder,
+    ProfileBuilder* profile_builder,
     NativeStackSamplerTestDelegate* test_delegate) {
   DCHECK(stack->empty());
 
@@ -394,7 +394,7 @@
   void ProfileRecordingStarting() override;
   std::vector<InternalFrame> RecordStackFrames(
       StackBuffer* stack_buffer,
-      SamplingProfileBuilder* profile_builder) override;
+      ProfileBuilder* profile_builder) override;
 
  private:
   // Attempts to query the module filename, base address, and id for
@@ -435,7 +435,7 @@
 
 std::vector<InternalFrame> NativeStackSamplerWin::RecordStackFrames(
     StackBuffer* stack_buffer,
-    SamplingProfileBuilder* profile_builder) {
+    ProfileBuilder* profile_builder) {
   DCHECK(stack_buffer);
 
   std::vector<RecordedFrame> stack;
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index 4e4139c..fcd6ace 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -136,61 +136,6 @@
 StackSamplingProfiler::CallStackProfile::CallStackProfile(
     const CallStackProfile& other) = default;
 
-// StackSamplingProfiler::SamplingProfileBuilder ------------------------------
-
-StackSamplingProfiler::SamplingProfileBuilder::SamplingProfileBuilder(
-    const CompletedCallback& callback)
-    : callback_(callback) {}
-
-StackSamplingProfiler::SamplingProfileBuilder::~SamplingProfileBuilder() =
-    default;
-
-void StackSamplingProfiler::SamplingProfileBuilder::RecordAnnotations() {
-  // The code inside this method must not do anything that could acquire a
-  // mutex, including allocating memory (which includes LOG messages) because
-  // that mutex could be held by a stopped thread, thus resulting in deadlock.
-  sample_.process_milestones = subtle::NoBarrier_Load(&process_milestones_);
-}
-
-void StackSamplingProfiler::SamplingProfileBuilder::OnProfileCompleted(
-    TimeDelta profile_duration,
-    TimeDelta sampling_period) {
-  profile_.profile_duration = profile_duration;
-  profile_.sampling_period = sampling_period;
-
-  // Run the associated callback, passing the collected profile.
-  callback_.Run(std::move(profile_));
-}
-
-void StackSamplingProfiler::SamplingProfileBuilder::OnSampleCompleted(
-    std::vector<InternalFrame> internal_frames) {
-  DCHECK_EQ(sample_.frames.size(), 0u);
-
-  // Dedup modules and convert InternalFrames to Frames.
-  for (const auto& internal_frame : internal_frames) {
-    const InternalModule& module(internal_frame.internal_module);
-    if (!module.is_valid) {
-      sample_.frames.emplace_back(internal_frame.instruction_pointer,
-                                  kUnknownModuleIndex);
-      continue;
-    }
-
-    auto loc = module_index_.find(module.base_address);
-    if (loc == module_index_.end()) {
-      profile_.modules.emplace_back(module.base_address, module.id,
-                                    module.filename);
-      size_t index = profile_.modules.size() - 1;
-      loc = module_index_.insert(std::make_pair(module.base_address, index))
-                .first;
-    }
-    sample_.frames.emplace_back(internal_frame.instruction_pointer,
-                                loc->second);
-  }
-
-  profile_.samples.push_back(std::move(sample_));
-  sample_ = Sample();
-}
-
 // StackSamplingProfiler::SamplingThread --------------------------------------
 
 class StackSamplingProfiler::SamplingThread : public Thread {
@@ -225,7 +170,7 @@
                       const SamplingParams& params,
                       WaitableEvent* finished,
                       std::unique_ptr<NativeStackSampler> sampler,
-                      std::unique_ptr<SamplingProfileBuilder> profile_builder)
+                      std::unique_ptr<ProfileBuilder> profile_builder)
         : collection_id(next_collection_id.GetNext()),
           target(target),
           params(params),
@@ -246,7 +191,7 @@
     std::unique_ptr<NativeStackSampler> native_sampler;
 
     // Receives the sampling data and builds a CallStackProfile.
-    std::unique_ptr<SamplingProfileBuilder> profile_builder;
+    std::unique_ptr<ProfileBuilder> profile_builder;
 
     // The absolute time for the next sample.
     Time next_sample_time;
@@ -765,7 +710,7 @@
 
 StackSamplingProfiler::StackSamplingProfiler(
     const SamplingParams& params,
-    std::unique_ptr<SamplingProfileBuilder> profile_builder,
+    std::unique_ptr<ProfileBuilder> profile_builder,
     NativeStackSamplerTestDelegate* test_delegate)
     : StackSamplingProfiler(PlatformThread::CurrentId(),
                             params,
@@ -775,7 +720,7 @@
 StackSamplingProfiler::StackSamplingProfiler(
     PlatformThreadId thread_id,
     const SamplingParams& params,
-    std::unique_ptr<SamplingProfileBuilder> profile_builder,
+    std::unique_ptr<ProfileBuilder> profile_builder,
     NativeStackSamplerTestDelegate* test_delegate)
     : thread_id_(thread_id),
       params_(params),
@@ -852,6 +797,11 @@
   ChangeAtomicFlags(&process_milestones_, 1 << milestone, 0);
 }
 
+// static
+subtle::Atomic32 StackSamplingProfiler::ProcessMilestone() {
+  return subtle::NoBarrier_Load(&process_milestones_);
+}
+
 // StackSamplingProfiler::Frame global functions ------------------------------
 
 bool operator==(const StackSamplingProfiler::Module& a,
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
index fb4bb25..df34df4 100644
--- a/base/profiler/stack_sampling_profiler.h
+++ b/base/profiler/stack_sampling_profiler.h
@@ -38,18 +38,12 @@
 //
 //   // Create and customize params as desired.
 //   base::StackStackSamplingProfiler::SamplingParams params;
-//   // Any thread's ID may be passed as the target.
-//   base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
-//       params);
 //
-//   // To process the profiles, use a custom completed callback:
-//   base::StackStackSamplingProfiler::CompletedCallback
-//       thread_safe_callback = ...;
-//   auto profile_builder =
-//       std::make_unique<base::StackSamplingProfiler::SamplingProfileBuilder>(
-//       thread_safe_callback);
+//   // To process the profiles, use a custom ProfileBuilder subclass:
+//   class SubProfileBuilder :
+//       public base::StackSamplingProfiler::ProfileBuilder{...}
 //   base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
-//       params, std::move(profile_builder));
+//       params, std::make_unique<SubProfileBuilder>(...));
 //
 //   profiler.Start();
 //   // ... work being done on the target thread here ...
@@ -60,8 +54,8 @@
 // altered as desired.
 //
 // When a call stack profile is complete, or the profiler is stopped,
-// SamplingProfileBuilder's OnProfileCompleted function is called from a thread
-// created by the profiler.
+// ProfileBuilder's OnProfileCompleted function is called from a thread created
+// by the profiler.
 class BASE_EXPORT StackSamplingProfiler {
  public:
   // Module represents the module (DLL or exe) corresponding to a stack frame.
@@ -92,7 +86,7 @@
   // Different from Module, it has an additional field "is_valid".
   //
   // This struct is only used for sampling data transfer from NativeStackSampler
-  // to SamplingProfileBuilder.
+  // to ProfileBuilder.
   struct BASE_EXPORT InternalModule {
     InternalModule();
     InternalModule(uintptr_t base_address,
@@ -139,7 +133,7 @@
   // information. This is different from Frame which only contains module index.
   //
   // This struct is only used for sampling data transfer from NativeStackSampler
-  // to SamplingProfileBuilder.
+  // to ProfileBuilder.
   struct BASE_EXPORT InternalFrame {
     InternalFrame(uintptr_t instruction_pointer,
                   InternalModule internal_module);
@@ -246,6 +240,36 @@
         bool simulate_intervening_start);
   };
 
+  // The ProfileBuilder interface allows the user to record profile information
+  // on the fly in whatever format is desired. Functions are invoked by the
+  // profiler on its own thread so must not block or perform expensive
+  // operations.
+  class BASE_EXPORT ProfileBuilder {
+   public:
+    ProfileBuilder() = default;
+    virtual ~ProfileBuilder() = default;
+
+    // Metadata associated with the sample to be saved off.
+    // The code implementing this method must not do anything that could acquire
+    // a mutex, including allocating memory (which includes LOG messages)
+    // because that mutex could be held by a stopped thread, thus resulting in
+    // deadlock.
+    virtual void RecordAnnotations() = 0;
+
+    // Records a new set of internal frames. Invoked when sampling a sample
+    // completes.
+    virtual void OnSampleCompleted(
+        std::vector<InternalFrame> internal_frames) = 0;
+
+    // Finishes the profile construction with |profile_duration| and
+    // |sampling_period|. Invoked when sampling a profile completes.
+    virtual void OnProfileCompleted(TimeDelta profile_duration,
+                                    TimeDelta sampling_period) = 0;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ProfileBuilder);
+  };
+
   // The callback type used to collect a completed profile. The passed |profile|
   // is move-only. Other threads, including the UI thread, may block on callback
   // completion so this should run as quickly as possible.
@@ -258,55 +282,12 @@
   // implementation.
   using CompletedCallback = Callback<void(CallStackProfile)>;
 
-  // SamplingProfileBuilder receives the sampling data from NativeSampler and
-  // builds a CallStackProfile.
-  //
-  // The results of the profile building -- a CallStackProfile, is passed to the
-  // completed callback. A CallStackProfile contains a set of Samples and
-  // Modules, and other sampling information. One Sample corresponds to a single
-  // recorded stack, and the Modules record those modules associated with the
-  // recorded stack frames.
-  class BASE_EXPORT SamplingProfileBuilder {
-   public:
-    SamplingProfileBuilder(const CompletedCallback& callback);
-
-    ~SamplingProfileBuilder();
-
-    // Records metadata associated with sample_.
-    void RecordAnnotations();
-
-    // Finishes the construction of profile_ with |profile_duration| and
-    // |sampling_period|. Runs callback_ to pass profile_. Invoked when sampling
-    // a Profile completes.
-    void OnProfileCompleted(TimeDelta profile_duration,
-                            TimeDelta sampling_period);
-
-    // Records a new set of frames to sample_. Invoked when sampling a Sample
-    // completes.
-    void OnSampleCompleted(std::vector<InternalFrame> internal_frames);
-
-   private:
-    // The collected stack samples.
-    CallStackProfile profile_;
-
-    // The current sample being recorded.
-    Sample sample_;
-
-    // The indexes of internal modules, indexed by module's base_address.
-    std::map<uintptr_t, size_t> module_index_;
-
-    // Callback made when sampling a profile completes.
-    const CompletedCallback callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(SamplingProfileBuilder);
-  };
-
   // Creates a profiler for the CURRENT thread. An optional |test_delegate| can
   // be supplied by tests. The caller must ensure that this object gets
   // destroyed before the current thread exits.
   StackSamplingProfiler(
       const SamplingParams& params,
-      std::unique_ptr<SamplingProfileBuilder> profile_builder,
+      std::unique_ptr<ProfileBuilder> profile_builder,
       NativeStackSamplerTestDelegate* test_delegate = nullptr);
 
   // Creates a profiler for ANOTHER thread. An optional |test_delegate| can be
@@ -317,7 +298,7 @@
   StackSamplingProfiler(
       PlatformThreadId thread_id,
       const SamplingParams& params,
-      std::unique_ptr<SamplingProfileBuilder> profile_builder,
+      std::unique_ptr<ProfileBuilder> profile_builder,
       NativeStackSamplerTestDelegate* test_delegate = nullptr);
 
   // Stops any profiling currently taking place before destroying the profiler.
@@ -338,7 +319,7 @@
   // are completed or the profiler object is destroyed, whichever occurs first.
   void Stop();
 
-  // Set the current system state that is recorded with each captured stack
+  // Sets the current system state that is recorded with each captured stack
   // frame. This is thread-safe so can be called from anywhere. The parameter
   // value should be from an enumeration of the appropriate type with values
   // ranging from 0 to 31, inclusive. This sets bits within Sample field of
@@ -346,6 +327,10 @@
   // (globally) by the caller(s).
   static void SetProcessMilestone(int milestone);
 
+  // Gets the current system state that is recorded with each captured stack
+  // frame. This is thread-safe so can be called from anywhere.
+  static subtle::Atomic32 ProcessMilestone();
+
  private:
   friend class TestAPI;
 
@@ -368,7 +353,7 @@
   // Receives the sampling data and builds a CallStackProfile. The ownership of
   // this object will be transferred to the sampling thread when thread sampling
   // starts.
-  std::unique_ptr<SamplingProfileBuilder> profile_builder_;
+  std::unique_ptr<ProfileBuilder> profile_builder_;
 
   // This starts "signaled", is reset when sampling begins, and is signaled
   // when that sampling is complete and the profile_builder_'s
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
index 204c1df8..b0f88362 100644
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
@@ -27,6 +28,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/test/bind_test_util.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/simple_thread.h"
 #include "base/time/time.h"
@@ -62,11 +64,13 @@
 
 using SamplingParams = StackSamplingProfiler::SamplingParams;
 using Frame = StackSamplingProfiler::Frame;
-using Frames = std::vector<StackSamplingProfiler::Frame>;
+using Frames = std::vector<Frame>;
+using InternalFrame = StackSamplingProfiler::InternalFrame;
+using InternalFrames = std::vector<InternalFrame>;
+using InternalFrameSets = std::vector<std::vector<InternalFrame>>;
 using Module = StackSamplingProfiler::Module;
+using InternalModule = StackSamplingProfiler::InternalModule;
 using Sample = StackSamplingProfiler::Sample;
-using CallStackProfile = StackSamplingProfiler::CallStackProfile;
-using SamplingProfileBuilder = StackSamplingProfiler::SamplingProfileBuilder;
 
 namespace {
 
@@ -93,8 +97,9 @@
 // Signature for a target function that is expected to appear in the stack. See
 // SignalAndWaitUntilSignaled() below. The return value should be a program
 // counter pointer near the end of the function.
-using TargetFunction = const void*(*)(WaitableEvent*, WaitableEvent*,
-                                      const StackConfiguration*);
+using TargetFunction = const void* (*)(WaitableEvent*,
+                                       WaitableEvent*,
+                                       const StackConfiguration*);
 
 // A thread to target for profiling, whose stack is guaranteed to contain
 // SignalAndWaitUntilSignaled() when coordinated with the main thread.
@@ -150,7 +155,7 @@
   };
 
   // Callback function to be provided when calling through the other library.
-  static void OtherLibraryCallback(void *arg);
+  static void OtherLibraryCallback(void* arg);
 
   // Returns the current program counter, or a value very close to it.
   static const void* GetProgramCounter();
@@ -238,18 +243,15 @@
     const StackConfiguration* stack_config) {
   if (stack_config) {
     // A function whose arguments are a function accepting void*, and a void*.
-    using InvokeCallbackFunction = void(*)(void (*)(void*), void*);
+    using InvokeCallbackFunction = void (*)(void (*)(void*), void*);
     EXPECT_TRUE(stack_config->library);
     InvokeCallbackFunction function = reinterpret_cast<InvokeCallbackFunction>(
         GetFunctionPointerFromNativeLibrary(stack_config->library,
                                             "InvokeCallbackFunction"));
     EXPECT_TRUE(function);
 
-    TargetFunctionArgs args = {
-      thread_started_event,
-      finish_event,
-      stack_config
-    };
+    TargetFunctionArgs args = {thread_started_event, finish_event,
+                               stack_config};
     (*function)(&OtherLibraryCallback, &args);
   }
 
@@ -259,7 +261,7 @@
 }
 
 // static
-void TargetThread::OtherLibraryCallback(void *arg) {
+void TargetThread::OtherLibraryCallback(void* arg) {
   const TargetFunctionArgs* args = static_cast<TargetFunctionArgs*>(arg);
   SignalAndWaitUntilSignaled(args->thread_started_event, args->finish_event,
                              args->stack_config);
@@ -278,6 +280,92 @@
 #endif
 }
 
+// Profile consists of a set of internal frame sets and other sampling
+// information.
+struct Profile {
+  Profile() = default;
+  Profile(Profile&& other) = default;
+  Profile(const InternalFrameSets& frame_sets,
+          int annotation_count,
+          TimeDelta profile_duration,
+          TimeDelta sampling_period);
+
+  ~Profile() = default;
+
+  Profile& operator=(Profile&& other) = default;
+
+  // The collected internal frame sets.
+  InternalFrameSets frame_sets;
+
+  // The number of invocations of RecordAnnotations().
+  int annotation_count;
+
+  // Duration of this profile.
+  TimeDelta profile_duration;
+
+  // Time between samples.
+  TimeDelta sampling_period;
+};
+
+Profile::Profile(const InternalFrameSets& frame_sets,
+                 int annotation_count,
+                 TimeDelta profile_duration,
+                 TimeDelta sampling_period)
+    : frame_sets(frame_sets),
+      annotation_count(annotation_count),
+      profile_duration(profile_duration),
+      sampling_period(sampling_period) {}
+
+// The callback type used to collect a profile. The passed Profile is move-only.
+// Other threads, including the UI thread, may block on callback completion so
+// this should run as quickly as possible.
+using ProfileCompletedCallback = Callback<void(Profile)>;
+
+// TestProfileBuilder collects internal frames produced by the profiler.
+class TestProfileBuilder : public StackSamplingProfiler::ProfileBuilder {
+ public:
+  TestProfileBuilder(const ProfileCompletedCallback& callback);
+
+  ~TestProfileBuilder() override;
+
+  // StackSamplingProfiler::ProfileBuilder:
+  void RecordAnnotations() override;
+  void OnSampleCompleted(InternalFrames internal_frames) override;
+  void OnProfileCompleted(TimeDelta profile_duration,
+                          TimeDelta sampling_period) override;
+
+ private:
+  // The sets of internal frames recorded.
+  std::vector<InternalFrames> frame_sets_;
+
+  // The number of invocations of RecordAnnotations().
+  int annotation_count_ = 0;
+
+  // Callback made when sampling a profile completes.
+  const ProfileCompletedCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestProfileBuilder);
+};
+
+TestProfileBuilder::TestProfileBuilder(const ProfileCompletedCallback& callback)
+    : callback_(callback) {}
+
+TestProfileBuilder::~TestProfileBuilder() = default;
+
+void TestProfileBuilder::RecordAnnotations() {
+  ++annotation_count_;
+}
+
+void TestProfileBuilder::OnSampleCompleted(InternalFrames internal_frames) {
+  frame_sets_.push_back(std::move(internal_frames));
+}
+
+void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration,
+                                            TimeDelta sampling_period) {
+  callback_.Run(Profile(frame_sets_, annotation_count_, profile_duration,
+                        sampling_period));
+}
+
 // Loads the other library, which defines a function to be called in the
 // WITH_OTHER_LIBRARY configuration.
 NativeLibrary LoadOtherLibrary() {
@@ -311,7 +399,7 @@
   HMODULE module_handle;
   // Keep trying to get the module handle until the call fails.
   while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
-                             GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+                                 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                              reinterpret_cast<LPCTSTR>(module_base_address),
                              &module_handle) ||
          ::GetLastError() != ERROR_MOD_NOT_FOUND) {
@@ -324,21 +412,6 @@
 #endif
 }
 
-// Called on the profiler thread when complete, to collect profile.
-void SaveProfile(CallStackProfile* profile, CallStackProfile pending_profile) {
-  *profile = std::move(pending_profile);
-}
-
-// Called on the profiler thread when complete. Collects the profile produced by
-// the profiler, and signals an event to allow the main thread to know that that
-// the profiler is done.
-void SaveProfileAndSignalEvent(CallStackProfile* profile,
-                               WaitableEvent* event,
-                               CallStackProfile pending_profile) {
-  *profile = std::move(pending_profile);
-  event->Signal();
-}
-
 // Executes the function with the target thread running and executing within
 // SignalAndWaitUntilSignaled(). Performs all necessary target thread startup
 // and shutdown work before and afterward.
@@ -371,15 +444,16 @@
                   WaitableEvent::InitialState::NOT_SIGNALED),
         profiler(thread_id,
                  params,
-                 std::make_unique<SamplingProfileBuilder>(
-                     Bind(&SaveProfileAndSignalEvent,
-                          Unretained(&profile),
-                          Unretained(&completed))),
+                 std::make_unique<TestProfileBuilder>(
+                     BindLambdaForTesting([this](Profile result_profile) {
+                       profile = std::move(result_profile);
+                       completed.Signal();
+                     })),
                  delegate) {}
 
   // The order here is important to ensure objects being referenced don't get
   // destructed until after the objects referencing them.
-  CallStackProfile profile;
+  Profile profile;
   WaitableEvent completed;
   StackSamplingProfiler profiler;
 
@@ -402,22 +476,22 @@
   return profilers;
 }
 
-// Captures profile as specified by |params| on the TargetThread, and returns
-// it in |profile|. Waits up to |profiler_wait_time| for the profiler to
-// complete.
-void CaptureProfile(const SamplingParams& params,
-                    TimeDelta profiler_wait_time,
-                    CallStackProfile* profile) {
-  WithTargetThread([&params, profile,
+// Captures internal frames as specified by |params| on the TargetThread, and
+// returns them. Waits up to |profiler_wait_time| for the profiler to complete.
+InternalFrameSets CaptureFrameSets(const SamplingParams& params,
+                                   TimeDelta profiler_wait_time) {
+  InternalFrameSets frame_sets;
+  WithTargetThread([&params, &frame_sets,
                     profiler_wait_time](PlatformThreadId target_thread_id) {
     TestProfilerInfo info(target_thread_id, params);
     info.profiler.Start();
     info.completed.TimedWait(profiler_wait_time);
     info.profiler.Stop();
     info.completed.Wait();
-
-    *profile = std::move(info.profile);
+    frame_sets = std::move(info.profile.frame_sets);
   });
+
+  return frame_sets;
 }
 
 // Waits for one of multiple samplings to complete.
@@ -459,39 +533,39 @@
 // Searches through the frames in |sample|, returning an iterator to the first
 // frame that has an instruction pointer within |target_function|. Returns
 // sample.end() if no such frames are found.
-Frames::const_iterator FindFirstFrameWithinFunction(
-    const Sample& sample,
+InternalFrames::const_iterator FindFirstFrameWithinFunction(
+    const InternalFrames& frames,
     TargetFunction target_function) {
-  uintptr_t function_start = reinterpret_cast<uintptr_t>(
-      MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
-          target_function)));
+  uintptr_t function_start =
+      reinterpret_cast<uintptr_t>(MaybeFixupFunctionAddressForILT(
+          reinterpret_cast<const void*>(target_function)));
   uintptr_t function_end =
       reinterpret_cast<uintptr_t>(target_function(nullptr, nullptr, nullptr));
-  for (auto it = sample.frames.begin(); it != sample.frames.end(); ++it) {
-    if ((it->instruction_pointer >= function_start) &&
-        (it->instruction_pointer <= function_end)) {
+  for (auto it = frames.begin(); it != frames.end(); ++it) {
+    if (it->instruction_pointer >= function_start &&
+        it->instruction_pointer <= function_end) {
       return it;
     }
   }
-  return sample.frames.end();
+  return frames.end();
 }
 
 // Formats a sample into a string that can be output for test diagnostics.
-std::string FormatSampleForDiagnosticOutput(
-    const Sample& sample,
-    const std::vector<Module>& modules) {
+std::string FormatSampleForDiagnosticOutput(const InternalFrames& frames) {
   std::string output;
-  for (const auto& frame : sample.frames) {
+  for (const auto& frame : frames) {
     output += StringPrintf(
         "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer),
-        modules[frame.module_index].filename.AsUTF8Unsafe().c_str());
+        frame.internal_module.filename.AsUTF8Unsafe().c_str());
   }
   return output;
 }
 
 // Returns a duration that is longer than the test timeout. We would use
 // TimeDelta::Max() but https://crbug.com/465948.
-TimeDelta AVeryLongTimeDelta() { return TimeDelta::FromDays(1); }
+TimeDelta AVeryLongTimeDelta() {
+  return TimeDelta::FromDays(1);
+}
 
 // Tests the scenario where the library is unloaded after copying the stack, but
 // before walking it. If |wait_until_unloaded| is true, ensures that the
@@ -527,8 +601,7 @@
 
   NativeLibrary other_library = LoadOtherLibrary();
   TargetThread target_thread(StackConfiguration(
-      StackConfiguration::WITH_OTHER_LIBRARY,
-      other_library));
+      StackConfiguration::WITH_OTHER_LIBRARY, other_library));
 
   PlatformThreadHandle target_thread_handle;
   EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
@@ -538,10 +611,8 @@
   WaitableEvent sampling_thread_completed(
       WaitableEvent::ResetPolicy::MANUAL,
       WaitableEvent::InitialState::NOT_SIGNALED);
-  CallStackProfile profile;
-  const StackSamplingProfiler::CompletedCallback callback =
-      Bind(&SaveProfileAndSignalEvent, Unretained(&profile),
-           Unretained(&sampling_thread_completed));
+  Profile profile;
+
   WaitableEvent stack_copied(WaitableEvent::ResetPolicy::MANUAL,
                              WaitableEvent::InitialState::NOT_SIGNALED);
   WaitableEvent start_stack_walk(WaitableEvent::ResetPolicy::MANUAL,
@@ -550,7 +621,12 @@
                                     wait_until_unloaded);
   StackSamplingProfiler profiler(
       target_thread.id(), params,
-      std::make_unique<SamplingProfileBuilder>(callback), &test_delegate);
+      std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
+          [&profile, &sampling_thread_completed](Profile result_profile) {
+            profile = std::move(result_profile);
+            sampling_thread_completed.Signal();
+          })),
+      &test_delegate);
 
   profiler.Start();
 
@@ -575,53 +651,54 @@
   // Wait for the sampling thread to complete and fill out |profile|.
   sampling_thread_completed.Wait();
 
-  // Look up the sample.
-  ASSERT_EQ(1u, profile.samples.size());
-  const Sample& sample = profile.samples[0];
+  // Look up the frames.
+  ASSERT_EQ(1u, profile.frame_sets.size());
+  const InternalFrames& frames = profile.frame_sets[0];
 
   // Check that the stack contains a frame for
   // TargetThread::SignalAndWaitUntilSignaled().
-  Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
-      sample, &TargetThread::SignalAndWaitUntilSignaled);
-  ASSERT_TRUE(end_frame != sample.frames.end())
+  InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
+      frames, &TargetThread::SignalAndWaitUntilSignaled);
+  ASSERT_TRUE(end_frame != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
              &TargetThread::SignalAndWaitUntilSignaled))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 
   if (wait_until_unloaded) {
     // The stack should look like this, resulting one frame after
-    // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is not
-    // recorded since we can't get module information.
+    // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is
+    // not recorded since we can't get module information.
     //
     // ... WaitableEvent and system frames ...
     // TargetThread::SignalAndWaitUntilSignaled
     // TargetThread::OtherLibraryCallback
-    EXPECT_EQ(2, sample.frames.end() - end_frame)
+    EXPECT_EQ(2, frames.end() - end_frame)
         << "Stack:\n"
-        << FormatSampleForDiagnosticOutput(sample, profile.modules);
+        << FormatSampleForDiagnosticOutput(frames);
   } else {
     // We didn't wait for the asynchronous unloading to complete, so the results
     // are non-deterministic: if the library finished unloading we should have
     // the same stack as |wait_until_unloaded|, if not we should have the full
     // stack. The important thing is that we should not crash.
 
-    if (sample.frames.end() - end_frame == 2) {
+    if (frames.end() - end_frame == 2) {
       // This is the same case as |wait_until_unloaded|.
       return;
     }
 
     // Check that the stack contains a frame for
     // TargetThread::CallThroughOtherLibrary().
-    Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction(
-        sample, &TargetThread::CallThroughOtherLibrary);
-    ASSERT_TRUE(other_library_frame != sample.frames.end())
+    InternalFrames::const_iterator other_library_frame =
+        FindFirstFrameWithinFunction(frames,
+                                     &TargetThread::CallThroughOtherLibrary);
+    ASSERT_TRUE(other_library_frame != frames.end())
         << "Function at "
         << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
                &TargetThread::CallThroughOtherLibrary))
         << " was not found in stack:\n"
-        << FormatSampleForDiagnosticOutput(sample, profile.modules);
+        << FormatSampleForDiagnosticOutput(frames);
 
     // The stack should look like this, resulting in three frames between
     // SignalAndWaitUntilSignaled and CallThroughOtherLibrary:
@@ -633,7 +710,7 @@
     // TargetThread::CallThroughOtherLibrary
     EXPECT_EQ(3, other_library_frame - end_frame)
         << "Stack:\n"
-        << FormatSampleForDiagnosticOutput(sample, profile.modules);
+        << FormatSampleForDiagnosticOutput(frames);
   }
 }
 
@@ -658,8 +735,9 @@
 
 }  // namespace
 
-// Checks that the basic expected information is present in a sampled call stack
-// profile.
+// Checks that the basic expected information is present in sampled internal
+// frames.
+//
 // macOS ASAN is not yet supported - crbug.com/718628.
 #if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX))
 #define MAYBE_Basic Basic
@@ -671,59 +749,26 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
+  InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
 
-  // Check that the profile and samples sizes are correct, and the module
-  // indices are in range.
-  ASSERT_EQ(1u, profile.samples.size());
-  EXPECT_EQ(params.sampling_interval, profile.sampling_period);
-  const Sample& sample = profile.samples[0];
-  EXPECT_EQ(0u, sample.process_milestones);
-  for (const auto& frame : sample.frames) {
-    ASSERT_GE(frame.module_index, 0u);
-    ASSERT_LT(frame.module_index, profile.modules.size());
-  }
+  // Check that the size of the frame sets are correct.
+  ASSERT_EQ(1u, frame_sets.size());
+  const InternalFrames& frames = frame_sets[0];
+
+  // Check that all the modules are valid.
+  for (const auto& frame : frames)
+    EXPECT_TRUE(frame.internal_module.is_valid);
 
   // Check that the stack contains a frame for
-  // TargetThread::SignalAndWaitUntilSignaled() and that the frame has this
-  // executable's module.
-  Frames::const_iterator loc = FindFirstFrameWithinFunction(
-      sample, &TargetThread::SignalAndWaitUntilSignaled);
-  ASSERT_TRUE(loc != sample.frames.end())
+  // TargetThread::SignalAndWaitUntilSignaled().
+  InternalFrames::const_iterator loc = FindFirstFrameWithinFunction(
+      frames, &TargetThread::SignalAndWaitUntilSignaled);
+  ASSERT_TRUE(loc != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
              &TargetThread::SignalAndWaitUntilSignaled))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
-  FilePath executable_path;
-  EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
-  EXPECT_EQ(executable_path,
-            MakeAbsoluteFilePath(profile.modules[loc->module_index].filename));
-}
-
-// Checks that annotations are recorded in samples.
-PROFILER_TEST_F(StackSamplingProfilerTest, Annotations) {
-  SamplingParams params;
-  params.sampling_interval = TimeDelta::FromMilliseconds(0);
-  params.samples_per_profile = 1;
-
-  // Check that a run picks up annotations.
-  StackSamplingProfiler::SetProcessMilestone(1);
-  CallStackProfile profile1;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile1);
-  ASSERT_EQ(1u, profile1.samples.size());
-  const Sample& sample1 = profile1.samples[0];
-  EXPECT_EQ(1u << 1, sample1.process_milestones);
-
-  // Run it a second time but with changed annotations. These annotations
-  // should appear in the first acquired sample.
-  StackSamplingProfiler::SetProcessMilestone(2);
-  CallStackProfile profile2;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile2);
-  ASSERT_EQ(1u, profile2.samples.size());
-  const Sample& sample2 = profile2.samples[0];
-  EXPECT_EQ(sample1.process_milestones | (1u << 2), sample2.process_milestones);
+      << FormatSampleForDiagnosticOutput(frames);
 }
 
 // Checks that the profiler handles stacks containing dynamically-allocated
@@ -739,52 +784,53 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
+  Profile profile;
   WithTargetThread(
       [&params, &profile](PlatformThreadId target_thread_id) {
         WaitableEvent sampling_thread_completed(
             WaitableEvent::ResetPolicy::MANUAL,
             WaitableEvent::InitialState::NOT_SIGNALED);
-        const StackSamplingProfiler::CompletedCallback callback =
-            Bind(&SaveProfileAndSignalEvent, Unretained(&profile),
-                 Unretained(&sampling_thread_completed));
         StackSamplingProfiler profiler(
             target_thread_id, params,
-            std::make_unique<SamplingProfileBuilder>(callback));
+            std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
+                [&profile, &sampling_thread_completed](Profile result_profile) {
+                  profile = std::move(result_profile);
+                  sampling_thread_completed.Signal();
+                })));
         profiler.Start();
         sampling_thread_completed.Wait();
       },
       StackConfiguration(StackConfiguration::WITH_ALLOCA));
 
-  // Look up the sample.
-  ASSERT_EQ(1u, profile.samples.size());
-  const Sample& sample = profile.samples[0];
+  // Look up the frames.
+  ASSERT_EQ(1u, profile.frame_sets.size());
+  const InternalFrames& frames = profile.frame_sets[0];
 
   // Check that the stack contains a frame for
   // TargetThread::SignalAndWaitUntilSignaled().
-  Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
-      sample, &TargetThread::SignalAndWaitUntilSignaled);
-  ASSERT_TRUE(end_frame != sample.frames.end())
+  InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
+      frames, &TargetThread::SignalAndWaitUntilSignaled);
+  ASSERT_TRUE(end_frame != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
              &TargetThread::SignalAndWaitUntilSignaled))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 
   // Check that the stack contains a frame for TargetThread::CallWithAlloca().
-  Frames::const_iterator alloca_frame =
-      FindFirstFrameWithinFunction(sample, &TargetThread::CallWithAlloca);
-  ASSERT_TRUE(alloca_frame != sample.frames.end())
+  InternalFrames::const_iterator alloca_frame =
+      FindFirstFrameWithinFunction(frames, &TargetThread::CallWithAlloca);
+  ASSERT_TRUE(alloca_frame != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(
              reinterpret_cast<const void*>(&TargetThread::CallWithAlloca))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 
   // These frames should be adjacent on the stack.
   EXPECT_EQ(1, alloca_frame - end_frame)
       << "Stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 }
 
 // Checks that a profiler can stop/destruct without ever having started.
@@ -794,16 +840,17 @@
     params.sampling_interval = TimeDelta::FromMilliseconds(0);
     params.samples_per_profile = 1;
 
-    CallStackProfile profile;
+    Profile profile;
     WaitableEvent sampling_completed(WaitableEvent::ResetPolicy::MANUAL,
                                      WaitableEvent::InitialState::NOT_SIGNALED);
-    const StackSamplingProfiler::CompletedCallback callback =
-        Bind(&SaveProfileAndSignalEvent, Unretained(&profile),
-             Unretained(&sampling_completed));
 
     StackSamplingProfiler profiler(
         target_thread_id, params,
-        std::make_unique<SamplingProfileBuilder>(callback));
+        std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
+            [&profile, &sampling_completed](Profile result_profile) {
+              profile = std::move(result_profile);
+              sampling_completed.Signal();
+            })));
 
     profiler.Stop();  // Constructed but never started.
     EXPECT_FALSE(sampling_completed.IsSignaled());
@@ -885,20 +932,20 @@
   });
 }
 
-// Checks that no call stack profile is captured if the profiling is stopped
+// Checks that no internal frames are captured if the profiling is stopped
 // during the initial delay.
 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
   SamplingParams params;
   params.initial_delay = TimeDelta::FromSeconds(60);
 
-  CallStackProfile profile;
-  CaptureProfile(params, TimeDelta::FromMilliseconds(0), &profile);
+  InternalFrameSets frame_sets =
+      CaptureFrameSets(params, TimeDelta::FromMilliseconds(0));
 
-  EXPECT_TRUE(profile.samples.empty());
+  EXPECT_TRUE(frame_sets.empty());
 }
 
-// Checks that tasks can be stopped before completion and incomplete call stack
-// profile is captured.
+// Checks that tasks can be stopped before completion and incomplete internal
+// frames are captured.
 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
   // Test delegate that counts samples.
   class SampleRecordedEvent : public NativeStackSamplerTestDelegate {
@@ -933,7 +980,7 @@
     profiler_info.profiler.Stop();
     profiler_info.completed.Wait();
 
-    EXPECT_EQ(1u, profiler_info.profile.samples.size());
+    EXPECT_EQ(1u, profiler_info.profile.frame_sets.size());
   });
 }
 
@@ -942,11 +989,13 @@
   SamplingParams params;
   params.sampling_interval = TimeDelta::FromMilliseconds(10);
 
-  CallStackProfile profile;
+  Profile profile;
   WithTargetThread([&params, &profile](PlatformThreadId target_thread_id) {
     std::unique_ptr<StackSamplingProfiler> profiler;
-    auto profile_builder = std::make_unique<SamplingProfileBuilder>(
-        Bind(&SaveProfile, Unretained(&profile)));
+    auto profile_builder = std::make_unique<TestProfileBuilder>(
+        BindLambdaForTesting([&profile](Profile result_profile) {
+          profile = std::move(result_profile);
+        }));
     profiler.reset(new StackSamplingProfiler(target_thread_id, params,
                                              std::move(profile_builder)));
     profiler->Start();
@@ -964,13 +1013,11 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
-  ASSERT_EQ(1u, profile.samples.size());
+  InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
+  ASSERT_EQ(1u, frame_sets.size());
 
-  profile = CallStackProfile();
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
-  ASSERT_EQ(1u, profile.samples.size());
+  frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
+  ASSERT_EQ(1u, frame_sets.size());
 }
 
 // Checks that a sampler can be started while another is running.
@@ -990,7 +1037,35 @@
     profiler_infos[0]->profiler.Start();
     profiler_infos[1]->profiler.Start();
     profiler_infos[1]->completed.Wait();
-    EXPECT_EQ(1u, profiler_infos[1]->profile.samples.size());
+    EXPECT_EQ(1u, profiler_infos[1]->profile.frame_sets.size());
+  });
+}
+
+// Checks that the profile duration and the sampling interval are calculated
+// correctly. Also checks that RecordAnnotations() is invoked each time a sample
+// is recorded.
+PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
+  WithTargetThread([](PlatformThreadId target_thread_id) {
+    SamplingParams params;
+    params.sampling_interval = TimeDelta::FromMilliseconds(1);
+    params.samples_per_profile = 3;
+
+    TestProfilerInfo profiler_info(target_thread_id, params);
+
+    profiler_info.profiler.Start();
+    profiler_info.completed.Wait();
+    EXPECT_EQ(3u, profiler_info.profile.frame_sets.size());
+
+    // The profile duration should be greater than the total sampling intervals.
+    EXPECT_GT(profiler_info.profile.profile_duration,
+              profiler_info.profile.sampling_period * 3);
+
+    EXPECT_EQ(TimeDelta::FromMilliseconds(1),
+              profiler_info.profile.sampling_period);
+
+    // The number of invocations of RecordAnnotations() should be equal to the
+    // number of samples recorded.
+    EXPECT_EQ(3, profiler_info.profile.annotation_count);
   });
 }
 
@@ -1000,9 +1075,8 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
-  ASSERT_EQ(1u, profile.samples.size());
+  InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
+  ASSERT_EQ(1u, frame_sets.size());
 
   // Capture thread should still be running at this point.
   ASSERT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
@@ -1026,9 +1100,8 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
-  ASSERT_EQ(1u, profile.samples.size());
+  InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
+  ASSERT_EQ(1u, frame_sets.size());
 
   // Capture thread should still be running at this point.
   ASSERT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
@@ -1038,9 +1111,8 @@
   StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(false);
 
   // Ensure another capture will start the sampling thread and run.
-  profile = CallStackProfile();
-  CaptureProfile(params, AVeryLongTimeDelta(), &profile);
-  ASSERT_EQ(1u, profile.samples.size());
+  frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
+  ASSERT_EQ(1u, frame_sets.size());
   EXPECT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
 }
 
@@ -1114,7 +1186,7 @@
 
     profiler_info.profiler.Start();
     profiler_info.completed.Wait();
-    EXPECT_EQ(1u, profiler_info.profile.samples.size());
+    EXPECT_EQ(1u, profiler_info.profile.frame_sets.size());
 
     // Perform an idle shutdown but simulate that a new capture is started
     // before it can actually run.
@@ -1132,7 +1204,7 @@
     TestProfilerInfo another_info(target_thread_id, params);
     another_info.profiler.Start();
     another_info.completed.Wait();
-    EXPECT_EQ(1u, another_info.profile.samples.size());
+    EXPECT_EQ(1u, another_info.profile.frame_sets.size());
   });
 }
 
@@ -1167,9 +1239,9 @@
     // Wait for the other profiler to finish.
     profiler_infos[other_profiler]->completed.Wait();
 
-    // Ensure each got the correct number of samples.
-    EXPECT_EQ(9u, profiler_infos[0]->profile.samples.size());
-    EXPECT_EQ(8u, profiler_infos[1]->profile.samples.size());
+    // Ensure each got the correct number of frame sets.
+    EXPECT_EQ(9u, profiler_infos[0]->profile.frame_sets.size());
+    EXPECT_EQ(8u, profiler_infos[1]->profile.frame_sets.size());
   });
 }
 
@@ -1198,7 +1270,8 @@
 
     // Wait for one profiler to finish.
     size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
-    EXPECT_EQ(10u, profiler_infos[completed_profiler]->profile.samples.size());
+    EXPECT_EQ(10u,
+              profiler_infos[completed_profiler]->profile.frame_sets.size());
     // Stop and destroy all profilers, always in the same order. Don't crash.
     for (size_t i = 0; i < profiler_infos.size(); ++i)
       profiler_infos[i]->profiler.Stop();
@@ -1220,7 +1293,7 @@
   params.sampling_interval = TimeDelta::FromMilliseconds(0);
   params.samples_per_profile = 1;
 
-  CallStackProfile profile;
+  Profile profile;
   {
     ScopedNativeLibrary other_library(LoadOtherLibrary());
     WithTargetThread(
@@ -1228,12 +1301,14 @@
           WaitableEvent sampling_thread_completed(
               WaitableEvent::ResetPolicy::MANUAL,
               WaitableEvent::InitialState::NOT_SIGNALED);
-          const StackSamplingProfiler::CompletedCallback callback =
-              Bind(&SaveProfileAndSignalEvent, Unretained(&profile),
-                   Unretained(&sampling_thread_completed));
           StackSamplingProfiler profiler(
               target_thread_id, params,
-              std::make_unique<SamplingProfileBuilder>(callback));
+              std::make_unique<TestProfileBuilder>(
+                  BindLambdaForTesting([&profile, &sampling_thread_completed](
+                                           Profile result_profile) {
+                    profile = std::move(result_profile);
+                    sampling_thread_completed.Signal();
+                  })));
           profiler.Start();
           sampling_thread_completed.Wait();
         },
@@ -1241,31 +1316,32 @@
                            other_library.get()));
   }
 
-  // Look up the sample.
-  ASSERT_EQ(1u, profile.samples.size());
-  const Sample& sample = profile.samples[0];
+  // Look up the frames.
+  ASSERT_EQ(1u, profile.frame_sets.size());
+  const InternalFrames& frames = profile.frame_sets[0];
 
   // Check that the stack contains a frame for
   // TargetThread::CallThroughOtherLibrary().
-  Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction(
-      sample, &TargetThread::CallThroughOtherLibrary);
-  ASSERT_TRUE(other_library_frame != sample.frames.end())
+  InternalFrames::const_iterator other_library_frame =
+      FindFirstFrameWithinFunction(frames,
+                                   &TargetThread::CallThroughOtherLibrary);
+  ASSERT_TRUE(other_library_frame != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
              &TargetThread::CallThroughOtherLibrary))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 
   // Check that the stack contains a frame for
   // TargetThread::SignalAndWaitUntilSignaled().
-  Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
-      sample, &TargetThread::SignalAndWaitUntilSignaled);
-  ASSERT_TRUE(end_frame != sample.frames.end())
+  InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
+      frames, &TargetThread::SignalAndWaitUntilSignaled);
+  ASSERT_TRUE(end_frame != frames.end())
       << "Function at "
       << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
              &TargetThread::SignalAndWaitUntilSignaled))
       << " was not found in stack:\n"
-      << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << FormatSampleForDiagnosticOutput(frames);
 
   // The stack should look like this, resulting in three frames between
   // SignalAndWaitUntilSignaled and CallThroughOtherLibrary:
@@ -1276,7 +1352,8 @@
   // InvokeCallbackFunction (in other library)
   // TargetThread::CallThroughOtherLibrary
   EXPECT_EQ(3, other_library_frame - end_frame)
-      << "Stack:\n" << FormatSampleForDiagnosticOutput(sample, profile.modules);
+      << "Stack:\n"
+      << FormatSampleForDiagnosticOutput(frames);
 }
 
 // Checks that a stack that runs through a library that is unloading produces a
@@ -1329,35 +1406,37 @@
   params2.sampling_interval = TimeDelta::FromMilliseconds(1);
   params2.samples_per_profile = 8;
 
-  CallStackProfile profile1, profile2;
+  Profile profile1, profile2;
 
   WaitableEvent sampling_thread_completed1(
       WaitableEvent::ResetPolicy::MANUAL,
       WaitableEvent::InitialState::NOT_SIGNALED);
-  const StackSamplingProfiler::CompletedCallback callback1 =
-      Bind(&SaveProfileAndSignalEvent, Unretained(&profile1),
-           Unretained(&sampling_thread_completed1));
   StackSamplingProfiler profiler1(
       target_thread1.id(), params1,
-      std::make_unique<SamplingProfileBuilder>(callback1));
+      std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
+          [&profile1, &sampling_thread_completed1](Profile result_profile) {
+            profile1 = std::move(result_profile);
+            sampling_thread_completed1.Signal();
+          })));
 
   WaitableEvent sampling_thread_completed2(
       WaitableEvent::ResetPolicy::MANUAL,
       WaitableEvent::InitialState::NOT_SIGNALED);
-  const StackSamplingProfiler::CompletedCallback callback2 =
-      Bind(&SaveProfileAndSignalEvent, Unretained(&profile2),
-           Unretained(&sampling_thread_completed2));
   StackSamplingProfiler profiler2(
       target_thread2.id(), params2,
-      std::make_unique<SamplingProfileBuilder>(callback2));
+      std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
+          [&profile2, &sampling_thread_completed2](Profile result_profile) {
+            profile2 = std::move(result_profile);
+            sampling_thread_completed2.Signal();
+          })));
 
   // Finally the real work.
   profiler1.Start();
   profiler2.Start();
   sampling_thread_completed1.Wait();
   sampling_thread_completed2.Wait();
-  EXPECT_EQ(9u, profile1.samples.size());
-  EXPECT_EQ(8u, profile2.samples.size());
+  EXPECT_EQ(9u, profile1.frame_sets.size());
+  EXPECT_EQ(8u, profile2.frame_sets.size());
 
   target_thread1.SignalThreadToFinish();
   target_thread2.SignalThreadToFinish();
@@ -1378,10 +1457,11 @@
                    WaitableEvent::InitialState::NOT_SIGNALED),
         profiler_(thread_id,
                   params,
-                  std::make_unique<SamplingProfileBuilder>(
-                      Bind(&SaveProfileAndSignalEvent,
-                           Unretained(&profile_),
-                           Unretained(&completed_)))) {}
+                  std::make_unique<TestProfileBuilder>(
+                      BindLambdaForTesting([this](Profile result_profile) {
+                        profile_ = std::move(result_profile);
+                        completed_.Signal();
+                      }))) {}
 
   void Run() override {
     run_.Wait();
@@ -1392,12 +1472,12 @@
 
   void Wait() { completed_.Wait(); }
 
-  CallStackProfile& profile() { return profile_; }
+  Profile& profile() { return profile_; }
 
  private:
   WaitableEvent run_;
 
-  CallStackProfile profile_;
+  Profile profile_;
   WaitableEvent completed_;
   StackSamplingProfiler profiler_;
 };
@@ -1431,8 +1511,8 @@
     // Wait for them both to finish and validate collection.
     profiler_thread1.Wait();
     profiler_thread2.Wait();
-    EXPECT_EQ(9u, profiler_thread1.profile().samples.size());
-    EXPECT_EQ(8u, profiler_thread2.profile().samples.size());
+    EXPECT_EQ(9u, profiler_thread1.profile().frame_sets.size());
+    EXPECT_EQ(8u, profiler_thread2.profile().frame_sets.size());
 
     profiler_thread1.Join();
     profiler_thread2.Join();
diff --git a/base/task/sequence_manager/task_queue.h b/base/task/sequence_manager/task_queue.h
index 3753b94..d6773a0 100644
--- a/base/task/sequence_manager/task_queue.h
+++ b/base/task/sequence_manager/task_queue.h
@@ -32,12 +32,12 @@
 namespace sequence_manager {
 
 namespace internal {
-class TaskQueueImpl;
 class GracefulQueueShutdownHelper;
+class SequenceManagerImpl;
+class TaskQueueImpl;
 }  // namespace internal
 
 class TimeDomain;
-class SequenceManagerImpl;
 
 class PLATFORM_EXPORT TaskQueue : public SingleThreadTaskRunner {
  public:
@@ -281,8 +281,8 @@
   internal::TaskQueueImpl* GetTaskQueueImpl() const { return impl_.get(); }
 
  private:
+  friend class internal::SequenceManagerImpl;
   friend class internal::TaskQueueImpl;
-  friend class SequenceManagerImpl;
 
   bool IsOnMainThread() const;
 
@@ -304,7 +304,7 @@
 
   const PlatformThreadId thread_id_;
 
-  const WeakPtr<SequenceManagerImpl> sequence_manager_;
+  const WeakPtr<internal::SequenceManagerImpl> sequence_manager_;
 
   const scoped_refptr<internal::GracefulQueueShutdownHelper>
       graceful_queue_shutdown_helper_;
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index bbf9ae7..f21437d 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -30,10 +30,10 @@
 
 class LazyNow;
 class TimeDomain;
-class SequenceManagerImpl;
 
 namespace internal {
 
+class SequenceManagerImpl;
 class WorkQueue;
 class WorkQueueSets;
 
diff --git a/base/task/sequence_manager/time_domain.h b/base/task/sequence_manager/time_domain.h
index d6c3487..14bad6a 100644
--- a/base/task/sequence_manager/time_domain.h
+++ b/base/task/sequence_manager/time_domain.h
@@ -19,9 +19,9 @@
 namespace sequence_manager {
 
 class SequenceManager;
-class SequenceManagerImpl;
 
 namespace internal {
+class SequenceManagerImpl;
 class TaskQueueImpl;
 }  // namespace internal
 
@@ -84,12 +84,13 @@
 
  private:
   friend class internal::TaskQueueImpl;
-  friend class SequenceManagerImpl;
+  friend class internal::SequenceManagerImpl;
   friend class TestTimeDomain;
 
   // Called when the TimeDomain is registered.
   // TODO(kraynov): Pass SequenceManager in the constructor.
-  void OnRegisterWithSequenceManager(SequenceManagerImpl* sequence_manager);
+  void OnRegisterWithSequenceManager(
+      internal::SequenceManagerImpl* sequence_manager);
 
   // Schedule TaskQueue to wake up at certain time, repeating calls with
   // the same |queue| invalidate previous requests.
@@ -125,7 +126,7 @@
     }
   };
 
-  SequenceManagerImpl* sequence_manager_;  // Not owned.
+  internal::SequenceManagerImpl* sequence_manager_;  // Not owned.
   internal::IntrusiveHeap<ScheduledDelayedWakeUp> delayed_wake_up_queue_;
 
   ThreadChecker main_thread_checker_;
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 82d1131ce..cd16765 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -311,6 +311,7 @@
     SkPixmap pixmap;
     staging_surface_->peekPixels(&pixmap);
     gl->BindTexture(backing->texture_target, backing->texture_id);
+    DCHECK(GLSupportsFormat(pool_resource.format()));
     gl->TexSubImage2D(
         backing->texture_target, 0, 0, 0, pool_resource.size().width(),
         pool_resource.size().height(), GLDataFormat(pool_resource.format()),
diff --git a/cc/raster/raster_buffer_provider.cc b/cc/raster/raster_buffer_provider.cc
index 873a432..57f2a6d0 100644
--- a/cc/raster/raster_buffer_provider.cc
+++ b/cc/raster/raster_buffer_provider.cc
@@ -38,6 +38,15 @@
     case viz::LUMINANCE_F16:
     case viz::RGBA_F16:
     case viz::R16_EXT:
+    case viz::BGR_565:
+    case viz::RG_88:
+    case viz::RGBX_8888:
+    case viz::BGRX_8888:
+    case viz::RGBX_1010102:
+    case viz::BGRX_1010102:
+    case viz::YVU_420:
+    case viz::YUV_420_BIPLANAR:
+    case viz::UYVY_422:
       return false;
   }
   NOTREACHED();
@@ -136,6 +145,15 @@
     case viz::RED_8:
     case viz::LUMINANCE_F16:
     case viz::R16_EXT:
+    case viz::BGR_565:
+    case viz::RG_88:
+    case viz::RGBX_8888:
+    case viz::BGRX_8888:
+    case viz::RGBX_1010102:
+    case viz::BGRX_1010102:
+    case viz::YVU_420:
+    case viz::YUV_420_BIPLANAR:
+    case viz::UYVY_422:
       NOTREACHED();
       return;
   }
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc
index 00cc4f7..72dde45 100644
--- a/cc/resources/resource_pool.cc
+++ b/cc/resources/resource_pool.cc
@@ -306,7 +306,6 @@
         resource.resource_->size(), resource.resource_->format());
   }
   transferable.format = resource.resource_->format();
-  transferable.buffer_format = viz::BufferFormat(transferable.format);
   transferable.color_space = resource.resource_->color_space();
   resource.resource_->set_resource_id(resource_provider_->ImportResource(
       std::move(transferable),
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc
index 6ed88e94..171b177 100644
--- a/cc/resources/resource_pool_unittest.cc
+++ b/cc/resources/resource_pool_unittest.cc
@@ -704,7 +704,6 @@
   EXPECT_EQ(transfer[0].mailbox_holder.sync_token, sync_token);
   EXPECT_EQ(transfer[0].mailbox_holder.texture_target, target);
   EXPECT_EQ(transfer[0].format, format);
-  EXPECT_EQ(transfer[0].buffer_format, viz::BufferFormat(format));
   EXPECT_TRUE(transfer[0].read_lock_fences_enabled);
   EXPECT_TRUE(transfer[0].is_overlay_candidate);
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index b69d9a2..efd246e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -5087,7 +5087,6 @@
         mailbox, GL_LINEAR, texture_alloc.texture_target, sync_token,
         upload_size, texture_alloc.overlay_candidate);
     transferable.format = format;
-    transferable.buffer_format = viz::BufferFormat(format);
   } else {
     mojo::ScopedSharedBufferHandle memory_handle =
         viz::bitmap_allocation::DuplicateAndCloseMappedBitmap(
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 56fb0c75..e0a43dc 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -647,7 +647,7 @@
   ]
 
   if (enable_feed_in_chrome) {
-    deps += feed_conformance_test_deps
+    deps += feed_test_deps
   }
 
   data = [
diff --git a/chrome/android/feed/core/DEPS b/chrome/android/feed/core/DEPS
index 3bfdb5b..062b9e0 100644
--- a/chrome/android/feed/core/DEPS
+++ b/chrome/android/feed/core/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/background_task_scheduler",
   "+components/feed",
   "+content/public/android/java/src/org/chromium/content_public",
   "+third_party/feed"
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
index a79a5ec..3312351 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -33,7 +33,7 @@
         return sFeedProcessScope;
     }
 
-    /*
+    /**
      * @return The {@link FeedSchedulerBridge} that was given to the {@link FeedProcessScope}.
      */
     public static FeedSchedulerBridge getFeedSchedulerBridge() {
@@ -62,6 +62,7 @@
                                 new LoggingApiImpl(), new FeedNetworkBridge(profile),
                                 sFeedSchedulerBridge, lifecycleListener, DebugBehavior.SILENT)
                         .build();
-        sFeedSchedulerBridge.setRequestManager(sFeedProcessScope.getRequestManager());
+        sFeedSchedulerBridge.initializeFeedDependencies(
+                sFeedProcessScope.getRequestManager(), sFeedProcessScope.getSessionManager());
     }
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedRefreshTask.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedRefreshTask.java
new file mode 100644
index 0000000..36478f42
--- /dev/null
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedRefreshTask.java
@@ -0,0 +1,89 @@
+// 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.feed;
+
+import android.content.Context;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask;
+import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler;
+import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
+import org.chromium.components.background_task_scheduler.TaskIds;
+import org.chromium.components.background_task_scheduler.TaskInfo;
+import org.chromium.components.background_task_scheduler.TaskParameters;
+
+/**
+ * A task implementation that loads native and then tries to refresh the Feed's articles. Failures
+ * or interruptions are not retried or rescheduled.
+ */
+public class FeedRefreshTask extends NativeBackgroundTask {
+    // The amount of "flex" to add around the fetching periods, as a ratio of the period.
+    private static final double FLEX_FACTOR = 0.1;
+
+    /**
+     * Schedules a periodic task to wake up every thresholdMs and try to refresh. Allows for a bit
+     * of flex time before and after thresholdMs. Replaces the previous scheduling of the feed
+     * refresh task.
+     *
+     * @param thresholdMs the target number of milliseconds between each refresh.
+     */
+    public static void scheduleWakeUp(long thresholdMs) {
+        // The flex given to the BackgroundTaskScheduler is a period of time before the |intervalMs|
+        // point in time. Because we want to schedule for +/- FLEX_FACTOR around |thresholdMs|, some
+        // adjustments below are needed.
+        long intervalMs = (long) (thresholdMs * (1 + FLEX_FACTOR));
+        long flexWindowSizeMs = (long) (thresholdMs * 2 * FLEX_FACTOR);
+
+        BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler();
+        TaskInfo taskInfo = TaskInfo.createPeriodicTask(TaskIds.FEED_REFRESH_JOB_ID,
+                                            FeedRefreshTask.class, intervalMs, flexWindowSizeMs)
+                                    .setIsPersisted(true)
+                                    .setUpdateCurrent(true)
+                                    .setRequiredNetworkType(TaskInfo.NETWORK_TYPE_ANY)
+                                    .build();
+        scheduler.schedule(ContextUtils.getApplicationContext(), taskInfo);
+    }
+
+    /** Clears previously scheduled task. */
+    public static void cancelWakeUp() {
+        BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler();
+        scheduler.cancel(ContextUtils.getApplicationContext(), TaskIds.FEED_REFRESH_JOB_ID);
+    }
+
+    @Override
+    protected int onStartTaskBeforeNativeLoaded(
+            Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
+        // Nothing to setup without native, just wait.
+        return NativeBackgroundTask.LOAD_NATIVE;
+    }
+
+    @Override
+    protected void onStartTaskWithNative(
+            Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
+        FeedProcessScopeFactory.getFeedSchedulerBridge().onFixedTimer(() -> {
+            // Regardless of success, mark ourselves as completed.
+            callback.taskFinished(false);
+        });
+    }
+
+    @Override
+    protected boolean onStopTaskBeforeNativeLoaded(Context context, TaskParameters taskParameters) {
+        // Don't retry, this task is periodic anyways.
+        return false;
+    }
+
+    @Override
+    protected boolean onStopTaskWithNative(Context context, TaskParameters taskParameters) {
+        // Don't retry, this task is periodic anyways.
+        return false;
+    }
+
+    @Override
+    public void reschedule(Context context) {
+        ThreadUtils.runOnUiThread(
+                () -> { FeedProcessScopeFactory.getFeedSchedulerBridge().onTaskReschedule(); });
+    }
+}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
index 25c69b7..c8a04f0 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
@@ -4,10 +4,15 @@
 
 package org.chromium.chrome.browser.feed;
 
+import android.support.annotation.NonNull;
+
+import com.google.android.libraries.feed.api.common.MutationContext;
 import com.google.android.libraries.feed.api.requestmanager.RequestManager;
+import com.google.android.libraries.feed.api.sessionmanager.SessionManager;
 import com.google.android.libraries.feed.host.scheduler.SchedulerApi;
 import com.google.search.now.wire.feed.FeedQueryProto.FeedQuery.RequestReason;
 
+import org.chromium.base.Callback;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -20,6 +25,7 @@
 public class FeedSchedulerBridge implements SchedulerApi {
     private long mNativeBridge;
     private RequestManager mRequestManager;
+    private SessionManager mSessionManager;
 
     /**
      * Creates a FeedSchedulerBridge for accessing native scheduling logic.
@@ -30,24 +36,28 @@
         mNativeBridge = nativeInit(profile);
     }
 
-    /*
-     * Cleans up native half of this bridge.
-     */
+    /** Cleans up the native half of this bridge. */
     public void destroy() {
         assert mNativeBridge != 0;
         nativeDestroy(mNativeBridge);
         mNativeBridge = 0;
     }
 
-    /*
-     * Sets our copy of the RequestManager. Should be done as early as possible, as the scheduler
-     * will be unable to trigger refreshes until after it has a reference to a RequestManager. When
-     * this is called, it is assumed that the RequestManager is initialized and can be used.
+    /**
+     * Sets our copies for various interfaces provided by the Feed library. Should be done as early
+     * as possible, as the scheduler will be unable to trigger refreshes until after it has the
+     * mechanisms to correctly do so. When this is called, it is assumed that the given
+     * RequestManager and SessionManager are initialized and can be used immediately.
      *
      * @param requestManager The interface that allows us make refresh requests.
+     * @param sessionManager The interface that provides correct consumtion of refresh results.
      */
-    public void setRequestManager(RequestManager requestManager) {
+    public void initializeFeedDependencies(
+            @NonNull RequestManager requestManager, @NonNull SessionManager sessionManager) {
+        assert mRequestManager == null;
+        assert mSessionManager == null;
         mRequestManager = requestManager;
+        mSessionManager = sessionManager;
     }
 
     @Override
@@ -98,20 +108,36 @@
         nativeOnForegrounded(mNativeBridge);
     }
 
-    public void onFixedTimer() {
+    public void onFixedTimer(Runnable onCompletion) {
         assert mNativeBridge != 0;
-        nativeOnFixedTimer(mNativeBridge);
+        // Convert to single argument Callback to make invoking from native more convenient.
+        nativeOnFixedTimer(mNativeBridge, (Void ignored) -> onCompletion.run());
+    }
+
+    public void onTaskReschedule() {
+        assert mNativeBridge != 0;
+        nativeOnTaskReschedule(mNativeBridge);
     }
 
     @CalledByNative
     private boolean triggerRefresh() {
-        if (mRequestManager != null) {
-            mRequestManager.triggerRefresh(RequestReason.SCHEDULED_REFRESH, ignored -> {});
+        if (mRequestManager != null && mSessionManager != null) {
+            mRequestManager.triggerRefresh(RequestReason.SCHEDULED_REFRESH,
+                    mSessionManager.getUpdateConsumer(MutationContext.EMPTY_CONTEXT));
             return true;
         }
         return false;
     }
 
+    @CalledByNative
+    private void scheduleWakeUp(long thresholdMs) {
+        FeedRefreshTask.scheduleWakeUp(thresholdMs);
+    }
+
+    @CalledByNative
+    private void cancelWakeUp() {
+        FeedRefreshTask.cancelWakeUp();
+    }
     private native long nativeInit(Profile profile);
     private native void nativeDestroy(long nativeFeedSchedulerBridge);
     private native int nativeShouldSessionRequestData(long nativeFeedSchedulerBridge,
@@ -121,5 +147,7 @@
     private native void nativeOnRequestError(
             long nativeFeedSchedulerBridge, int networkResponseCode);
     private native void nativeOnForegrounded(long nativeFeedSchedulerBridge);
-    private native void nativeOnFixedTimer(long nativeFeedSchedulerBridge);
+    private native void nativeOnFixedTimer(
+            long nativeFeedSchedulerBridge, Callback<Void> onCompletion);
+    private native void nativeOnTaskReschedule(long nativeFeedSchedulerBridge);
 }
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index 49233be..9dd42da 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -15,6 +15,7 @@
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java",
+    "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedRefreshTask.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java",
@@ -22,12 +23,18 @@
 
   feed_srcjar_deps = [ "//components/feed/core:feed_core_java_enums_srcjar" ]
 
-  feed_conformance_test_sources = [
-    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNetworkBridgeConformanceTest.java",
-    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java",
+  feed_junit_test_java_sources = [
+    "junit/src/org/chromium/chrome/browser/feed/FeedImageLoaderTest.java",
+    "junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java",
   ]
 
-  feed_conformance_test_deps = [
+  feed_test_java_sources = [
+    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNetworkBridgeConformanceTest.java",
+    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java",
+    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java",
+  ]
+
+  feed_test_deps = [
     "//third_party/feed:feed_lib_java",
     "//third_party/feed:feed_conformance_test_lib_android_java",
   ]
diff --git a/chrome/android/java/res/color/blue_mode_tint.xml b/chrome/android/java/res/color/blue_mode_tint.xml
index b918ba4..c51af18 100644
--- a/chrome/android/java/res/color/blue_mode_tint.xml
+++ b/chrome/android/java/res/color/blue_mode_tint.xml
@@ -4,5 +4,5 @@
      found in the LICENSE file.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/light_active_color"/>
+    <item android:color="@color/default_icon_color_blue"/>
 </selector>
diff --git a/chrome/android/java/res/color/blue_when_enabled.xml b/chrome/android/java/res/color/blue_when_enabled.xml
index 855d690..0593a59 100644
--- a/chrome/android/java/res/color/blue_when_enabled.xml
+++ b/chrome/android/java/res/color/blue_when_enabled.xml
@@ -5,5 +5,5 @@
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false" android:color="@color/google_grey_300" />
-    <item android:color="@color/light_active_color"/>
+    <item android:color="@color/default_icon_color_blue"/>
 </selector>
diff --git a/chrome/android/java/res/drawable/checkmark_blue.xml b/chrome/android/java/res/drawable/checkmark_blue.xml
index fc7cebc..10403b0 100644
--- a/chrome/android/java/res/drawable/checkmark_blue.xml
+++ b/chrome/android/java/res/drawable/checkmark_blue.xml
@@ -14,6 +14,6 @@
         android:fillColor="@android:color/white"
         android:pathData="M4 6H20v12H4z" />
     <path
-        android:fillColor="@color/google_blue_500"
+        android:fillColor="@color/default_icon_color_blue"
         android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
 </vector>
diff --git a/chrome/android/java/res/drawable/ic_check_googblue_24dp_animated.xml b/chrome/android/java/res/drawable/ic_check_googblue_24dp_animated.xml
index b775b23a..a236f312 100644
--- a/chrome/android/java/res/drawable/ic_check_googblue_24dp_animated.xml
+++ b/chrome/android/java/res/drawable/ic_check_googblue_24dp_animated.xml
@@ -21,7 +21,7 @@
                 android:name="ic_check"
                 android:pathData="M4.12,12.705 l4.88,4.88 l11.295,-11.29"
                 android:strokeWidth="2"
-                android:strokeColor="#4285F4"/>
+                android:strokeColor="@color/default_icon_color_blue"/>
         </vector>
     </aapt:attr>
 
diff --git a/chrome/android/java/res/drawable/infobar_download_complete.xml b/chrome/android/java/res/drawable/infobar_download_complete.xml
index 9e516c4..a9eb187c 100644
--- a/chrome/android/java/res/drawable/infobar_download_complete.xml
+++ b/chrome/android/java/res/drawable/infobar_download_complete.xml
@@ -20,6 +20,6 @@
     <path
         android:name="check_mark"
         android:pathData="M5 18h14v2H5v-2zm4.6-2.7L5 10.7l2-1.9 2.6 2.6L17 4l2 2-9.4 9.3z"
-        android:fillColor="@color/google_blue_500"/>
+        android:fillColor="@color/default_icon_color_blue"/>
 
 </vector>
\ No newline at end of file
diff --git a/chrome/android/java/res/drawable/infobar_downloading_fill_animation.xml b/chrome/android/java/res/drawable/infobar_downloading_fill_animation.xml
index f1e96f4e..e78893d 100644
--- a/chrome/android/java/res/drawable/infobar_downloading_fill_animation.xml
+++ b/chrome/android/java/res/drawable/infobar_downloading_fill_animation.xml
@@ -28,7 +28,7 @@
 
                 <path
                     android:name="arrow_blue"
-                    android:fillColor="@color/google_blue_500"
+                    android:fillColor="@color/default_icon_color_blue"
                     android:pathData="M30,15 L42,15 L42,30 L52,30 L36,46 L20,30 L30,30 Z"
                     android:strokeColor="#00000000"/>
             </group>
@@ -42,7 +42,7 @@
             <path
                 android:name="bar"
                 android:pathData="M12,54 L60,54"
-                android:strokeColor="@color/google_blue_500"
+                android:strokeColor="@color/default_icon_color_blue"
                 android:strokeWidth="6"/>
 
         </vector>
@@ -67,14 +67,14 @@
                     android:duration="0"
                     android:interpolator="@android:interpolator/linear"
                     android:propertyName="fillColor"
-                    android:valueFrom="@color/google_blue_500"
-                    android:valueTo="@color/google_blue_500"/>
+                    android:valueFrom="@color/default_icon_color_blue"
+                    android:valueTo="@color/default_icon_color_blue"/>
                 <objectAnimator
                     android:duration="@integer/download_infobar_fill_out_delay"
                     android:startOffset="@integer/download_infobar_fill_in_delay"
                     android:interpolator="@android:interpolator/linear"
                     android:propertyName="fillColor"
-                    android:valueFrom="@color/google_blue_500"
+                    android:valueFrom="@color/default_icon_color_blue"
                     android:valueTo="@color/google_blue_50"/>
             </set>
         </aapt:attr>
diff --git a/chrome/android/java/res/drawable/infobar_downloading_sweep_animation.xml b/chrome/android/java/res/drawable/infobar_downloading_sweep_animation.xml
index 971a65ae..c88e9333 100644
--- a/chrome/android/java/res/drawable/infobar_downloading_sweep_animation.xml
+++ b/chrome/android/java/res/drawable/infobar_downloading_sweep_animation.xml
@@ -28,7 +28,7 @@
 
                 <path
                     android:name="arrow_blue"
-                    android:fillColor="@color/google_blue_500"
+                    android:fillColor="@color/default_icon_color_blue"
                     android:pathData="M30,15 L42,15 L42,30 L52,30 L36,46 L20,30 L30,30 Z"
                     android:strokeColor="#00000000"/>
             </group>
@@ -97,11 +97,11 @@
                     android:startOffset="300"
                     android:propertyName="strokeColor"
                     android:valueFrom="@color/google_blue_50"
-                    android:valueTo="@color/google_blue_500"/>
+                    android:valueTo="@color/default_icon_color_blue"/>
                 <objectAnimator
                     android:duration="@integer/download_infobar_sweep_down_delay"
                     android:propertyName="strokeColor"
-                    android:valueFrom="@color/google_blue_500"
+                    android:valueFrom="@color/default_icon_color_blue"
                     android:valueTo="@color/google_blue_50"/>
             </set>
         </aapt:attr>
diff --git a/chrome/android/java/res/layout/download_manager_ui_space_widget.xml b/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
index 8cff29c..4171d72 100644
--- a/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
+++ b/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
@@ -35,8 +35,8 @@
             android:layout_marginTop="8dp"
             android:layout_marginBottom="8dp"
             app:colorBackground="@color/google_grey_300"
-            app:colorProgress="@color/google_blue_500_alpha_38_opaque"
-            app:colorSecondaryProgress="@color/google_blue_500" />
+            app:colorProgress="@color/modern_blue_600_alpha_38_opaque"
+            app:colorSecondaryProgress="@color/modern_blue_600" />
 
         <TextView
             android:id="@+id/size_free_and_other_apps"
diff --git a/chrome/android/java/res/layout/keyboard_accessory_action.xml b/chrome/android/java/res/layout/keyboard_accessory_action.xml
index 6508df7..8c296a1 100644
--- a/chrome/android/java/res/layout/keyboard_accessory_action.xml
+++ b/chrome/android/java/res/layout/keyboard_accessory_action.xml
@@ -18,5 +18,5 @@
     android:textAlignment="center"
     android:textColor="@color/white_alpha_90"
     android:textSize="@dimen/keyboard_accessory_text_size"
-    app:buttonColor="@color/google_blue_500"
+    app:buttonColor="@color/light_active_color"
     app:buttonRaised="false"/>
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
index 40ca43d..723e93c 100644
--- a/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
+++ b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
@@ -29,7 +29,7 @@
         android:layout_marginStart="24dp"
         android:layout_marginTop="6dp"
         android:ellipsize="end"
-        android:maxLines="1"
+        android:singleLine="true"
         android:text="@string/signin_promo_continue_as"/>
 
     <Button
@@ -42,6 +42,6 @@
         android:layout_marginStart="24dp"
         android:layout_marginTop="6dp"
         android:ellipsize="end"
-        android:maxLines="1"
+        android:singleLine="true"
         android:text="@string/signin_promo_choose_account"/>
 </merge>
\ No newline at end of file
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 07bd8ed..72e16cb 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -21,9 +21,9 @@
     <style name="MainThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:textColorHighlight">@color/text_highlight_color</item>
-        <item name="android:textColorLink">@color/light_active_color</item>
+        <item name="android:textColorLink">@color/default_text_color_link</item>
         <item name="colorPrimaryDark">@android:color/black</item>
-        <item name="android:colorAccent" tools:targetApi="21">@color/google_blue_500</item>
+        <item name="android:colorAccent" tools:targetApi="21">@color/light_active_color</item>
         <item name="android:statusBarColor" tools:targetApi="21">@android:color/black</item>
 
         <!--  Overriding AppCompat values -->
@@ -455,7 +455,7 @@
     <style name="DialogWhenLargeBase" parent="Theme.AppCompat.Light.DialogWhenLarge" >
         <item name="android:windowBackground">@drawable/bg_white_dialog</item>
         <item name="android:textAppearance">@style/BlackBodyDefault</item>
-        <item name="android:textColorLink">@color/light_active_color</item>
+        <item name="android:textColorLink">@color/default_text_color_link</item>
         <item name="colorPrimaryDark">@android:color/black</item>
         <item name="colorAccent">@color/light_active_color</item>
         <item name="buttonStyle">@style/MainButtonStyle</item>
@@ -472,7 +472,7 @@
     </style>
 
     <style name="SigninDialogButtonStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
-        <item name="android:textColor">@color/light_active_color</item>
+        <item name="android:textColor">@color/default_text_color_link</item>
     </style>
 
     <!-- Contextual Search styles -->
@@ -538,7 +538,7 @@
         <item name="android:textColor">@color/explanation_text_color</item>
     </style>
     <style name="EditorDialogSectionAddButtonLabel">
-        <item name="android:textColor">@color/light_active_color</item>
+        <item name="android:textColor">@color/default_text_color_link</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">true</item>
     </style>
@@ -594,10 +594,12 @@
          they are removed from @style/ButtonCompatBase. -->
     <style name="SigninButtonBorderlessRegular">
         <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:paddingStart">0dp</item>
+        <item name="android:paddingEnd">0dp</item>
         <item name="android:fontFamily">sans-serif</item>
         <item name="android:textAllCaps">false</item>
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">@color/light_active_color</item>
+        <item name="android:textColor">@color/default_text_color_link</item>
         <item name="android:textSize">14sp</item>
     </style>
 
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index c14018f..60479bb 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -4,25 +4,48 @@
      found in the LICENSE file. -->
 
 <resources>
-    <!-- Common colors -->
+    <!-- Common text colors -->
     <color name="default_text_color">@color/black_alpha_87</color>
     <color name="default_primary_color">#F2F2F2</color>
     <color name="default_text_color_link">@color/modern_blue_600</color>
-    <!-- Deprecated. Use dark_mode_tint or default_icon_color for icons instead. -->
-    <color name="light_normal_color">#5A5A5A</color>
-    <color name="light_active_color">@color/google_blue_500</color>
-    <color name="default_icon_color">@color/modern_grey_800</color>
-    <color name="light_icon_color">@color/modern_grey_500</color>
     <color name="input_underline_error_color">#D32F2F</color>
     <color name="explanation_text_color">#909090</color>
     <color name="text_highlight_color">#C6DAFC</color>
-    <color name="dark_action_bar_color">#263238</color>
     <color name="descriptive_text_color">#646464</color>
     <color name="error_text_color">@color/google_red_700</color>
+
+    <!-- Common control colors for toggles, checkboxes, ratio buttons and accent. -->
+    <!-- Deprecated. Use dark_mode_tint or default_icon_color for icons instead. -->
+    <color name="light_normal_color">#5A5A5A</color>
+    <color name="light_active_color">@color/modern_blue_600</color>
+
+    <!-- Common icon colors for drawables. -->
+    <color name="default_icon_color">@color/modern_grey_800</color>
+    <color name="default_icon_color_blue">@color/modern_blue_600</color>
+    <color name="light_icon_color">@color/modern_grey_500</color>
+
+    <!-- Other common colors -->
+    <color name="dark_action_bar_color">#263238</color>
+    <color name="modal_dialog_scrim_color">#7F000000</color>
+
+    <!-- Modern color palette -->
+    <color name="black_alpha_11">#1D000000</color>
+    <color name="black_alpha_12">#1F000000</color>
+    <color name="black_alpha_20">#33000000</color>
+    <color name="black_alpha_24">#3D000000</color>
+    <color name="black_alpha_30">#4D000000</color>
+    <color name="black_alpha_40">#66000000</color>
+    <color name="black_alpha_65">#A6000000</color>
+    <color name="white_alpha_50">#80FFFFFF</color>
+    <color name="white_alpha_90">#E6FFFFFF</color>
+
+    <color name="modern_light_grey">#F1F3F4</color>
+    <color name="modern_grey_800">#3C4043</color>
+    <color name="modern_grey_500">#9AA0A6</color>
+
+    <!-- Old color palette -->
     <color name="google_blue_grey_500">#607D8B</color>
     <color name="google_blue_50">#E3F2FD</color>
-    <color name="google_blue_500">#4285F4</color>
-    <color name="google_blue_700">#3367D6</color>
     <color name="google_red_700">#C53929</color>
     <color name="google_green_700">#0B8043</color>
     <color name="google_grey_50">#FAFAFA</color>
@@ -32,23 +55,7 @@
     <color name="google_grey_400">#BDBDBD</color>
     <color name="google_grey_500">#9E9E9E</color>
     <color name="google_grey_600">#757575</color>
-    <color name="black_alpha_11">#1D000000</color>
-    <color name="black_alpha_12">#1F000000</color>
-    <color name="white_alpha_50">#80FFFFFF</color>
-    <color name="black_alpha_65">#A6000000</color>
-    <color name="white_alpha_90">#E6FFFFFF</color>
     <color name="light_grey">#CCCCCC</color>
-    <color name="modal_dialog_scrim_color">#7F000000</color>
-
-    <color name="modern_light_grey">#F1F3F4</color>
-    <color name="modern_grey_800">#3C4043</color>
-    <color name="modern_grey_500">#9AA0A6</color>
-
-    <!-- New list of common text colors -->
-    <color name="black_alpha_20">#33000000</color>
-    <color name="black_alpha_24">#3D000000</color>
-    <color name="black_alpha_30">#4D000000</color>
-    <color name="black_alpha_40">#66000000</color>
 
     <!-- Infobar colors -->
     <color name="infobar_accent_blue">@color/modern_blue_600</color>
@@ -125,7 +132,7 @@
     <color name="snippets_list_header_text_color">#646464</color>
     <color name="suggestions_modern_bg">@android:color/white</color>
     <color name="tile_view_text">@color/black_alpha_54</color>
-    <color name="suggestions_offline_badge_tint">@color/google_blue_500</color>
+    <color name="suggestions_offline_badge_tint">@color/default_icon_color_blue</color>
 
     <!-- Incognito NTP Colors. -->
     <color name="incognito_emphasis">@android:color/white</color>
@@ -200,7 +207,7 @@
     <!-- Other colors -->
     <color name="media_viewer_bg">#000000</color>
     <color name="image_viewer_bg">#0E0E0E</color>
-    <color name="google_blue_500_alpha_38_opaque">#B7D1FB</color>
+    <color name="modern_blue_600_alpha_38_opaque">#A8CAF6</color>
     <color name="toolbar_shadow_color">@color/black_alpha_11</color>
     <color name="bottom_system_nav_color">@android:color/white</color>
     <color name="bottom_system_nav_divider_color">@color/black_alpha_12</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index a2523f5c..189caed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -193,6 +193,7 @@
     public static final String CONTEXTUAL_SUGGESTIONS_BUTTON = "ContextualSuggestionsButton";
     public static final String CONTEXTUAL_SUGGESTIONS_SLIM_PEEK_UI =
             "ContextualSuggestionsSlimPeekUI";
+    public static final String CONTEXTUAL_SUGGESTIONS_OPT_OUT = "ContextualSuggestionsOptOut";
     public static final String CUSTOM_CONTEXT_MENU = "CustomContextMenu";
     public static final String CUSTOM_FEEDBACK_UI = "CustomFeedbackUi";
     // Enables the Data Reduction Proxy menu item in the main menu rather than under Settings on
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardSuggestions.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardSuggestions.java
index fc22396e..274f22f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardSuggestions.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardSuggestions.java
@@ -153,7 +153,7 @@
         Drawable drawable = AppCompatResources.getDrawable(getContext(), suggestion.getIconId());
         if (isKeyboardAccessoryHint) {
             drawable.setColorFilter(
-                    ApiCompatibilityUtils.getColor(getResources(), R.color.google_blue_500),
+                    ApiCompatibilityUtils.getColor(getResources(), R.color.default_icon_color_blue),
                     PorterDuff.Mode.SRC_IN);
         } else {
             icon.setContentDescription(suggestion.getLabel());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
index 5adfbe0..23b010f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -530,7 +530,7 @@
                     R.string.contextual_suggestions_in_product_help,
                     R.string.contextual_suggestions_in_product_help, true, rectProvider,
                     R.drawable.ic_logo_googleg_24dp);
-            mModel.setToolbarArrowTintResourceId(R.color.google_blue_500);
+            mModel.setToolbarArrowTintResourceId(R.color.default_icon_color_blue);
         } else {
             mHelpBubble = new TextBubble(mIphParentView.getContext(), mIphParentView,
                     R.string.contextual_suggestions_in_product_help,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/EnabledStateMonitor.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/EnabledStateMonitor.java
index 3b903b0..e13f313 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/EnabledStateMonitor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/EnabledStateMonitor.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
@@ -85,7 +86,8 @@
 
     /** @return Whether the user settings for contextual suggestions should be shown. */
     public static boolean shouldShowSettings() {
-        return isDSEConditionMet() && !AccessibilityUtil.isAccessibilityEnabled();
+        return isDSEConditionMet() && !AccessibilityUtil.isAccessibilityEnabled()
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_OPT_OUT);
     }
 
     /** @return Whether the settings state is currently enabled. */
@@ -105,7 +107,9 @@
     /** @return Whether the state is currently enabled. */
     public static boolean getEnabledState() {
         return getSettingsEnabled()
-                && PrefServiceBridge.getInstance().getBoolean(Pref.CONTEXTUAL_SUGGESTIONS_ENABLED);
+                && (PrefServiceBridge.getInstance().getBoolean(Pref.CONTEXTUAL_SUGGESTIONS_ENABLED)
+                           || !ChromeFeatureList.isEnabled(
+                                      ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_OPT_OUT));
     }
 
     public static void recordEnabled(boolean enabled) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
index 6c5159b..043da8b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
@@ -213,7 +213,7 @@
                     itemView.getResources().getInteger(R.integer.list_item_level_default));
             mThumbnail.setImageResource(mIconId);
             mThumbnail.setTint(AppCompatResources.getColorStateList(
-                    itemView.getContext(), R.color.google_blue_500));
+                    itemView.getContext(), R.color.default_icon_color_blue));
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
index c289eaa..b651fa05 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
@@ -454,7 +454,7 @@
 
             if (permissionParams.warningTextResource != 0) {
                 permissionParams.iconResource = R.drawable.exclamation_triangle;
-                permissionParams.iconTintColorResource = R.color.google_blue_700;
+                permissionParams.iconTintColorResource = R.color.default_icon_color_blue;
                 permissionParams.clickCallback =
                         createPermissionClickCallback(intentOverride, androidPermissions);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
index 60af1e4..b111b48 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -887,7 +887,7 @@
                         drawableTint = R.color.error_text_color;
                     } else {
                         drawableId = R.drawable.plus;
-                        drawableTint = R.color.light_active_color;
+                        drawableTint = R.color.default_icon_color_blue;
                     }
 
                     TintedDrawable tintedDrawable = TintedDrawable.constructTintedDrawable(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncPreference.java
index 9c9e1f8..fceaeb8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SyncPreference.java
@@ -43,8 +43,8 @@
             // Sets preference icon and tints it to blue.
             Drawable icon = ApiCompatibilityUtils.getDrawable(
                     getContext().getResources(), R.drawable.permission_background_sync);
-            icon.setColorFilter(ApiCompatibilityUtils.getColor(
-                                        getContext().getResources(), R.color.light_active_color),
+            icon.setColorFilter(ApiCompatibilityUtils.getColor(getContext().getResources(),
+                                        R.color.default_icon_color_blue),
                     PorterDuff.Mode.SRC_IN);
             setIcon(icon);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/TasksUma.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/TasksUma.java
index 6941b20..099666a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/TasksUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/TasksUma.java
@@ -80,9 +80,9 @@
 
         RecordHistogram.recordCountHistogram("Tabs.Tasks.TabsInGroupCount", tabsInGroupCount);
 
-        double tabsInGroupRatio = tabsInGroupCount * 1.0 / totalTabCount;
+        double tabsInGroupRatioPercent = tabsInGroupCount * 1.0 / totalTabCount * 100.0;
         RecordHistogram.recordPercentageHistogram(
-                "Tabs.Tasks.TabsInGroupRatio", (int) tabsInGroupRatio * 100);
+                "Tabs.Tasks.TabsInGroupRatio", (int) tabsInGroupRatioPercent);
 
         if (tabGroupCount != 0) {
             int averageGroupSize = tabsInGroupCount / tabGroupCount;
@@ -91,14 +91,14 @@
             Log.d(TAG, "AverageGroupSize: %d", averageGroupSize);
         }
 
-        double tabGroupDensity = tabGroupCount * 1.0 / totalTabCount;
+        double tabGroupDensityPercent = tabGroupCount * 1.0 / totalTabCount * 100.0;
         RecordHistogram.recordPercentageHistogram(
-                "Tabs.Tasks.TabGroupDensity", (int) tabGroupDensity * 100);
+                "Tabs.Tasks.TabGroupDensity", (int) tabGroupDensityPercent);
 
         Log.d(TAG, "TotalTabCount: %d", totalTabCount);
         Log.d(TAG, "TabGroupCount: %d", tabGroupCount);
         Log.d(TAG, "TabsInGroupCount: %d", tabsInGroupCount);
-        Log.d(TAG, "TabsInGroupRatio: %f", tabsInGroupRatio);
-        Log.d(TAG, "TabGroupDensity: %f", tabGroupDensity);
+        Log.d(TAG, "TabsInGroupRatioPercent: %d", (int) tabsInGroupRatioPercent);
+        Log.d(TAG, "TabGroupDensityPercent: %d", (int) tabGroupDensityPercent);
     }
 }
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 990b9ce..cb51740 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
@@ -68,6 +68,7 @@
 import org.chromium.chrome.browser.omnibox.LocationBarPhone;
 import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -1887,7 +1888,8 @@
         // Don't inflate the incognito toggle button unless the horizontal tab switcher experiment
         // is enabled and the user actually enters the tab switcher.
         if (mIncognitoToggleButton == null && mTabSwitcherState != STATIC_TAB
-                && usingHorizontalTabSwitcher()) {
+                && usingHorizontalTabSwitcher()
+                && PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
             ViewStub incognitoToggleButtonStub = findViewById(R.id.incognito_button_stub);
             mIncognitoToggleButton = (IncognitoToggleButton) incognitoToggleButtonStub.inflate();
             mIncognitoToggleButton.setOnClickListener(this);
@@ -2789,12 +2791,12 @@
         if (mExperimentalButton == null) {
             ViewStub viewStub = findViewById(R.id.experimental_button_stub);
             mExperimentalButton = (TintedImageButton) viewStub.inflate();
-            mBrowsingModeViews.add(mExperimentalButton);
         } else {
             assert mExperimentalButton.getVisibility()
                     == View.GONE : "#disableExperimentalButton() should be called first.";
         }
 
+        mBrowsingModeViews.add(mExperimentalButton);
         mExperimentalButton.setOnClickListener(onClickListener);
         mExperimentalButton.setImageResource(drawableResId);
         mExperimentalButton.setContentDescription(
@@ -2810,6 +2812,7 @@
         if (mExperimentalButton == null) return;
 
         mExperimentalButton.setVisibility(View.GONE);
+        mBrowsingModeViews.remove(mExperimentalButton);
         if (mLayoutUpdateHost != null) mLayoutUpdateHost.requestUpdate();
     }
 
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
index d70282c7..ceca4af 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
@@ -21,7 +21,7 @@
  * <ImageViewTinterInstanceOwner
  *     xmlns:android="http://schemas.android.com/apk/res/android"
  *     xmlns:app="http://schemas.android.com/apk/res-auto"
- *     app:chrometint="@color/light_active_color" />
+ *     app:chrometint="@color/default_icon_color_blue" />
  */
 public class ImageViewTinter {
     /** Classes that own an ImageViewTinter must implement these functions. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
index e0c6912..d90721c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
@@ -153,8 +153,8 @@
         Resources resources = ContextUtils.getApplicationContext().getResources();
 
         @ColorInt
-        int color = ApiCompatibilityUtils.getColor(
-                resources, useLightPulseColor ? R.color.google_grey_100 : R.color.google_blue_500);
+        int color = ApiCompatibilityUtils.getColor(resources,
+                useLightPulseColor ? R.color.google_grey_100 : R.color.default_icon_color_blue);
         if (mState.color == color) return;
 
         int alpha = getAlpha();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
index f6706e2..df1a82e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
@@ -94,8 +94,8 @@
 
         if (fieldModel.getActionIconAction() != null) {
             mActionIcon = (ImageView) mIconsLayer.findViewById(R.id.action_icon);
-            mActionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(
-                    context, fieldModel.getActionIconResourceId(), R.color.light_active_color));
+            mActionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(context,
+                    fieldModel.getActionIconResourceId(), R.color.default_icon_color_blue));
             mActionIcon.setContentDescription(context.getResources().getString(
                     fieldModel.getActionIconDescriptionForAccessibility()));
             mActionIcon.setOnClickListener(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
index 80f8713..bf74f815 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
@@ -68,7 +68,7 @@
             // Create the "+" icon, put it left of the text and add appropriate padding.
             mTextView.setCompoundDrawablesWithIntrinsicBounds(
                     TintedDrawable.constructTintedDrawable(
-                            getContext(), R.drawable.plus, R.color.light_active_color),
+                            getContext(), R.drawable.plus, R.color.default_icon_color_blue),
                     null, null, null);
             Resources resources = getContext().getResources();
             mTextView.setCompoundDrawablePadding(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
index 7ec55ea..ec38e62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java
@@ -188,8 +188,8 @@
         addOnDismissListener(mDismissListener);
 
         // Set predefined styles for the TextBubble.
-        mDrawable.setBubbleColor(
-                ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.google_blue_500));
+        mDrawable.setBubbleColor(ApiCompatibilityUtils.getColor(
+                mContext.getResources(), R.color.light_active_color));
     }
 
     /** Shows the bubble. Will have no effect if the bubble is already showing. */
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index d9000ed3..2b862cd 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -2230,11 +2230,8 @@
 }
 
 if (enable_feed_in_chrome) {
-  chrome_junit_test_java_sources += [
-    "junit/src/org/chromium/chrome/browser/feed/FeedImageLoaderTest.java",
-    "junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java",
-  ]
-  chrome_test_java_sources += feed_conformance_test_sources
+  chrome_junit_test_java_sources += feed_junit_test_java_sources
+  chrome_test_java_sources += feed_test_java_sources
 }
 
 # This is enable_arcore, not package_arcore because the apk merger, for
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java
new file mode 100644
index 0000000..4e016875
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java
@@ -0,0 +1,122 @@
+// 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.feed;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+
+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.ThreadUtils;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler;
+import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
+import org.chromium.components.background_task_scheduler.TaskIds;
+import org.chromium.components.background_task_scheduler.TaskInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link FeedSchedulerBridge}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class FeedRefreshTaskTest {
+    @Rule
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+
+    private static class TestBackgroundTaskScheduler implements BackgroundTaskScheduler {
+        private List<TaskInfo> mTaskInfoList = new ArrayList<>();
+        private List<Integer> mCanceledTaskIds = new ArrayList<>();
+
+        public List<TaskInfo> getTaskInfoList() {
+            return mTaskInfoList;
+        }
+
+        public List<Integer> getCanceledTaskIds() {
+            return mCanceledTaskIds;
+        }
+
+        @Override
+        public boolean schedule(Context context, TaskInfo taskInfo) {
+            mTaskInfoList.add(taskInfo);
+            return true;
+        }
+
+        @Override
+        public void cancel(Context context, int taskId) {
+            mCanceledTaskIds.add(taskId);
+        }
+
+        @Override
+        public void checkForOSUpgrade(Context context) {}
+
+        @Override
+        public void reschedule(Context context) {}
+    }
+
+    private TestBackgroundTaskScheduler mTaskScheduler;
+
+    @Before
+    public void setUp() throws InterruptedException {
+        mTaskScheduler = new TestBackgroundTaskScheduler();
+        BackgroundTaskSchedulerFactory.setSchedulerForTesting(mTaskScheduler);
+        mActivityTestRule.startMainActivityOnBlankPage();
+    }
+
+    @Test
+    @SmallTest
+    public void testSchedule() {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertEquals(0, mTaskScheduler.getTaskInfoList().size());
+            FeedRefreshTask.scheduleWakeUp(/*thresholdMs=*/1234);
+            Assert.assertEquals(1, mTaskScheduler.getTaskInfoList().size());
+            TaskInfo actualInfo = mTaskScheduler.getTaskInfoList().get(0);
+            Assert.assertEquals(TaskIds.FEED_REFRESH_JOB_ID, actualInfo.getTaskId());
+            Assert.assertEquals(TaskInfo.NETWORK_TYPE_ANY, actualInfo.getRequiredNetworkType());
+            Assert.assertEquals(false, actualInfo.requiresCharging());
+            Assert.assertEquals(true, actualInfo.isPeriodic());
+            Assert.assertEquals(true, actualInfo.isPersisted());
+            Assert.assertEquals(true, actualInfo.shouldUpdateCurrent());
+            // 1234 * 1.1 = 1357
+            Assert.assertEquals(1357, actualInfo.getPeriodicInfo().getIntervalMs());
+            // 1234 * 0.2 = 246
+            Assert.assertEquals(246, actualInfo.getPeriodicInfo().getFlexMs());
+        });
+    }
+
+    @Test
+    @SmallTest
+    public void testCancelWakeUp() {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertEquals(0, mTaskScheduler.getCanceledTaskIds().size());
+            FeedRefreshTask.cancelWakeUp();
+            Assert.assertEquals(1, mTaskScheduler.getCanceledTaskIds().size());
+        });
+    }
+
+    @Test
+    @SmallTest
+    public void testReschedule() {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // The FeedSchedulerHost might create a task during its initialization, so clear
+            // out anything before reschedule() is called.
+            FeedProcessScopeFactory.getFeedSchedulerBridge();
+            mTaskScheduler.getTaskInfoList().clear();
+            Assert.assertEquals(0, mTaskScheduler.getTaskInfoList().size());
+
+            new FeedRefreshTask().reschedule(mActivityTestRule.getActivity());
+            Assert.assertEquals(1, mTaskScheduler.getTaskInfoList().size());
+        });
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java
index e062b49..6e016d0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java
@@ -4,17 +4,14 @@
 
 package org.chromium.chrome.browser.feed;
 
+import static org.mockito.Mockito.mock;
+
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.UiThreadTestRule;
 
 import com.google.android.libraries.feed.api.requestmanager.RequestManager;
-import com.google.android.libraries.feed.common.Result;
-import com.google.android.libraries.feed.common.functional.Consumer;
-import com.google.android.libraries.feed.common.functional.Supplier;
+import com.google.android.libraries.feed.api.sessionmanager.SessionManager;
 import com.google.android.libraries.feed.testing.conformance.scheduler.SchedulerConformanceTest;
-import com.google.search.now.feed.client.StreamDataProto.StreamDataOperation;
-import com.google.search.now.feed.client.StreamDataProto.StreamToken;
-import com.google.search.now.wire.feed.FeedQueryProto.FeedQuery.RequestReason;
 
 import org.junit.After;
 import org.junit.Before;
@@ -60,20 +57,6 @@
                 }
             });
 
-    private final class NoOpRequestManager implements RequestManager {
-        @Override
-        public void loadMore(StreamToken streamToken,
-                             Consumer < Result < List<StreamDataOperation>>> consumer) {}
-        @Override
-        public void triggerRefresh(RequestReason reason,
-                                   Consumer < Result < List<StreamDataOperation>>> consumer) {}
-        @Override
-        public void triggerRefresh(RequestReason reason) {}
-        @Override
-        public void setDefaultTriggerRefreshConsumerSupplier(
-                Supplier < Consumer < Result<List<StreamDataOperation>>>> consumer) {}
-    }
-
     private boolean mUseRequestManager;
 
     public FeedSchedulerBridgeConformanceTest(boolean useRequestManager) {
@@ -85,7 +68,9 @@
         // The scheduler is declared and tested in SchedulerConformanceTest.
         scheduler = new FeedSchedulerBridge(Profile.getLastUsedProfile());
         if (mUseRequestManager) {
-            ((FeedSchedulerBridge) scheduler).setRequestManager(new NoOpRequestManager());
+            ((FeedSchedulerBridge) scheduler)
+                    .initializeFeedDependencies(
+                            mock(RequestManager.class), mock(SessionManager.class));
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
index b4c593d..f538904 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
@@ -156,14 +156,6 @@
             // Adding an observer should not lead to a callback.
             Assert.assertEquals(0, mObserver.getRevokedCallCount());
 
-            // First seed the account state (some native classes make the assumption that
-            // a notification that a token was revoked for a given account was preceded by a
-            // notifictation that that account was available).
-            mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT1);
-            mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT2);
-
-            Assert.assertEquals(2, mObserver.getAvailableCallCount());
-
             // An observer should be called with the correct account.
             mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT1);
             Assert.assertEquals(1, mObserver.getRevokedCallCount());
@@ -174,9 +166,8 @@
             mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT2);
             Assert.assertEquals(1, mObserver.getRevokedCallCount());
 
-            // No other observer interface method should have been called after the initial seeding
-            // of the accounts.
-            Assert.assertEquals(2, mObserver.getAvailableCallCount());
+            // No other observer interface method should ever have been called.
+            Assert.assertEquals(0, mObserver.getAvailableCallCount());
             Assert.assertEquals(0, mObserver.getLoadedCallCount());
         });
     }
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
index 361e627..9ec150a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
@@ -116,8 +116,8 @@
 
     private void checkSetTintWorksCorrectly(ImageViewTinterOwner view) {
         ImageView imageView = (ImageView) view;
-        int color =
-                ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.light_active_color);
+        int color = ApiCompatibilityUtils.getColor(
+                mContext.getResources(), R.color.default_icon_color_blue);
 
         Assert.assertNull(imageView.getColorFilter());
         if (imageView.getDrawable() == null) {
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
index b79beb5..9969ef43 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
@@ -26,6 +26,7 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -150,6 +151,7 @@
     @Test
     @SmallTest
     @Feature({"Sync"})
+    @DisabledTest
     public void testOpeningSettingsDoesntStartEngine() {
         mSyncTestRule.setUpTestAccountAndSignIn();
         mSyncTestRule.stopSync();
@@ -163,6 +165,7 @@
     @Test
     @SmallTest
     @Feature({"Sync"})
+    @DisabledTest
     public void testDefaultControlStatesWithSyncOffThenOn() {
         mSyncTestRule.setUpTestAccountAndSignIn();
         mSyncTestRule.stopSync();
@@ -514,6 +517,7 @@
     @Test
     @SmallTest
     @Feature({"Sync"})
+    @DisabledTest
     public void testPassphraseDialogDismissed() {
         final FakeProfileSyncService pss = overrideProfileSyncService();
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3b8ee38..0df2628 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2536,6 +2536,10 @@
      flag_descriptions::kContextualSuggestionsSlimPeekUIDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(
          contextual_suggestions::kContextualSuggestionsSlimPeekUI)},
+    {"contextual-suggestions-opt-out",
+     flag_descriptions::kContextualSuggestionsOptOutName,
+     flag_descriptions::kContextualSuggestionsOptOutDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(contextual_suggestions::kContextualSuggestionsOptOut)},
     {"enable-content-suggestions-new-favicon-server",
      flag_descriptions::kEnableContentSuggestionsNewFaviconServerName,
      flag_descriptions::kEnableContentSuggestionsNewFaviconServerDescription,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 84c0651..d007da9 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -50,6 +50,7 @@
     &contextual_suggestions::kContextualSuggestionsBottomSheet,
     &contextual_suggestions::kContextualSuggestionsButton,
     &contextual_suggestions::kContextualSuggestionsSlimPeekUI,
+    &contextual_suggestions::kContextualSuggestionsOptOut,
     &features::kClearOldBrowsingData,
     &features::kClipboardContentSetting,
     &features::kDownloadsForeground,
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
index 7a97e2d..dc3ea44 100644
--- a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
+++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
@@ -189,7 +189,7 @@
 
   RegisterSyntheticFieldTrials(result);
 
-  RunCallbackAndroid(j_callback, j_result);
+  RunObjectCallbackAndroid(j_callback, j_result);
 }
 
 void ContextualSuggestionsBridge::OnImageFetched(
@@ -199,7 +199,7 @@
   if (!image.IsEmpty())
     j_bitmap = gfx::ConvertToJavaBitmap(image.ToSkBitmap());
 
-  RunCallbackAndroid(j_callback, j_bitmap);
+  RunObjectCallbackAndroid(j_callback, j_bitmap);
 }
 
 }  // namespace contextual_suggestions
diff --git a/chrome/browser/android/download/service/download_background_task.cc b/chrome/browser/android/download/service/download_background_task.cc
index e46375c..86c394a 100644
--- a/chrome/browser/android/download/service/download_background_task.cc
+++ b/chrome/browser/android/download/service/download_background_task.cc
@@ -16,11 +16,6 @@
 namespace download {
 namespace android {
 
-void CallTaskFinishedCallback(const base::android::JavaRef<jobject>& j_callback,
-                              bool needs_reschedule) {
-  RunCallbackAndroid(j_callback, needs_reschedule);
-}
-
 // static
 void JNI_DownloadBackgroundTask_StartBackgroundTask(
     JNIEnv* env,
@@ -32,7 +27,7 @@
   DCHECK(profile);
 
   TaskFinishedCallback finish_callback =
-      base::BindOnce(&CallTaskFinishedCallback,
+      base::BindOnce(&base::android::RunBooleanCallbackAndroid,
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback));
 
   DownloadService* download_service =
diff --git a/chrome/browser/android/explore_sites/explore_sites_bridge.cc b/chrome/browser/android/explore_sites/explore_sites_bridge.cc
index 7d39ada..7b93624 100644
--- a/chrome/browser/android/explore_sites/explore_sites_bridge.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_bridge.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/android/explore_sites/explore_sites_bridge.h"
 
+#include <string>
+#include <utility>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
@@ -68,7 +71,7 @@
     }
   }
 
-  base::android::RunCallbackAndroid(j_callback_ref, j_result_ref);
+  base::android::RunObjectCallbackAndroid(j_callback_ref, j_result_ref);
 }
 
 void OnGetIconDone(std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher,
@@ -80,7 +83,7 @@
   if (!image.IsEmpty()) {
     j_bitmap = gfx::ConvertToJavaBitmap(image.ToSkBitmap());
   }
-  base::android::RunCallbackAndroid(j_callback_obj, j_bitmap);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_bitmap);
 
   // Delete |image_fetcher| when appropriate.
   base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
diff --git a/chrome/browser/android/feed/feed_image_loader_bridge.cc b/chrome/browser/android/feed/feed_image_loader_bridge.cc
index 75e050b..7aafff28 100644
--- a/chrome/browser/android/feed/feed_image_loader_bridge.cc
+++ b/chrome/browser/android/feed/feed_image_loader_bridge.cc
@@ -75,7 +75,7 @@
   if (!image.IsEmpty()) {
     j_bitmap = gfx::ConvertToJavaBitmap(image.ToSkBitmap());
   }
-  RunCallbackAndroid(callback, j_bitmap);
+  RunObjectCallbackAndroid(callback, j_bitmap);
 }
 
 }  // namespace feed
diff --git a/chrome/browser/android/feed/feed_image_loader_bridge.h b/chrome/browser/android/feed/feed_image_loader_bridge.h
index b843b45..9c14bbc 100644
--- a/chrome/browser/android/feed/feed_image_loader_bridge.h
+++ b/chrome/browser/android/feed/feed_image_loader_bridge.h
@@ -11,30 +11,28 @@
 
 namespace feed {
 
-using base::android::JavaParamRef;
-using base::android::ScopedJavaGlobalRef;
-
 class FeedImageManager;
 
 // Native counterpart of FeedImageLoaderBridge.java. Holds non-owning pointers
 // to native implementation, to which operations are delegated. Results are
 // passed back by a single argument callback so
-// base::android::RunCallbackAndroid() can be used. This bridge is instantiated,
-// owned, and destroyed from Java.
+// base::android::RunObjectCallbackAndroid() can be used. This bridge is
+// instantiated, owned, and destroyed from Java.
 class FeedImageLoaderBridge {
  public:
   explicit FeedImageLoaderBridge(FeedImageManager* feed_image_manager);
   ~FeedImageLoaderBridge();
 
-  void Destroy(JNIEnv* j_env, const JavaParamRef<jobject>& j_this);
+  void Destroy(JNIEnv* j_env,
+               const base::android::JavaParamRef<jobject>& j_this);
 
   void FetchImage(JNIEnv* j_env,
-                  const JavaParamRef<jobject>& j_this,
-                  const JavaParamRef<jobjectArray>& j_urls,
-                  const JavaParamRef<jobject>& j_callback);
+                  const base::android::JavaParamRef<jobject>& j_this,
+                  const base::android::JavaParamRef<jobjectArray>& j_urls,
+                  const base::android::JavaParamRef<jobject>& j_callback);
 
  private:
-  void OnImageFetched(ScopedJavaGlobalRef<jobject> callback,
+  void OnImageFetched(base::android::ScopedJavaGlobalRef<jobject> callback,
                       const gfx::Image& image);
 
   FeedImageManager* feed_image_manager_;
diff --git a/chrome/browser/android/feed/feed_network_bridge.cc b/chrome/browser/android/feed/feed_network_bridge.cc
index 61f6086..7c685e5 100644
--- a/chrome/browser/android/feed/feed_network_bridge.cc
+++ b/chrome/browser/android/feed/feed_network_bridge.cc
@@ -38,7 +38,7 @@
   ScopedJavaLocalRef<jobject> j_http_response =
       Java_FeedNetworkBridge_createHttpResponse(env, http_code,
                                                 j_response_bytes);
-  base::android::RunCallbackAndroid(j_callback, j_http_response);
+  base::android::RunObjectCallbackAndroid(j_callback, j_http_response);
 }
 
 }  // namespace
diff --git a/chrome/browser/android/feed/feed_network_bridge.h b/chrome/browser/android/feed/feed_network_bridge.h
index 44080b9..01b9ea2 100644
--- a/chrome/browser/android/feed/feed_network_bridge.h
+++ b/chrome/browser/android/feed/feed_network_bridge.h
@@ -16,8 +16,8 @@
 
 // Native counterpart of FeedNetworkBridge.java. Holds non-owning pointers to
 // native implementation, to which operations are delegated. Results are passed
-// back by a single argument callback so base::android::RunCallbackAndroid() can
-// be used. This bridge is instantiated, owned, and destroyed from Java.
+// back by a single argument callback so base::android::RunObjectCallbackAndroid
+// can be used. This bridge is instantiated, owned, and destroyed from Java.
 class FeedNetworkBridge {
  public:
   explicit FeedNetworkBridge(
diff --git a/chrome/browser/android/feed/feed_scheduler_bridge.cc b/chrome/browser/android/feed/feed_scheduler_bridge.cc
index 89ab0c671..69cfecd 100644
--- a/chrome/browser/android/feed/feed_scheduler_bridge.cc
+++ b/chrome/browser/android/feed/feed_scheduler_bridge.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/android/feed/feed_scheduler_bridge.h"
 
+#include <utility>
+
+#include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/bind.h"
 #include "base/time/time.h"
@@ -11,7 +14,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "components/feed/core/feed_host_service.h"
-#include "components/feed/core/feed_scheduler_host.h"
 #include "jni/FeedSchedulerBridge_jni.h"
 
 using base::android::JavaRef;
@@ -37,8 +39,11 @@
       scheduler_host_(scheduler_host),
       weak_factory_(this) {
   DCHECK(scheduler_host_);
-  scheduler_host_->RegisterTriggerRefreshCallback(base::BindRepeating(
-      &FeedSchedulerBridge::TriggerRefresh, weak_factory_.GetWeakPtr()));
+  scheduler_host_->Initialize(
+      base::BindRepeating(&FeedSchedulerBridge::TriggerRefresh,
+                          weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&FeedSchedulerBridge::ScheduleWakeUp,
+                          weak_factory_.GetWeakPtr()));
 }
 
 FeedSchedulerBridge::~FeedSchedulerBridge() {}
@@ -77,9 +82,20 @@
   scheduler_host_->OnForegrounded();
 }
 
-void FeedSchedulerBridge::OnFixedTimer(JNIEnv* env,
-                                       const JavaRef<jobject>& j_this) {
-  scheduler_host_->OnFixedTimer();
+void FeedSchedulerBridge::OnFixedTimer(
+    JNIEnv* env,
+    const JavaRef<jobject>& j_this,
+    const base::android::JavaRef<jobject>& j_callback) {
+  base::OnceClosure callback =
+      base::BindOnce(&base::android::RunObjectCallbackAndroid,
+                     ScopedJavaGlobalRef<jobject>(j_callback), nullptr);
+  scheduler_host_->OnFixedTimer(std::move(callback));
+}
+
+void FeedSchedulerBridge::OnTaskReschedule(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& j_this) {
+  scheduler_host_->OnTaskReschedule();
 }
 
 void FeedSchedulerBridge::TriggerRefresh() {
@@ -87,4 +103,15 @@
   Java_FeedSchedulerBridge_triggerRefresh(env, j_this_);
 }
 
+void FeedSchedulerBridge::ScheduleWakeUp(base::TimeDelta threshold) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_FeedSchedulerBridge_scheduleWakeUp(env, j_this_,
+                                          threshold.InMilliseconds());
+}
+
+void FeedSchedulerBridge::CancelWakeUp() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_FeedSchedulerBridge_cancelWakeUp(env, j_this_);
+}
+
 }  // namespace feed
diff --git a/chrome/browser/android/feed/feed_scheduler_bridge.h b/chrome/browser/android/feed/feed_scheduler_bridge.h
index 4465dee..29382c6 100644
--- a/chrome/browser/android/feed/feed_scheduler_bridge.h
+++ b/chrome/browser/android/feed/feed_scheduler_bridge.h
@@ -6,10 +6,16 @@
 #define CHROME_BROWSER_ANDROID_FEED_FEED_SCHEDULER_BRIDGE_H_
 
 #include <jni.h>
+#include <stdint.h>
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "components/feed/core/feed_scheduler_host.h"
+
+namespace base {
+class TimeDelta;
+}  // namespace base
 
 namespace feed {
 
@@ -43,13 +49,25 @@
   void OnForegrounded(JNIEnv* env,
                       const base::android::JavaRef<jobject>& j_this);
 
-  void OnFixedTimer(JNIEnv* env, const base::android::JavaRef<jobject>& j_this);
+  void OnFixedTimer(JNIEnv* env,
+                    const base::android::JavaRef<jobject>& j_this,
+                    const base::android::JavaRef<jobject>& j_callback);
 
+  void OnTaskReschedule(JNIEnv* env,
+                        const base::android::JavaRef<jobject>& j_this);
+
+ private:
   // Callable by native code to invoke Java code. Sends a request to the Feed
   // library to make the refresh call.
   void TriggerRefresh();
 
- private:
+  // Calls into Java logic to schedule a background task to wake up Chrome and
+  // call back into the FeedHostScheduler.
+  void ScheduleWakeUp(base::TimeDelta threshold_ms);
+
+  // Cancels previously scheduled background task.
+  void CancelWakeUp();
+
   // Reference to the Java half of this bridge. Always valid.
   base::android::ScopedJavaGlobalRef<jobject> j_this_;
 
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
index b2921e1..d83689e 100644
--- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc
+++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/android/ntp/ntp_snippets_bridge.h"
 
 #include <jni.h>
+#include <set>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -377,7 +379,7 @@
   if (!image.IsEmpty()) {
     j_bitmap = gfx::ConvertToJavaBitmap(image.ToSkBitmap());
   }
-  RunCallbackAndroid(callback, j_bitmap);
+  RunObjectCallbackAndroid(callback, j_bitmap);
 }
 
 void NTPSnippetsBridge::OnSuggestionsFetched(
@@ -389,14 +391,14 @@
   // TODO(fhorschig, dgn): Allow refetch or show notification acc. to status.
   JNIEnv* env = AttachCurrentThread();
   if (status.IsSuccess()) {
-    RunCallbackAndroid(
+    RunObjectCallbackAndroid(
         success_callback,
         JNI_SnippetsBridge_ToJavaSuggestionList(env, category, suggestions));
   } else {
     // The second parameter here means nothing - it was more convenient to pass
     // a Callback (which has 1 parameter) over to the native side than a
     // Runnable (which has no parameters). We ignore the parameter Java-side.
-    RunCallbackAndroid(failure_callback, 0);
+    RunIntCallbackAndroid(failure_callback, 0);
   }
 }
 
diff --git a/chrome/browser/android/password_ui_view_android.cc b/chrome/browser/android/password_ui_view_android.cc
index c0391a2..b4900f7 100644
--- a/chrome/browser/android/password_ui_view_android.cc
+++ b/chrome/browser/android/password_ui_view_android.cc
@@ -240,14 +240,12 @@
         *export_target_for_testing_ = serialization_result;
       } else {
         if (serialization_result.entries_count) {
-          base::android::RunCallbackAndroid(success_callback,
-                                            serialization_result.entries_count);
+          base::android::RunIntCallbackAndroid(
+              success_callback, serialization_result.entries_count);
         } else {
-          base::android::RunCallbackAndroid(
-              error_callback, base::android::ConvertUTF8ToJavaString(
-                                  base::android::AttachCurrentThread(),
-                                  logging::SystemErrorCodeToString(
-                                      serialization_result.error)));
+          base::android::RunStringCallbackAndroid(
+              error_callback,
+              logging::SystemErrorCodeToString(serialization_result.error));
         }
       }
       break;
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc
index 0cb277f4..7b661bbb 100644
--- a/chrome/browser/android/preferences/website_preference_bridge.cc
+++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -705,7 +705,7 @@
         env, list, host, static_cast<jint>(i->type), i->usage);
   }
 
-  base::android::RunCallbackAndroid(java_callback, list);
+  base::android::RunObjectCallbackAndroid(java_callback, list);
 }
 
 void OnLocalStorageCleared(const ScopedJavaGlobalRef<jobject>& java_callback) {
@@ -776,7 +776,7 @@
         env, map, origin, full_origin, info.size, important);
   }
 
-  base::android::RunCallbackAndroid(java_callback, map);
+  base::android::RunObjectCallbackAndroid(java_callback, map);
 }
 
 }  // anonymous namespace
diff --git a/chrome/browser/android/rlz/rlz_ping_handler.cc b/chrome/browser/android/rlz/rlz_ping_handler.cc
index e55fd0a..892679161 100644
--- a/chrome/browser/android/rlz/rlz_ping_handler.cc
+++ b/chrome/browser/android/rlz/rlz_ping_handler.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/android/rlz/rlz_ping_handler.h"
 
+#include <utility>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
@@ -55,7 +57,7 @@
     const base::android::JavaParamRef<jstring>& j_id,
     const base::android::JavaParamRef<jobject>& j_callback) {
   if (!j_brand || !j_language || !j_events || !j_id || !j_callback) {
-    base::android::RunCallbackAndroid(j_callback, false);
+    base::android::RunBooleanCallbackAndroid(j_callback, false);
     delete this;
     return;
   }
@@ -146,7 +148,7 @@
 
   // TODO(yusufo) : Investigate what else can be checked for validity that is
   // specific to the ping
-  base::android::RunCallbackAndroid(j_callback_, valid);
+  base::android::RunBooleanCallbackAndroid(j_callback_, valid);
   delete this;
 }
 
diff --git a/chrome/browser/android/rlz/rlz_ping_handler.h b/chrome/browser/android/rlz/rlz_ping_handler.h
index a58c815..ae9f12f 100644
--- a/chrome/browser/android/rlz/rlz_ping_handler.h
+++ b/chrome/browser/android/rlz/rlz_ping_handler.h
@@ -8,6 +8,7 @@
 #include <jni.h>
 #include <memory>
 #include <string>
+
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/ref_counted.h"
 
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index 92b751f..d3ff3cc 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <vector>
-
 #include "chrome/browser/android/signin/signin_manager_android.h"
 
+#include <utility>
+#include <vector>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
@@ -130,7 +131,7 @@
 void UserManagementDomainFetched(
     base::android::ScopedJavaGlobalRef<jobject> callback,
     const std::string& dm_token, const std::string& client_id) {
-  base::android::RunCallbackAndroid(callback, !dm_token.empty());
+  base::android::RunBooleanCallbackAndroid(callback, !dm_token.empty());
 }
 
 }  // namespace
diff --git a/chrome/browser/android/webapk/webapk_update_manager.cc b/chrome/browser/android/webapk/webapk_update_manager.cc
index 2aecc2c7..44d5293 100644
--- a/chrome/browser/android/webapk/webapk_update_manager.cc
+++ b/chrome/browser/android/webapk/webapk_update_manager.cc
@@ -31,12 +31,6 @@
 
 namespace {
 
-// Called after saving the update request proto either succeeds or fails.
-void OnStoredUpdateRequest(const JavaRef<jobject>& java_callback,
-                           bool success) {
-  base::android::RunCallbackAndroid(java_callback, success);
-}
-
 // Called after the update either succeeds or fails.
 void OnUpdated(const JavaRef<jobject>& java_callback,
                WebApkInstallResult result,
@@ -128,7 +122,7 @@
       base::FilePath(update_request_path), info, primary_icon, badge_icon,
       webapk_package, std::to_string(java_webapk_version),
       icon_url_to_murmur2_hash, java_is_manifest_stale, update_reason,
-      base::BindOnce(&OnStoredUpdateRequest,
+      base::BindOnce(&base::android::RunBooleanCallbackAndroid,
                      ScopedJavaGlobalRef<jobject>(java_callback)));
 }
 
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
index 508fbb1..8b889d4 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/observer_list.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/common/accessibility_helper.mojom.h"
@@ -28,7 +29,6 @@
 #include "ui/display/display.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/message_center/public/cpp/notification.h"
-#include "ui/views/test/views_test_base.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
@@ -47,7 +47,7 @@
 
 }  // namespace
 
-class ArcAccessibilityHelperBridgeTest : public views::ViewsTestBase {
+class ArcAccessibilityHelperBridgeTest : public ChromeViewsTestBase {
  public:
   class TestArcAccessibilityHelperBridge : public ArcAccessibilityHelperBridge {
    public:
@@ -117,7 +117,7 @@
   ArcAccessibilityHelperBridgeTest() = default;
 
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
+    ChromeViewsTestBase::SetUp();
 
     testing_profile_ = std::make_unique<TestingProfile>();
     bridge_service_ = std::make_unique<ArcBridgeService>();
@@ -135,7 +135,7 @@
     bridge_service_.reset();
     testing_profile_.reset();
 
-    views::ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
   TestArcAccessibilityHelperBridge* accessibility_helper_bridge() {
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
index 110ee7b..9f92722 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -234,7 +234,7 @@
 }
 
 void ArcInputMethodManagerService::RemoveArcIMEFromPrefs() {
-  RemoveArcIMEFromPref(prefs::kLanguageEnabledExtensionImes);
+  RemoveArcIMEFromPref(prefs::kLanguageEnabledImes);
   RemoveArcIMEFromPref(prefs::kLanguagePreloadEngines);
 
   PrefService* prefs = profile_->GetPrefs();
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 75c947e..b32e43e8 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
@@ -329,18 +329,15 @@
 
     // Emulate enabling ARC IME from chrome://settings.
     const std::string& arc_ime_id = std::get<1>(added_extensions[0])[0].id();
-    profile()->GetPrefs()->SetString(prefs::kLanguageEnabledExtensionImes,
-                                     arc_ime_id);
-    EXPECT_EQ(arc_ime_id, profile()->GetPrefs()->GetString(
-                              prefs::kLanguageEnabledExtensionImes));
+    profile()->GetPrefs()->SetString(prefs::kLanguageEnabledImes, arc_ime_id);
+    EXPECT_EQ(arc_ime_id,
+              profile()->GetPrefs()->GetString(prefs::kLanguageEnabledImes));
 
     // Removing the ARC IME should clear the pref
     std::vector<mojom::ImeInfoPtr> empty_info_array;
     service()->OnImeInfoChanged(std::move(empty_info_array));
-    EXPECT_TRUE(profile()
-                    ->GetPrefs()
-                    ->GetString(prefs::kLanguageEnabledExtensionImes)
-                    .empty());
+    EXPECT_TRUE(
+        profile()->GetPrefs()->GetString(prefs::kLanguageEnabledImes).empty());
     added_extensions.clear();
   }
 
diff --git a/chrome/browser/chromeos/drive/debug_info_collector.cc b/chrome/browser/chromeos/drive/debug_info_collector.cc
index 1ed296b..7b339ce 100644
--- a/chrome/browser/chromeos/drive/debug_info_collector.cc
+++ b/chrome/browser/chromeos/drive/debug_info_collector.cc
@@ -32,7 +32,7 @@
 void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback,
                                  std::unique_ptr<ResourceEntry> entry,
                                  FileError error) {
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
   if (error != FILE_ERROR_OK)
     entry.reset();
   callback.Run(error, std::move(entry));
@@ -43,7 +43,7 @@
     const DebugInfoCollector::ReadDirectoryCallback& callback,
     std::unique_ptr<ResourceEntryVector> entries,
     FileError error) {
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
   if (error != FILE_ERROR_OK)
     entries.reset();
   callback.Run(error, std::move(entries));
@@ -62,14 +62,13 @@
   DCHECK(file_system_);
 }
 
-DebugInfoCollector::~DebugInfoCollector() {
-}
+DebugInfoCollector::~DebugInfoCollector() = default;
 
 void DebugInfoCollector::GetResourceEntry(
     const base::FilePath& file_path,
     const GetResourceEntryCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!callback.is_null());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(callback);
 
   std::unique_ptr<ResourceEntry> entry(new ResourceEntry);
   ResourceEntry* entry_ptr = entry.get();
@@ -86,8 +85,8 @@
 void DebugInfoCollector::ReadDirectory(
     const base::FilePath& file_path,
     const ReadDirectoryCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!callback.is_null());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(callback);
 
   std::unique_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
   ResourceEntryVector* entries_ptr = entries.get();
@@ -104,9 +103,9 @@
 void DebugInfoCollector::IterateFileCache(
     const IterateFileCacheCallback& iteration_callback,
     const base::Closure& completion_callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!iteration_callback.is_null());
-  DCHECK(!completion_callback.is_null());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(iteration_callback);
+  DCHECK(completion_callback);
 
   blocking_task_runner_->PostTaskAndReply(
       FROM_HERE,
@@ -117,8 +116,8 @@
 
 void DebugInfoCollector::GetMetadata(
     const GetFilesystemMetadataCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!callback.is_null());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(callback);
 
   // Currently, this is just a proxy to the FileSystem.
   // TODO(hidehiko): Move the implementation to here to simplify the
diff --git a/chrome/browser/chromeos/drive/debug_info_collector.h b/chrome/browser/chromeos/drive/debug_info_collector.h
index 71cc78f..39f5fec 100644
--- a/chrome/browser/chromeos/drive/debug_info_collector.h
+++ b/chrome/browser/chromeos/drive/debug_info_collector.h
@@ -58,7 +58,7 @@
   FileSystemInterface* file_system_;  // Not owned.
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
-  base::ThreadChecker thread_checker_;
+  THREAD_CHECKER(thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(DebugInfoCollector);
 };
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc
index b4cae740..27a6f76 100644
--- a/chrome/browser/chromeos/drive/download_handler.cc
+++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -52,7 +52,7 @@
  public:
   explicit DriveUserData(const base::FilePath& path) : file_path_(path),
                                                        is_complete_(false) {}
-  ~DriveUserData() override {}
+  ~DriveUserData() override = default;
 
   const base::FilePath& file_path() const { return file_path_; }
   const base::FilePath& cache_file_path() const { return cache_file_path_; }
@@ -150,8 +150,7 @@
           base::TimeDelta::FromSeconds(kFreeDiskSpaceDelayInSeconds)),
       weak_ptr_factory_(this) {}
 
-DownloadHandler::~DownloadHandler() {
-}
+DownloadHandler::~DownloadHandler() = default;
 
 // static
 DownloadHandler* DownloadHandler::GetForProfile(Profile* profile) {
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
index 03986266..0b4c3ca1 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
@@ -107,12 +107,11 @@
   DCHECK(file_reader_);
 }
 
-LocalReaderProxy::~LocalReaderProxy() {
-}
+LocalReaderProxy::~LocalReaderProxy() = default;
 
 int LocalReaderProxy::Read(net::IOBuffer* buffer, int buffer_length,
                            const net::CompletionCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(file_reader_);
 
   if (buffer_length > remaining_length_) {
@@ -142,7 +141,7 @@
 
 void LocalReaderProxy::OnReadCompleted(const net::CompletionCallback& callback,
                                        int read_result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(file_reader_);
 
   if (read_result >= 0) {
@@ -175,7 +174,7 @@
 
 int NetworkReaderProxy::Read(net::IOBuffer* buffer, int buffer_length,
                              const net::CompletionCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // Check if there is no pending Read operation.
   DCHECK(!buffer_.get());
   DCHECK_EQ(buffer_length_, 0);
@@ -183,7 +182,7 @@
   // Validate the arguments.
   DCHECK(buffer);
   DCHECK_GT(buffer_length, 0);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   if (error_code_ != net::OK) {
     // An error is already found. Return it immediately.
@@ -222,7 +221,7 @@
 }
 
 void NetworkReaderProxy::OnGetContent(std::unique_ptr<std::string> data) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(data && !data->empty());
 
   if (remaining_offset_ >= static_cast<int64_t>(data->length())) {
@@ -257,7 +256,7 @@
 }
 
 void NetworkReaderProxy::OnCompleted(FileError error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // The downloading is completed, so we do not need to cancel the job
   // in the destructor.
   job_canceller_.Reset();
@@ -339,11 +338,10 @@
       weak_ptr_factory_(this) {
 }
 
-DriveFileStreamReader::~DriveFileStreamReader() {
-}
+DriveFileStreamReader::~DriveFileStreamReader() = default;
 
 bool DriveFileStreamReader::IsInitialized() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   return reader_proxy_.get() != nullptr;
 }
 
@@ -351,8 +349,8 @@
     const base::FilePath& drive_file_path,
     const net::HttpByteRange& byte_range,
     const InitializeCompletionCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!callback.is_null());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(callback);
 
   GetFileContent(
       file_system_getter_,
@@ -373,16 +371,16 @@
 
 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length,
                                 const net::CompletionCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(reader_proxy_);
   DCHECK(buffer);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
   return reader_proxy_->Read(buffer, buffer_length, callback);
 }
 
 void DriveFileStreamReader::StoreCancelDownloadClosure(
     const base::Closure& cancel_download_closure) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   cancel_download_closure_ = cancel_download_closure;
 }
 
@@ -392,7 +390,7 @@
     FileError error,
     const base::FilePath& local_cache_file_path,
     std::unique_ptr<ResourceEntry> entry) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // StoreCancelDownloadClosure() should be called before this function.
   DCHECK(!cancel_download_closure_.is_null());
 
@@ -447,7 +445,7 @@
     std::unique_ptr<ResourceEntry> entry,
     std::unique_ptr<util::LocalFileReader> file_reader,
     int open_result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (open_result != net::OK) {
     callback.Run(net::ERR_FAILED, std::unique_ptr<ResourceEntry>());
@@ -462,7 +460,7 @@
 void DriveFileStreamReader::OnGetContent(
     google_apis::DriveApiErrorCode error_code,
     std::unique_ptr<std::string> data) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(reader_proxy_);
   reader_proxy_->OnGetContent(std::move(data));
 }
@@ -470,7 +468,7 @@
 void DriveFileStreamReader::OnGetFileContentCompletion(
     const InitializeCompletionCallback& callback,
     FileError error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (reader_proxy_) {
     // If the proxy object available, send the error to it.
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader.h b/chrome/browser/chromeos/drive/drive_file_stream_reader.h
index ce7e13a..a107814b 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader.h
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader.h
@@ -81,7 +81,7 @@
   // The number of remaining bytes to be read.
   int64_t remaining_length_;
 
-  base::ThreadChecker thread_checker_;
+  THREAD_CHECKER(thread_checker_);
 
   // This should remain the last member so it'll be destroyed first and
   // invalidate its weak pointers before other members are destroyed.
@@ -131,7 +131,7 @@
   int buffer_length_;
   net::CompletionCallback callback_;
 
-  base::ThreadChecker thread_checker_;
+  THREAD_CHECKER(thread_checker_);
 
   // Keeps the closure to cancel downloading job if necessary.
   // Will be reset when the job is completed (regardless whether the job is
@@ -222,7 +222,7 @@
   base::Closure cancel_download_closure_;
   std::unique_ptr<internal::ReaderProxy> reader_proxy_;
 
-  base::ThreadChecker thread_checker_;
+  THREAD_CHECKER(thread_checker_);
 
   // This should remain the last member so it'll be destroyed first and
   // invalidate its weak pointers before other members are destroyed.
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 9a0ace36..dcdd01a6 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -553,7 +553,7 @@
 void DriveIntegrationService::ClearCacheAndRemountFileSystem(
     const base::Callback<void(bool)>& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   // TODO(crbug.com/845393): Implement for DriveFS.
   if (state_ != INITIALIZED || drivefs_holder_) {
@@ -589,7 +589,7 @@
     const base::Callback<void(bool)>& callback,
     FileError error) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   state_ = error == FILE_ERROR_OK ? INITIALIZED : NOT_INITIALIZED;
 
@@ -810,8 +810,7 @@
   DependsOn(DownloadCoreServiceFactory::GetInstance());
 }
 
-DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() {
-}
+DriveIntegrationServiceFactory::~DriveIntegrationServiceFactory() = default;
 
 content::BrowserContext* DriveIntegrationServiceFactory::GetBrowserContextToUse(
     content::BrowserContext* context) const {
diff --git a/chrome/browser/chromeos/drive/file_system_util.cc b/chrome/browser/chromeos/drive/file_system_util.cc
index aed7875..27e173f 100644
--- a/chrome/browser/chromeos/drive/file_system_util.cc
+++ b/chrome/browser/chromeos/drive/file_system_util.cc
@@ -190,7 +190,7 @@
                                const base::FilePath& path,
                                const PrepareWritableFileCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   FileSystemInterface* file_system = GetFileSystemByProfile(profile);
   if (!file_system || !IsUnderDriveMountPoint(path)) {
@@ -209,7 +209,7 @@
                            const base::FilePath& directory,
                            const FileOperationCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
   if (IsUnderDriveMountPoint(directory)) {
     FileSystemInterface* file_system = GetFileSystemByProfile(profile);
     DCHECK(file_system);
diff --git a/chrome/browser/chromeos/drive/file_task_executor.cc b/chrome/browser/chromeos/drive/file_task_executor.cc
index b0cad9e..dd9e581 100644
--- a/chrome/browser/chromeos/drive/file_task_executor.cc
+++ b/chrome/browser/chromeos/drive/file_task_executor.cc
@@ -74,8 +74,7 @@
       current_index_(0),
       weak_ptr_factory_(this) {}
 
-FileTaskExecutor::~FileTaskExecutor() {
-}
+FileTaskExecutor::~FileTaskExecutor() = default;
 
 void FileTaskExecutor::Execute(
     const std::vector<FileSystemURL>& file_urls,
diff --git a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
index 572b20a..ba904a59 100644
--- a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
+++ b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
@@ -110,11 +110,9 @@
 
 }  // namespace
 
-AsyncFileUtil::AsyncFileUtil() {
-}
+AsyncFileUtil::AsyncFileUtil() = default;
 
-AsyncFileUtil::~AsyncFileUtil() {
-}
+AsyncFileUtil::~AsyncFileUtil() = default;
 
 void AsyncFileUtil::CreateOrOpen(
     std::unique_ptr<storage::FileSystemOperationContext> context,
diff --git a/chrome/browser/chromeos/drive/fileapi/file_system_backend_delegate.cc b/chrome/browser/chromeos/drive/fileapi/file_system_backend_delegate.cc
index fd0339d..e1954149 100644
--- a/chrome/browser/chromeos/drive/fileapi/file_system_backend_delegate.cc
+++ b/chrome/browser/chromeos/drive/fileapi/file_system_backend_delegate.cc
@@ -75,8 +75,7 @@
     : async_file_util_(new internal::AsyncFileUtil) {
 }
 
-FileSystemBackendDelegate::~FileSystemBackendDelegate() {
-}
+FileSystemBackendDelegate::~FileSystemBackendDelegate() = default;
 
 storage::AsyncFileUtil* FileSystemBackendDelegate::GetAsyncFileUtil(
     storage::FileSystemType type) {
diff --git a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_reader_impl.cc b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_reader_impl.cc
index 76031bc..47954ea 100644
--- a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_reader_impl.cc
+++ b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_reader_impl.cc
@@ -36,8 +36,7 @@
   DCHECK_GE(offset, 0);
 }
 
-WebkitFileStreamReaderImpl::~WebkitFileStreamReaderImpl() {
-}
+WebkitFileStreamReaderImpl::~WebkitFileStreamReaderImpl() = default;
 
 int WebkitFileStreamReaderImpl::Read(net::IOBuffer* buffer,
                                      int buffer_length,
@@ -45,7 +44,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(stream_reader_);
   DCHECK(buffer);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   if (stream_reader_->IsInitialized())
     return stream_reader_->Read(buffer, buffer_length, callback);
@@ -68,7 +67,7 @@
     const net::Int64CompletionCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(stream_reader_);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   if (stream_reader_->IsInitialized()) {
     // Returns file_size regardless of |offset_|.
@@ -95,7 +94,7 @@
     std::unique_ptr<ResourceEntry> entry) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(stream_reader_);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   // TODO(hashimoto): Report ERR_UPLOAD_FILE_CHANGED when modification time
   // doesn't match. crbug.com/346625
@@ -117,7 +116,7 @@
     const net::CompletionCallback& callback,
     int initialization_result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   if (initialization_result != net::OK) {
     callback.Run(initialization_result);
@@ -134,7 +133,7 @@
     const net::Int64CompletionCallback& callback,
     int initialization_result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   if (initialization_result != net::OK) {
     callback.Run(initialization_result);
diff --git a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
index 878d3e5..06bb3e7 100644
--- a/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
+++ b/chrome/browser/chromeos/drive/fileapi/webkit_file_stream_writer_impl.cc
@@ -68,7 +68,7 @@
                                       const net::CompletionCallback& callback) {
   DCHECK(pending_write_callback_.is_null());
   DCHECK(pending_cancel_callback_.is_null());
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   // If the local file is already available, just delegate to it.
   if (local_file_writer_)
@@ -90,7 +90,7 @@
 int WebkitFileStreamWriterImpl::Cancel(
     const net::CompletionCallback& callback) {
   DCHECK(pending_cancel_callback_.is_null());
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   // If LocalFileWriter is already created, just delegate the cancel to it.
   if (local_file_writer_)
@@ -111,7 +111,7 @@
 
 int WebkitFileStreamWriterImpl::Flush(const net::CompletionCallback& callback) {
   DCHECK(pending_cancel_callback_.is_null());
-  DCHECK(!callback.is_null());
+  DCHECK(callback);
 
   // If LocalFileWriter is already created, just delegate to it.
   if (local_file_writer_)
diff --git a/chrome/browser/chromeos/drive/write_on_cache_file.cc b/chrome/browser/chromeos/drive/write_on_cache_file.cc
index 3de477a..91ba925c 100644
--- a/chrome/browser/chromeos/drive/write_on_cache_file.cc
+++ b/chrome/browser/chromeos/drive/write_on_cache_file.cc
@@ -22,7 +22,7 @@
                                   FileError error) {
   if (!close_callback.is_null())
     close_callback.Run();
-  DCHECK(!reply.is_null());
+  DCHECK(reply);
   reply.Run(error);
 }
 
@@ -61,8 +61,8 @@
                               const FileOperationCallback& reply) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(file_system);
-  DCHECK(!callback.is_null());
-  DCHECK(!reply.is_null());
+  DCHECK(callback);
+  DCHECK(reply);
 
   file_system->OpenFile(
       path,
diff --git a/chrome/browser/chromeos/input_method/input_method_syncer.cc b/chrome/browser/chromeos/input_method/input_method_syncer.cc
index ccc3049..987fd20 100644
--- a/chrome/browser/chromeos/input_method/input_method_syncer.cc
+++ b/chrome/browser/chromeos/input_method/input_method_syncer.cc
@@ -135,10 +135,8 @@
       prefs::kLanguagePreloadEnginesSyncable,
       "",
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-  registry->RegisterStringPref(
-      prefs::kLanguageEnabledExtensionImesSyncable,
-      "",
-      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+  registry->RegisterStringPref(prefs::kLanguageEnabledImesSyncable, "",
+                               user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
   registry->RegisterBooleanPref(prefs::kLanguageShouldMergeInputMethods, false);
 }
 
@@ -151,8 +149,7 @@
                                      prefs_);
   preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable,
                                  prefs_);
-  enabled_extension_imes_syncable_.Init(
-      prefs::kLanguageEnabledExtensionImesSyncable, prefs_);
+  enabled_imes_syncable_.Init(prefs::kLanguageEnabledImesSyncable, prefs_);
 
   BooleanPrefMember::NamedChangeCallback callback =
       base::Bind(&InputMethodSyncer::OnPreferenceChanged,
@@ -161,14 +158,13 @@
                             prefs_, callback);
   preload_engines_.Init(prefs::kLanguagePreloadEngines,
                         prefs_, callback);
-  enabled_extension_imes_.Init(
-      prefs::kLanguageEnabledExtensionImes, prefs_, callback);
+  enabled_imes_.Init(prefs::kLanguageEnabledImes, prefs_, callback);
 
   // If we have already synced but haven't merged input methods yet, do so now.
   if (prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods) &&
       !(preferred_languages_syncable_.GetValue().empty() &&
         preload_engines_syncable_.GetValue().empty() &&
-        enabled_extension_imes_syncable_.GetValue().empty())) {
+        enabled_imes_syncable_.GetValue().empty())) {
     MergeSyncedPrefs();
   }
 }
@@ -196,17 +192,15 @@
   MergeLists(&new_tokens, synced_tokens);
   preferred_languages_syncable_.SetValue(base::JoinString(new_tokens, ","));
 
-  std::string enabled_extension_imes_syncable =
-      enabled_extension_imes_syncable_.GetValue();
-  synced_tokens =
-      base::SplitStringPiece(enabled_extension_imes_syncable, ",",
-                             base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  std::string enabled_extension_imes = enabled_extension_imes_.GetValue();
-  new_tokens = base::SplitStringPiece(
-      enabled_extension_imes, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  std::string enabled_imes_syncable = enabled_imes_syncable_.GetValue();
+  synced_tokens = base::SplitStringPiece(
+      enabled_imes_syncable, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  std::string enabled_imes = enabled_imes_.GetValue();
+  new_tokens = base::SplitStringPiece(enabled_imes, ",", base::TRIM_WHITESPACE,
+                                      base::SPLIT_WANT_ALL);
 
   MergeLists(&new_tokens, synced_tokens);
-  enabled_extension_imes_syncable_.SetValue(base::JoinString(new_tokens, ","));
+  enabled_imes_syncable_.SetValue(base::JoinString(new_tokens, ","));
 
   // Revert preload engines to legacy component IDs.
   std::string preload_engines = preload_engines_.GetValue();
@@ -231,10 +225,9 @@
       AddSupportedInputMethodValues(preload_engines_.GetValue(),
                                     preload_engines_syncable,
                                     prefs::kLanguagePreloadEngines));
-  enabled_extension_imes_.SetValue(
-      AddSupportedInputMethodValues(enabled_extension_imes_.GetValue(),
-                                    enabled_extension_imes_syncable,
-                                    prefs::kLanguageEnabledExtensionImes));
+  enabled_imes_.SetValue(AddSupportedInputMethodValues(
+      enabled_imes_.GetValue(), enabled_imes_syncable,
+      prefs::kLanguageEnabledImes));
 
   // Remove unsupported locales before updating the local languages preference.
   std::string languages(
@@ -258,7 +251,7 @@
 
   // Check and convert the new tokens.
   if (pref_name == prefs::kLanguagePreloadEngines ||
-      pref_name == prefs::kLanguageEnabledExtensionImes) {
+      pref_name == prefs::kLanguageEnabledImes) {
     input_method::InputMethodManager* manager =
         input_method::InputMethodManager::Get();
     std::unique_ptr<input_method::InputMethodDescriptors> supported_descriptors;
@@ -305,7 +298,7 @@
 void InputMethodSyncer::OnPreferenceChanged(const std::string& pref_name) {
   DCHECK(pref_name == prefs::kLanguagePreferredLanguages ||
          pref_name == prefs::kLanguagePreloadEngines ||
-         pref_name == prefs::kLanguageEnabledExtensionImes);
+         pref_name == prefs::kLanguageEnabledImes);
 
   if (merging_ || prefs_->GetBoolean(prefs::kLanguageShouldMergeInputMethods))
     return;
@@ -313,7 +306,7 @@
   // Set the language and input prefs at the same time. Otherwise we may,
   // e.g., use a stale languages setting but push a new preload engines setting.
   preferred_languages_syncable_.SetValue(preferred_languages_.GetValue());
-  enabled_extension_imes_syncable_.SetValue(enabled_extension_imes_.GetValue());
+  enabled_imes_syncable_.SetValue(enabled_imes_.GetValue());
 
   // For preload engines, use legacy xkb IDs so the preference can sync
   // across Chrome OS and Chromium OS.
diff --git a/chrome/browser/chromeos/input_method/input_method_syncer.h b/chrome/browser/chromeos/input_method/input_method_syncer.h
index 0757b01b..f570d1c 100644
--- a/chrome/browser/chromeos/input_method/input_method_syncer.h
+++ b/chrome/browser/chromeos/input_method/input_method_syncer.h
@@ -70,14 +70,14 @@
 
   StringPrefMember preferred_languages_;
   StringPrefMember preload_engines_;
-  StringPrefMember enabled_extension_imes_;
+  StringPrefMember enabled_imes_;
   // These are syncable variants which don't change the device settings. We can
   // set these to keep track of the user's most recent choices. That way, after
   // the initial sync, we can add the user's synced choices to the values that
   // have already been chosen at OOBE.
   StringPrefMember preferred_languages_syncable_;
   StringPrefMember preload_engines_syncable_;
-  StringPrefMember enabled_extension_imes_syncable_;
+  StringPrefMember enabled_imes_syncable_;
 
   sync_preferences::PrefServiceSyncable* prefs_;
   scoped_refptr<input_method::InputMethodManager::State> ime_state_;
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 7a25af0..053e7f7 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -314,7 +314,7 @@
                                kFallbackInputMethodLocale);
   registry->RegisterStringPref(prefs::kLanguagePreloadEngines,
                                hardware_keyboard_id);
-  registry->RegisterStringPref(prefs::kLanguageEnabledExtensionImes, "");
+  registry->RegisterStringPref(prefs::kLanguageEnabledImes, "");
 
   registry->RegisterIntegerPref(
       prefs::kLanguageRemapSearchKeyTo,
@@ -502,8 +502,7 @@
   download_default_directory_.Init(prefs::kDownloadDefaultDirectory,
                                    prefs, callback);
   preload_engines_.Init(prefs::kLanguagePreloadEngines, prefs, callback);
-  enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes,
-                               prefs, callback);
+  enabled_imes_.Init(prefs::kLanguageEnabledImes, prefs, callback);
   current_input_method_.Init(prefs::kLanguageCurrentInputMethod,
                              prefs, callback);
   previous_input_method_.Init(prefs::kLanguagePreviousInputMethod,
@@ -784,9 +783,9 @@
   }
 
   if ((reason == REASON_INITIALIZATION) ||
-      (pref_name == prefs::kLanguageEnabledExtensionImes &&
+      (pref_name == prefs::kLanguageEnabledImes &&
        reason == REASON_PREF_CHANGED)) {
-    std::string value(enabled_extension_imes_.GetValue());
+    std::string value(enabled_imes_.GetValue());
 
     std::vector<std::string> split_values;
     if (!value.empty()) {
diff --git a/chrome/browser/chromeos/preferences.h b/chrome/browser/chromeos/preferences.h
index c394702..931d0d5 100644
--- a/chrome/browser/chromeos/preferences.h
+++ b/chrome/browser/chromeos/preferences.h
@@ -133,7 +133,7 @@
   StringPrefMember previous_input_method_;
 
   StringListPrefMember allowed_input_methods_;
-  StringPrefMember enabled_extension_imes_;
+  StringPrefMember enabled_imes_;
   BooleanPrefMember ime_menu_activated_;
 
   BooleanPrefMember xkb_auto_repeat_enabled_;
diff --git a/chrome/browser/chromeos/preferences_unittest.cc b/chrome/browser/chromeos/preferences_unittest.cc
index 5139b60..a0c61b2a 100644
--- a/chrome/browser/chromeos/preferences_unittest.cc
+++ b/chrome/browser/chromeos/preferences_unittest.cc
@@ -232,10 +232,9 @@
     preload_engines_.Init(prefs::kLanguagePreloadEngines, pref_service_);
     preload_engines_syncable_.Init(prefs::kLanguagePreloadEnginesSyncable,
                                    pref_service_);
-    enabled_extension_imes_.Init(prefs::kLanguageEnabledExtensionImes,
-                                 pref_service_);
-    enabled_extension_imes_syncable_.Init(
-        prefs::kLanguageEnabledExtensionImesSyncable, pref_service_);
+    enabled_imes_.Init(prefs::kLanguageEnabledImes, pref_service_);
+    enabled_imes_syncable_.Init(prefs::kLanguageEnabledImesSyncable,
+                                pref_service_);
 
     // Initialize component and 3rd-party input method extensions.
     InitComponentExtensionIMEManager();
@@ -295,38 +294,37 @@
   // Helper function to set local language and input values.
   void SetLocalValues(const std::string& preferred_languages,
                       const std::string& preload_engines,
-                      const std::string& enabled_extension_imes) {
+                      const std::string& enabled_imes) {
     preferred_languages_.SetValue(preferred_languages);
     preload_engines_.SetValue(preload_engines);
-    enabled_extension_imes_.SetValue(enabled_extension_imes);
+    enabled_imes_.SetValue(enabled_imes);
   }
 
   // Helper function to set global language and input values.
   void SetGlobalValues(const std::string& preferred_languages,
                        const std::string& preload_engines,
-                       const std::string& enabled_extension_imes) {
+                       const std::string& enabled_imes) {
     preferred_languages_syncable_.SetValue(preferred_languages);
     preload_engines_syncable_.SetValue(preload_engines);
-    enabled_extension_imes_syncable_.SetValue(enabled_extension_imes);
+    enabled_imes_syncable_.SetValue(enabled_imes);
   }
 
   // Helper function to check local language and input values.
   void ExpectLocalValues(const std::string& preferred_languages,
                          const std::string& preload_engines,
-                         const std::string& enabled_extension_imes) {
+                         const std::string& enabled_imes) {
     EXPECT_EQ(preferred_languages, preferred_languages_.GetValue());
     EXPECT_EQ(preload_engines, preload_engines_.GetValue());
-    EXPECT_EQ(enabled_extension_imes, enabled_extension_imes_.GetValue());
+    EXPECT_EQ(enabled_imes, enabled_imes_.GetValue());
   }
 
   // Helper function to check global language and input values.
   void ExpectGlobalValues(const std::string& preferred_languages,
                           const std::string& preload_engines,
-                          const std::string& enabled_extension_imes) {
+                          const std::string& enabled_imes) {
     EXPECT_EQ(preferred_languages, preferred_languages_syncable_.GetValue());
     EXPECT_EQ(preload_engines, preload_engines_syncable_.GetValue());
-    EXPECT_EQ(enabled_extension_imes,
-              enabled_extension_imes_syncable_.GetValue());
+    EXPECT_EQ(enabled_imes, enabled_imes_syncable_.GetValue());
   }
 
   // Translates engine IDs in a CSV string to input method IDs.
@@ -342,8 +340,8 @@
   StringPrefMember preferred_languages_syncable_;
   StringPrefMember preload_engines_;
   StringPrefMember preload_engines_syncable_;
-  StringPrefMember enabled_extension_imes_;
-  StringPrefMember enabled_extension_imes_syncable_;
+  StringPrefMember enabled_imes_;
+  StringPrefMember enabled_imes_syncable_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InputMethodPreferencesTest);
@@ -369,9 +367,8 @@
       prefs::kLanguagePreferredLanguagesSyncable, base::Value("ru,fi")));
   sync_data_list.push_back(CreatePrefSyncData(
       prefs::kLanguagePreloadEnginesSyncable, base::Value("xkb:se::swe")));
-  sync_data_list.push_back(
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(kIdentityIMEID)));
+  sync_data_list.push_back(CreatePrefSyncData(
+      prefs::kLanguageEnabledImesSyncable, base::Value(kIdentityIMEID)));
 
   // Sync for the first time.
   syncer::SyncableService* sync =
@@ -413,10 +410,10 @@
       FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
       CreatePrefSyncData(prefs::kLanguagePreloadEnginesSyncable,
                          base::Value(ToInputMethodIds("xkb:de::ger")))));
-  change_list.push_back(syncer::SyncChange(
-      FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(kToUpperIMEID))));
+  change_list.push_back(
+      syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
+                         CreatePrefSyncData(prefs::kLanguageEnabledImesSyncable,
+                                            base::Value(kToUpperIMEID))));
   sync->ProcessSyncChanges(FROM_HERE, change_list);
   content::RunAllTasksUntilIdle();
 
@@ -456,8 +453,8 @@
   sync_data_list.push_back(
       CreatePrefSyncData(prefs::kLanguagePreloadEngines,
                          base::Value(ToInputMethodIds("xkb:ru::rus"))));
-  sync_data_list.push_back(CreatePrefSyncData(
-      prefs::kLanguageEnabledExtensionImes, base::Value(kIdentityIMEID)));
+  sync_data_list.push_back(CreatePrefSyncData(prefs::kLanguageEnabledImes,
+                                              base::Value(kIdentityIMEID)));
 
   // Sync.
   syncer::SyncableService* sync =
@@ -496,9 +493,8 @@
   sync_data_list.push_back(
       CreatePrefSyncData(prefs::kLanguagePreloadEnginesSyncable,
                          base::Value(ToInputMethodIds("xkb:ru::rus"))));
-  sync_data_list.push_back(
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(kToUpperIMEID)));
+  sync_data_list.push_back(CreatePrefSyncData(
+      prefs::kLanguageEnabledImesSyncable, base::Value(kToUpperIMEID)));
 
   syncer::SyncableService* sync =
       pref_service_->GetSyncableService(
@@ -553,9 +549,8 @@
       prefs::kLanguagePreloadEnginesSyncable,
       base::Value(
           "nacl_mozc_us,xkb:ru::rus,xkb:ru::rus,xkb:es::spa,xkb:es::spa")));
-  sync_data_list.push_back(
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(std::string())));
+  sync_data_list.push_back(CreatePrefSyncData(
+      prefs::kLanguageEnabledImesSyncable, base::Value(std::string())));
 
   // Sync for the first time.
   syncer::SyncableService* sync =
@@ -604,9 +599,8 @@
                          base::Value("klingon,en-US")));
   sync_data_list.push_back(CreatePrefSyncData(
       prefs::kLanguagePreloadEnginesSyncable, base::Value(preload_engines)));
-  sync_data_list.push_back(
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(kUnknownIMEID)));
+  sync_data_list.push_back(CreatePrefSyncData(
+      prefs::kLanguageEnabledImesSyncable, base::Value(kUnknownIMEID)));
 
   // Sync for the first time.
   syncer::SyncableService* sync =
@@ -644,9 +638,8 @@
       prefs::kLanguagePreferredLanguagesSyncable, base::Value("en-US")));
   sync_data_list.push_back(CreatePrefSyncData(
       prefs::kLanguagePreloadEnginesSyncable, base::Value(preload_engines)));
-  sync_data_list.push_back(
-      CreatePrefSyncData(prefs::kLanguageEnabledExtensionImesSyncable,
-                         base::Value(kUnknownIMEID)));
+  sync_data_list.push_back(CreatePrefSyncData(
+      prefs::kLanguageEnabledImesSyncable, base::Value(kUnknownIMEID)));
 
   // Sync for the first time.
   syncer::SyncableService* sync =
diff --git a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
index 5498a19c..6e38db8f 100644
--- a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
+++ b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
@@ -134,9 +134,8 @@
 using DistillablePageUtilsBrowserTestAlways =
     DistillablePageUtilsBrowserTestOption<kAlwaysTrue>;
 
-// This test should be updated to use QuitClosure. See crbug.com/859151.
 IN_PROC_BROWSER_TEST_F(DistillablePageUtilsBrowserTestAlways,
-                       DISABLED_TestDelegate) {
+                       TestDelegate) {
   for (unsigned i = 0; i < sizeof(kAllPaths) / sizeof(kAllPaths[0]); ++i) {
     testing::InSequence dummy;
     EXPECT_CALL(holder_, OnResult(true, true, _))
diff --git a/chrome/browser/engagement/site_engagement_helper.cc b/chrome/browser/engagement/site_engagement_helper.cc
index a02482e..4e11f961 100644
--- a/chrome/browser/engagement/site_engagement_helper.cc
+++ b/chrome/browser/engagement/site_engagement_helper.cc
@@ -67,7 +67,7 @@
 
 SiteEngagementService::Helper::PeriodicTracker::PeriodicTracker(
     SiteEngagementService::Helper* helper)
-    : helper_(helper), pause_timer_(new base::Timer(true, false)) {}
+    : helper_(helper), pause_timer_(new base::OneShotTimer()) {}
 
 SiteEngagementService::Helper::PeriodicTracker::~PeriodicTracker() {}
 
@@ -92,7 +92,7 @@
 }
 
 void SiteEngagementService::Helper::PeriodicTracker::SetPauseTimerForTesting(
-    std::unique_ptr<base::Timer> timer) {
+    std::unique_ptr<base::OneShotTimer> timer) {
   pause_timer_ = std::move(timer);
 }
 
diff --git a/chrome/browser/engagement/site_engagement_helper.h b/chrome/browser/engagement/site_engagement_helper.h
index 26989252..6a7db7d 100644
--- a/chrome/browser/engagement/site_engagement_helper.h
+++ b/chrome/browser/engagement/site_engagement_helper.h
@@ -65,7 +65,7 @@
     bool IsTimerRunning();
 
     // Set the timer object for testing.
-    void SetPauseTimerForTesting(std::unique_ptr<base::Timer> timer);
+    void SetPauseTimerForTesting(std::unique_ptr<base::OneShotTimer> timer);
 
     SiteEngagementService::Helper* helper() { return helper_; }
 
@@ -84,7 +84,7 @@
 
    private:
     SiteEngagementService::Helper* helper_;
-    std::unique_ptr<base::Timer> pause_timer_;
+    std::unique_ptr<base::OneShotTimer> pause_timer_;
 
     DISALLOW_COPY_AND_ASSIGN(PeriodicTracker);
   };
diff --git a/chrome/browser/engagement/site_engagement_helper_unittest.cc b/chrome/browser/engagement/site_engagement_helper_unittest.cc
index 52b96f4..53f213c 100644
--- a/chrome/browser/engagement/site_engagement_helper_unittest.cc
+++ b/chrome/browser/engagement/site_engagement_helper_unittest.cc
@@ -78,13 +78,13 @@
 
   // Set a pause timer on the input tracker for test purposes.
   void SetInputTrackerPauseTimer(SiteEngagementService::Helper* helper,
-                                 std::unique_ptr<base::Timer> timer) {
+                                 std::unique_ptr<base::OneShotTimer> timer) {
     helper->input_tracker_.SetPauseTimerForTesting(std::move(timer));
   }
 
   // Set a pause timer on the input tracker for test purposes.
   void SetMediaTrackerPauseTimer(SiteEngagementService::Helper* helper,
-                                 std::unique_ptr<base::Timer> timer) {
+                                 std::unique_ptr<base::OneShotTimer> timer) {
     helper->media_tracker_.SetPauseTimerForTesting(std::move(timer));
   }
 
@@ -209,7 +209,7 @@
   GURL url2("http://www.google.com/");
   content::WebContents* contents = web_contents();
 
-  base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
+  base::MockOneShotTimer* media_tracker_timer = new base::MockOneShotTimer();
   SiteEngagementService::Helper* helper = GetHelper(contents);
   SetMediaTrackerPauseTimer(helper, base::WrapUnique(media_tracker_timer));
   SiteEngagementService* service = SiteEngagementService::Get(profile());
@@ -387,8 +387,8 @@
   GURL url2("http://www.google.com/");
   content::WebContents* contents = web_contents();
 
-  base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
-  base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
+  base::MockOneShotTimer* input_tracker_timer = new base::MockOneShotTimer;
+  base::MockOneShotTimer* media_tracker_timer = new base::MockOneShotTimer;
   SiteEngagementService::Helper* helper = GetHelper(contents);
   SetInputTrackerPauseTimer(helper, base::WrapUnique(input_tracker_timer));
   SetMediaTrackerPauseTimer(helper, base::WrapUnique(media_tracker_timer));
@@ -494,8 +494,8 @@
   GURL url2("http://www.google.com/");
   content::WebContents* contents = web_contents();
 
-  base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
-  base::MockTimer* media_tracker_timer = new base::MockTimer(true, false);
+  base::MockOneShotTimer* input_tracker_timer = new base::MockOneShotTimer();
+  base::MockOneShotTimer* media_tracker_timer = new base::MockOneShotTimer();
   SiteEngagementService::Helper* helper = GetHelper(contents);
   SetInputTrackerPauseTimer(helper, base::WrapUnique(input_tracker_timer));
   SetMediaTrackerPauseTimer(helper, base::WrapUnique(media_tracker_timer));
@@ -545,7 +545,7 @@
 // - Handles a hidden <-> occluded transition like a hidden <-> visible
 //   transition.
 TEST_F(SiteEngagementHelperTest, Occlusion) {
-  base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
+  base::MockOneShotTimer* input_tracker_timer = new base::MockOneShotTimer();
   SiteEngagementService::Helper* helper = GetHelper(web_contents());
   SetInputTrackerPauseTimer(helper, base::WrapUnique(input_tracker_timer));
 
@@ -595,7 +595,7 @@
   GURL url2("https://www.example.com/");
   content::WebContents* contents = web_contents();
 
-  base::MockTimer* input_tracker_timer = new base::MockTimer(true, false);
+  base::MockOneShotTimer* input_tracker_timer = new base::MockOneShotTimer();
   SiteEngagementService::Helper* helper = GetHelper(contents);
   SetInputTrackerPauseTimer(helper, base::WrapUnique(input_tracker_timer));
 
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index ddc74ff..e3a17ea 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -802,8 +802,10 @@
     "//chrome/app/theme:theme_resources",
     "//chrome/app/vector_icons",
     "//chrome/browser/devtools",
+    "//chrome/browser/engagement:mojo_bindings",
     "//chrome/browser/media/router",
     "//chrome/browser/media/router/discovery",
+    "//chrome/browser/resource_coordinator:mojo_bindings",
     "//chrome/browser/safe_browsing",
     "//chrome/common",
     "//chrome/common/extensions:mojo_bindings",
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
index dd2042b..1b291578 100644
--- a/chrome/browser/extensions/active_tab_permission_granter.cc
+++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -117,15 +117,20 @@
 
   const PermissionsData* permissions_data = extension->permissions_data();
 
-  // If the extension requested all-hosts but has had it withheld, we grant it
-  // active tab-style permissions, even if it doesn't have the activeTab
-  // permission in the manifest.
+  // TODO(devlin): This should be GetLastCommittedURL().
+  GURL url = web_contents()->GetVisibleURL();
+
+  // If the extension requested the host permission to |url| but had it
+  // withheld, we grant it active tab-style permissions, even if it doesn't have
+  // the activeTab permission in the manifest. This is necessary for the
+  // runtime host permissions feature to work.
   // Note: It's important that we check if the extension has activeTab before
   // checking ShouldGrantActiveTabOrPrompt() in order to prevent
   // ShouldGrantActiveTabOrPrompt() from prompting for extensions that don't
   // request the activeTab permission.
-  if ((permissions_data->HasWithheldImpliedAllHosts() ||
-       permissions_data->HasAPIPermission(APIPermission::kActiveTab)) &&
+  if ((permissions_data->HasAPIPermission(APIPermission::kActiveTab) ||
+       permissions_data->withheld_permissions().effective_hosts().MatchesURL(
+           url)) &&
       ShouldGrantActiveTabOrPrompt(extension, web_contents())) {
     // Gate activeTab for file urls on extensions having explicit access to file
     // urls.
@@ -134,8 +139,7 @@
                                web_contents()->GetBrowserContext())) {
       valid_schemes &= ~URLPattern::SCHEME_FILE;
     }
-    new_hosts.AddOrigin(valid_schemes,
-                        web_contents()->GetVisibleURL().GetOrigin());
+    new_hosts.AddOrigin(valid_schemes, url.GetOrigin());
     new_apis.insert(APIPermission::kTab);
   }
 
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index dc1b40d..665d030 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -444,7 +444,7 @@
               params->opt_args.additional_properties,
               &replace_selected_text_params));
       action->action = ax::mojom::Action::kReplaceSelectedText;
-      action->value = base::UTF8ToUTF16(replace_selected_text_params.value);
+      action->value = replace_selected_text_params.value;
       break;
     }
     case api::automation::ACTION_TYPE_SETVALUE: {
@@ -453,7 +453,7 @@
           api::automation_internal::SetValueParams::Populate(
               params->opt_args.additional_properties, &set_value_params));
       action->action = ax::mojom::Action::kSetValue;
-      action->value = base::UTF8ToUTF16(set_value_params.value);
+      action->value = set_value_params.value;
       break;
     }
     // These actions are currently unused by any existing clients of
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index f579a85..c03f35b 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -870,7 +870,7 @@
     ScriptingPermissionsModifier modifier(browser_context(), extension);
     if (!modifier.CanAffectExtension())
       return RespondNow(Error(kCannotChangeHostPermissions));
-    modifier.SetWithholdAllUrls(!(*update.run_on_all_urls));
+    modifier.SetWithholdHostPermissions(!(*update.run_on_all_urls));
   }
 
   return RespondNow(NoArguments());
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index 484ae6e..f020d18 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -85,7 +85,8 @@
 
 bool HasAllUrlsPermission(const Extension* extension,
                           content::BrowserContext* context) {
-  return !ScriptingPermissionsModifier(context, extension).HasWithheldAllUrls();
+  return !ScriptingPermissionsModifier(context, extension)
+              .HasWithheldHostPermissions();
 }
 
 bool HasPrefsPermission(bool (*has_pref)(const std::string&,
@@ -369,7 +370,7 @@
   const std::string& id = extension->id();
 
   ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension))
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
 
   TestExtensionPrefSetting(
       base::Bind(&HasPrefsPermission, &util::IsIncognitoEnabled, profile(), id),
@@ -1309,8 +1310,8 @@
       ExtensionBuilder("test").AddPermission("<all_urls>").Build();
   service()->AddExtension(extension.get());
   ScriptingPermissionsModifier modifier(profile(), extension.get());
-  EXPECT_FALSE(modifier.HasWithheldAllUrls());
-  modifier.SetWithholdAllUrls(true);
+  EXPECT_FALSE(modifier.HasWithheldHostPermissions());
+  modifier.SetWithholdHostPermissions(true);
 
   auto run_add_host_permission = [this, extension](base::StringPiece host,
                                                    bool should_succeed,
@@ -1354,8 +1355,8 @@
       ExtensionBuilder("test").AddPermission("<all_urls>").Build();
   service()->AddExtension(extension.get());
   ScriptingPermissionsModifier modifier(profile(), extension.get());
-  EXPECT_FALSE(modifier.HasWithheldAllUrls());
-  modifier.SetWithholdAllUrls(true);
+  EXPECT_FALSE(modifier.HasWithheldHostPermissions());
+  modifier.SetWithholdHostPermissions(true);
 
   auto run_remove_host_permission = [this, extension](
                                         base::StringPiece host,
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index a4a9769..eb7997f 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -534,8 +534,9 @@
   ScriptingPermissionsModifier permissions_modifier(
       browser_context_, base::WrapRefCounted(&extension));
   info->run_on_all_urls.is_enabled = permissions_modifier.CanAffectExtension();
-  info->run_on_all_urls.is_active = info->run_on_all_urls.is_enabled &&
-                                    !permissions_modifier.HasWithheldAllUrls();
+  info->run_on_all_urls.is_active =
+      info->run_on_all_urls.is_enabled &&
+      !permissions_modifier.HasWithheldHostPermissions();
 
   // Runtime warnings.
   std::vector<std::string> warnings =
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index 8921aaa..5aa2c93 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -412,7 +412,7 @@
   // Revoke the all urls permission.
   ScriptingPermissionsModifier permissions_modifier(profile(),
                                                     all_urls_extension);
-  permissions_modifier.SetWithholdAllUrls(true);
+  permissions_modifier.SetWithholdHostPermissions(true);
 
   // Now the extension want all urls, but not have it granted.
   info = GenerateExtensionInfo(all_urls_extension->id());
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 7a82ed16..22c00c0 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -134,11 +134,11 @@
 }
 
 // Sorts the third-party IMEs by the order of their associated languages.
-std::vector<std::string> GetSortedExtensionIMEs(
+std::vector<std::string> GetSortedThirdPartyIMEs(
     scoped_refptr<InputMethodManager::State> ime_state,
-    const std::unordered_set<std::string>& extension_ime_set,
+    const std::unordered_set<std::string>& third_party_ime_set,
     PrefService* prefs) {
-  std::vector<std::string> extension_ime_list;
+  std::vector<std::string> ime_list;
   std::string preferred_languages =
       prefs->GetString(prefs::kLanguagePreferredLanguages);
   std::vector<std::string> enabled_languages =
@@ -152,10 +152,10 @@
   InputMethodDescriptors descriptors;
   ime_state->GetInputMethodExtensions(&descriptors);
 
-  // Filter out the IMEs not in |extension_ime_set|.
+  // Filter out the IMEs not in |third_party_ime_set|.
   auto it = descriptors.begin();
   while (it != descriptors.end()) {
-    if (extension_ime_set.count(it->id()) == 0)
+    if (third_party_ime_set.count(it->id()) == 0)
       it = descriptors.erase(it);
     else
       it++;
@@ -165,9 +165,9 @@
   for (const auto& language : enabled_languages) {
     auto it = descriptors.begin();
     while (it != descriptors.end() && descriptors.size()) {
-      if (extension_ime_set.count(it->id()) &&
+      if (third_party_ime_set.count(it->id()) &&
           base::ContainsValue(it->language_codes(), language)) {
-        extension_ime_list.push_back(it->id());
+        ime_list.push_back(it->id());
         // Remove the added descriptor from the candidate list.
         it = descriptors.erase(it);
       } else {
@@ -176,7 +176,7 @@
     }
   }
 
-  return extension_ime_list;
+  return ime_list;
 }
 
 }  // namespace
@@ -635,7 +635,7 @@
   PrefService* prefs = chrome_details_.GetProfile()->GetPrefs();
   const char* pref_name = is_component_extension_ime
                               ? prefs::kLanguagePreloadEngines
-                              : prefs::kLanguageEnabledExtensionImes;
+                              : prefs::kLanguageEnabledImes;
 
   // Get the input methods we are adding to.
   std::unordered_set<std::string> input_method_set(
@@ -651,7 +651,7 @@
         GetSortedComponentIMEs(manager, ime_state, input_method_set, prefs);
   } else {
     input_method_list =
-        GetSortedExtensionIMEs(ime_state, input_method_set, prefs);
+        GetSortedThirdPartyIMEs(ime_state, input_method_set, prefs);
   }
 
   std::string input_methods = base::JoinString(input_method_list, ",");
@@ -690,7 +690,7 @@
   PrefService* prefs = chrome_details_.GetProfile()->GetPrefs();
   const char* pref_name = is_component_extension_ime
                               ? prefs::kLanguagePreloadEngines
-                              : prefs::kLanguageEnabledExtensionImes;
+                              : prefs::kLanguageEnabledImes;
 
   std::string input_method_ids = prefs->GetString(pref_name);
   std::vector<std::string> input_method_list = base::SplitString(
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
index c964b72a..e112824 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
@@ -236,26 +236,25 @@
 
   // Initialize relevant prefs.
   profile()->GetPrefs()->SetString(prefs::kLanguagePreferredLanguages, "en-US");
-  StringPrefMember enabled_extension_imes;
-  enabled_extension_imes.Init(prefs::kLanguageEnabledExtensionImes,
-                              profile()->GetPrefs());
+  StringPrefMember enabled_imes;
+  enabled_imes.Init(prefs::kLanguageEnabledImes, profile()->GetPrefs());
   StringPrefMember preload_engines;
   preload_engines.Init(prefs::kLanguagePreloadEngines, profile()->GetPrefs());
-  enabled_extension_imes.SetValue(std::string());
+  enabled_imes.SetValue(std::string());
   preload_engines.SetValue(std::string());
 
   {
-    // Add an extension IME. kLanguageEnabledExtensionImes should be updated.
+    // Add an extension IME. kLanguageEnabledImes should be updated.
     auto function =
         base::MakeRefCounted<LanguageSettingsPrivateAddInputMethodFunction>();
     api_test_utils::RunFunctionAndReturnSingleResult(
         function.get(), "[\"" + GetExtensionImeId() + "\"]", profile());
 
-    EXPECT_EQ(GetExtensionImeId(), enabled_extension_imes.GetValue());
+    EXPECT_EQ(GetExtensionImeId(), enabled_imes.GetValue());
     EXPECT_TRUE(preload_engines.GetValue().empty());
   }
 
-  enabled_extension_imes.SetValue(std::string());
+  enabled_imes.SetValue(std::string());
   preload_engines.SetValue(std::string());
   {
     // Add a component extension IME. kLanguagePreloadEngines should be
@@ -266,20 +265,20 @@
         function.get(), "[\"" + GetComponentExtensionImeId() + "\"]",
         profile());
 
-    EXPECT_TRUE(enabled_extension_imes.GetValue().empty());
+    EXPECT_TRUE(enabled_imes.GetValue().empty());
     EXPECT_EQ(GetComponentExtensionImeId(), preload_engines.GetValue());
   }
 
-  enabled_extension_imes.SetValue(std::string());
+  enabled_imes.SetValue(std::string());
   preload_engines.SetValue(std::string());
   {
-    // Add an ARC IME. kLanguageEnabledExtensionImes should be updated.
+    // Add an ARC IME. kLanguageEnabledImes should be updated.
     auto function =
         base::MakeRefCounted<LanguageSettingsPrivateAddInputMethodFunction>();
     api_test_utils::RunFunctionAndReturnSingleResult(
         function.get(), "[\"" + GetArcImeId() + "\"]", profile());
 
-    EXPECT_EQ(GetArcImeId(), enabled_extension_imes.GetValue());
+    EXPECT_EQ(GetArcImeId(), enabled_imes.GetValue());
     EXPECT_TRUE(preload_engines.GetValue().empty());
   }
 
@@ -290,13 +289,12 @@
   TestInputMethodManager::Initialize(new TestInputMethodManager);
 
   // Initialize relevant prefs.
-  StringPrefMember enabled_extension_imes;
-  enabled_extension_imes.Init(prefs::kLanguageEnabledExtensionImes,
-                              profile()->GetPrefs());
+  StringPrefMember enabled_imes;
+  enabled_imes.Init(prefs::kLanguageEnabledImes, profile()->GetPrefs());
   StringPrefMember preload_engines;
   preload_engines.Init(prefs::kLanguagePreloadEngines, profile()->GetPrefs());
 
-  enabled_extension_imes.SetValue(
+  enabled_imes.SetValue(
       base::JoinString({GetExtensionImeId(), GetArcImeId()}, ","));
   preload_engines.SetValue(GetComponentExtensionImeId());
   {
@@ -306,7 +304,7 @@
     api_test_utils::RunFunctionAndReturnSingleResult(
         function.get(), "[\"" + GetExtensionImeId() + "\"]", profile());
 
-    EXPECT_EQ(GetArcImeId(), enabled_extension_imes.GetValue());
+    EXPECT_EQ(GetArcImeId(), enabled_imes.GetValue());
     EXPECT_EQ(GetComponentExtensionImeId(), preload_engines.GetValue());
   }
 
@@ -318,7 +316,7 @@
         function.get(), "[\"" + GetComponentExtensionImeId() + "\"]",
         profile());
 
-    EXPECT_EQ(GetArcImeId(), enabled_extension_imes.GetValue());
+    EXPECT_EQ(GetArcImeId(), enabled_imes.GetValue());
     EXPECT_TRUE(preload_engines.GetValue().empty());
   }
 
@@ -329,7 +327,7 @@
     api_test_utils::RunFunctionAndReturnSingleResult(
         function.get(), "[\"" + GetArcImeId() + "\"]", profile());
 
-    EXPECT_TRUE(enabled_extension_imes.GetValue().empty());
+    EXPECT_TRUE(enabled_imes.GetValue().empty());
     EXPECT_TRUE(preload_engines.GetValue().empty());
   }
 
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 4598366..c8c6ac5 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -418,7 +418,7 @@
   // Input method settings.
   (*s_whitelist)[::prefs::kLanguagePreloadEngines] =
       settings_api::PrefType::PREF_TYPE_STRING;
-  (*s_whitelist)[::prefs::kLanguageEnabledExtensionImes] =
+  (*s_whitelist)[::prefs::kLanguageEnabledImes] =
       settings_api::PrefType::PREF_TYPE_STRING;
   (*s_whitelist)[::prefs::kLanguageAllowedInputMethods] =
       settings_api::PrefType::PREF_TYPE_LIST;
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 6648b8fd..0f9c6748 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -805,7 +805,7 @@
       LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab"));
   ASSERT_TRUE(extension) << message_;
   ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension))
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
   EXPECT_TRUE(listener.WaitUntilSatisfied());
 
   // Navigate the browser to a page in a new tab.
@@ -916,7 +916,7 @@
       LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab"));
   ASSERT_TRUE(extension) << message_;
   ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension))
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
   EXPECT_TRUE(listener.WaitUntilSatisfied());
 
   ui_test_utils::NavigateToURL(
@@ -1832,7 +1832,7 @@
       LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab"));
   ASSERT_TRUE(extension) << message_;
   ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension))
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
   EXPECT_TRUE(listener.WaitUntilSatisfied());
 
   // Navigate the browser to a page in a new tab.
diff --git a/chrome/browser/extensions/extension_action_runner_browsertest.cc b/chrome/browser/extensions/extension_action_runner_browsertest.cc
index d64443c9..76631c8 100644
--- a/chrome/browser/extensions/extension_action_runner_browsertest.cc
+++ b/chrome/browser/extensions/extension_action_runner_browsertest.cc
@@ -173,7 +173,7 @@
     ScriptingPermissionsModifier modifier(profile(), extension);
     if (withhold_permissions == WITHHOLD_PERMISSIONS &&
         modifier.CanAffectExtension()) {
-      modifier.SetWithholdAllUrls(true);
+      modifier.SetWithholdHostPermissions(true);
     }
   }
 
@@ -318,13 +318,12 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionActionRunnerBrowserTest,
                        ActiveScriptsAreDisplayedAndDelayExecution) {
-  // First, we load up three extensions:
+  // First, we load up four extensions:
   // - An extension that injects scripts into all hosts,
   // - An extension that injects scripts into explicit hosts,
   // - An extension with a content script that runs on all hosts,
   // - An extension with a content script that runs on explicit hosts.
-  // The extensions that operate on explicit hosts have permission; the ones
-  // that request all hosts require user consent.
+  // All extensions should require user consent.
   std::vector<std::unique_ptr<ActiveScriptTester>> testers;
   testers.push_back(std::make_unique<ActiveScriptTester>(
       "inject_scripts_all_hosts",
@@ -333,7 +332,7 @@
   testers.push_back(std::make_unique<ActiveScriptTester>(
       "inject_scripts_explicit_hosts",
       CreateExtension(EXPLICIT_HOSTS, EXECUTE_SCRIPT, WITHHOLD_PERMISSIONS),
-      browser(), DOES_NOT_REQUIRE_CONSENT, EXECUTE_SCRIPT));
+      browser(), REQUIRES_CONSENT, EXECUTE_SCRIPT));
   testers.push_back(std::make_unique<ActiveScriptTester>(
       "content_scripts_all_hosts",
       CreateExtension(ALL_HOSTS, CONTENT_SCRIPT, WITHHOLD_PERMISSIONS),
@@ -341,7 +340,7 @@
   testers.push_back(std::make_unique<ActiveScriptTester>(
       "content_scripts_explicit_hosts",
       CreateExtension(EXPLICIT_HOSTS, CONTENT_SCRIPT, WITHHOLD_PERMISSIONS),
-      browser(), DOES_NOT_REQUIRE_CONSENT, CONTENT_SCRIPT));
+      browser(), REQUIRES_CONSENT, CONTENT_SCRIPT));
 
   // Navigate to an URL (which matches the explicit host specified in the
   // extension content_scripts_explicit_hosts). All four extensions should
@@ -435,7 +434,7 @@
 
   // Enable the extension to run on all urls.
   ScriptingPermissionsModifier modifier(profile(), extension);
-  modifier.SetWithholdAllUrls(false);
+  modifier.SetWithholdHostPermissions(false);
   EXPECT_TRUE(RunAllPendingInRenderer(web_contents));
 
   // Navigate again - this time, the extension should execute immediately (and
@@ -447,7 +446,7 @@
 
   // Revoke all urls permissions.
   inject_success_listener.Reset();
-  modifier.SetWithholdAllUrls(true);
+  modifier.SetWithholdHostPermissions(true);
   EXPECT_TRUE(RunAllPendingInRenderer(web_contents));
 
   // Re-navigate; the extension should again need permission to run.
@@ -466,7 +465,8 @@
   const Extension* extension = LoadExtension(
       test_data_dir_.AppendASCII("blocked_actions/content_scripts"));
   ASSERT_TRUE(extension);
-  ScriptingPermissionsModifier(profile(), extension).SetWithholdAllUrls(true);
+  ScriptingPermissionsModifier(profile(), extension)
+      .SetWithholdHostPermissions(true);
 
   ui_test_utils::NavigateToURL(browser(), url);
   content::WebContents* web_contents =
diff --git a/chrome/browser/extensions/extension_action_runner_unittest.cc b/chrome/browser/extensions/extension_action_runner_unittest.cc
index 285ef3ff..83e62d55 100644
--- a/chrome/browser/extensions/extension_action_runner_unittest.cc
+++ b/chrome/browser/extensions/extension_action_runner_unittest.cc
@@ -118,7 +118,7 @@
   PermissionsUpdater(profile()).InitializePermissions(extension_.get());
 
   ScriptingPermissionsModifier(profile(), extension_.get())
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
   return extension_.get();
 }
 
@@ -354,7 +354,7 @@
 
   // Enable the extension on all urls.
   ScriptingPermissionsModifier permissions_modifier(profile(), extension);
-  permissions_modifier.SetWithholdAllUrls(false);
+  permissions_modifier.SetWithholdHostPermissions(false);
 
   EXPECT_FALSE(RequiresUserConsent(extension));
   // This should carry across navigations, and websites.
@@ -362,7 +362,7 @@
   EXPECT_FALSE(RequiresUserConsent(extension));
 
   // Turning off the preference should have instant effect.
-  permissions_modifier.SetWithholdAllUrls(true);
+  permissions_modifier.SetWithholdHostPermissions(true);
   EXPECT_TRUE(RequiresUserConsent(extension));
 
   // And should also persist across navigations and websites.
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc
index 51474cd..d88b75a 100644
--- a/chrome/browser/extensions/extension_context_menu_model.cc
+++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -374,7 +374,7 @@
     content::WebContents* web_contents) const {
   ScriptingPermissionsModifier modifier(profile_, extension);
   DCHECK(modifier.CanAffectExtension());
-  if (!modifier.HasWithheldAllUrls())
+  if (!modifier.HasWithheldHostPermissions())
     return PAGE_ACCESS_RUN_ON_ALL_SITES;
   if (modifier.HasGrantedHostPermission(
           GetActiveWebContents()->GetLastCommittedURL()))
@@ -394,6 +394,8 @@
   page_access_submenu_->AddRadioItemWithStringId(
       PAGE_ACCESS_RUN_ON_CLICK,
       IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_CLICK, kRadioGroup);
+  // TODO(https://crbug.com/857235): We should update these options based on
+  // the withheld permissions for the extension.
   page_access_submenu_->AddRadioItemWithStringId(
       PAGE_ACCESS_RUN_ON_ALL_SITES,
       IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_ALL_SITES, kRadioGroup);
@@ -428,18 +430,18 @@
   switch (command_id) {
     case PAGE_ACCESS_RUN_ON_CLICK:
       if (current_access == PAGE_ACCESS_RUN_ON_ALL_SITES)
-        modifier.SetWithholdAllUrls(true);
+        modifier.SetWithholdHostPermissions(true);
       if (modifier.HasGrantedHostPermission(url))
         modifier.RemoveGrantedHostPermission(url);
       break;
     case PAGE_ACCESS_RUN_ON_SITE:
       if (current_access == PAGE_ACCESS_RUN_ON_ALL_SITES)
-        modifier.SetWithholdAllUrls(true);
+        modifier.SetWithholdHostPermissions(true);
       if (!modifier.HasGrantedHostPermission(url))
         modifier.GrantHostPermission(url);
       break;
     case PAGE_ACCESS_RUN_ON_ALL_SITES:
-      modifier.SetWithholdAllUrls(false);
+      modifier.SetWithholdHostPermissions(false);
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
index e79c2786..731c6dae 100644
--- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc
+++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -623,7 +623,8 @@
   const Extension* extension =
       AddExtensionWithHostPermission("extension", manifest_keys::kBrowserAction,
                                      Manifest::INTERNAL, "*://*/*");
-  ScriptingPermissionsModifier(profile(), extension).SetWithholdAllUrls(true);
+  ScriptingPermissionsModifier(profile(), extension)
+      .SetWithholdHostPermissions(true);
   EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
 
   const GURL kActiveUrl("http://www.example.com/");
@@ -755,16 +756,15 @@
   EXPECT_EQ(2, run_count);
   EXPECT_TRUE(action_runner->WantsToRun(extension));
 
-  // Install an extension requesting only a single host. Since the extension
-  // doesn't request all hosts, it shouldn't have withheld permissions, and
-  // thus shouldn't have the page access submenu.
+  // Install an extension requesting a single host. The page access submenu
+  // should still be present.
   const Extension* single_host_extension = AddExtensionWithHostPermission(
       "single_host_extension", manifest_keys::kBrowserAction,
       Manifest::INTERNAL, "http://www.google.com/*");
   ExtensionContextMenuModel single_host_menu(
       single_host_extension, GetBrowser(), ExtensionContextMenuModel::VISIBLE,
       nullptr);
-  EXPECT_EQ(-1, single_host_menu.GetIndexOfCommandId(
+  EXPECT_NE(-1, single_host_menu.GetIndexOfCommandId(
                     ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU));
 
   // Disable the click-to-script feature, and install a new extension requiring
diff --git a/chrome/browser/extensions/forced_extensions/installation_tracker.cc b/chrome/browser/extensions/forced_extensions/installation_tracker.cc
index 9ec3545..80db14f 100644
--- a/chrome/browser/extensions/forced_extensions/installation_tracker.cc
+++ b/chrome/browser/extensions/forced_extensions/installation_tracker.cc
@@ -19,9 +19,10 @@
 
 namespace extensions {
 
-InstallationTracker::InstallationTracker(ExtensionRegistry* registry,
-                                         PrefService* pref_service,
-                                         std::unique_ptr<base::Timer> timer)
+InstallationTracker::InstallationTracker(
+    ExtensionRegistry* registry,
+    PrefService* pref_service,
+    std::unique_ptr<base::OneShotTimer> timer)
     : registry_(registry),
       pref_service_(pref_service),
       start_time_(base::Time::Now()),
diff --git a/chrome/browser/extensions/forced_extensions/installation_tracker.h b/chrome/browser/extensions/forced_extensions/installation_tracker.h
index 89fdc46..37a1d1ba 100644
--- a/chrome/browser/extensions/forced_extensions/installation_tracker.h
+++ b/chrome/browser/extensions/forced_extensions/installation_tracker.h
@@ -32,7 +32,7 @@
  public:
   InstallationTracker(ExtensionRegistry* registry,
                       PrefService* pref_service,
-                      std::unique_ptr<base::Timer> timer =
+                      std::unique_ptr<base::OneShotTimer> timer =
                           std::make_unique<base::OneShotTimer>());
 
   ~InstallationTracker() override;
@@ -70,7 +70,7 @@
   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> observer_;
 
   // Tracks installation reporting timeout.
-  std::unique_ptr<base::Timer> timer_;
+  std::unique_ptr<base::OneShotTimer> timer_;
 
   DISALLOW_COPY_AND_ASSIGN(InstallationTracker);
 };
diff --git a/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc b/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
index 04bc7f9..2094b6d 100644
--- a/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
+++ b/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
@@ -36,7 +36,7 @@
   ForcedExtensionsInstallationTrackerTest()
       : prefs_(profile_.GetTestingPrefService()),
         registry_(ExtensionRegistry::Get(&profile_)) {
-    auto fake_timer = std::make_unique<base::MockTimer>(true, false);
+    auto fake_timer = std::make_unique<base::MockOneShotTimer>();
     fake_timer_ = fake_timer.get();
     tracker_ = std::make_unique<InstallationTracker>(registry_, prefs_,
                                                      std::move(fake_timer));
@@ -57,7 +57,7 @@
   ExtensionRegistry* registry_;
   base::HistogramTester histogram_tester_;
 
-  base::MockTimer* fake_timer_;
+  base::MockOneShotTimer* fake_timer_;
   std::unique_ptr<InstallationTracker> tracker_;
 
   DISALLOW_COPY_AND_ASSIGN(ForcedExtensionsInstallationTrackerTest);
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index 77c6810..e725c11 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -268,14 +268,6 @@
                                            URLPatternSet(), URLPatternSet());
   };
 
-  auto url_permission_set = [](const GURL& url) {
-    URLPatternSet set;
-    URLPattern pattern(URLPattern::SCHEME_ALL, url.spec());
-    set.AddPattern(pattern);
-    return std::make_unique<PermissionSet>(
-        APIPermissionSet(), ManifestPermissionSet(), set, URLPatternSet());
-  };
-
   auto can_access_page =
       [](scoped_refptr<const extensions::Extension> extension,
          const GURL& document_url) -> bool {
@@ -340,65 +332,6 @@
   }
 
   {
-    // Test revoking non-optional host permissions with click-to-script.
-    base::test::ScopedFeatureList scoped_feature_list;
-    scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
-    ListBuilder optional_permissions;
-    optional_permissions.Append("tabs");
-    ListBuilder required_permissions;
-    required_permissions.Append("topSites")
-        .Append("http://*/*")
-        .Append("http://*.google.com/*");
-    scoped_refptr<const Extension> extension =
-        CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
-                                               required_permissions.Build(),
-                                               "My Extension");
-    PermissionsUpdater updater(profile());
-    updater.InitializePermissions(extension.get());
-
-    ScriptingPermissionsModifier(profile(), extension).SetWithholdAllUrls(true);
-
-    // All-hosts was withheld, so the extension shouldn't have access to any
-    // site (like foo.com).
-    const GURL kOrigin("http://foo.com");
-
-    EXPECT_FALSE(extension->permissions_data()
-                     ->active_permissions()
-                     .HasExplicitAccessToOrigin(kOrigin));
-    EXPECT_TRUE(extension->permissions_data()
-                    ->withheld_permissions()
-                    .HasExplicitAccessToOrigin(kOrigin));
-
-    const GURL kRequiredOrigin("http://www.google.com/");
-    EXPECT_TRUE(extension->permissions_data()
-                    ->active_permissions()
-                    .HasExplicitAccessToOrigin(kRequiredOrigin));
-    EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
-                     ->HasExplicitAccessToOrigin(kRequiredOrigin));
-
-    // Give the extension access to foo.com. Now, the foo.com permission should
-    // be revokable.
-    updater.AddPermissions(extension.get(), *url_permission_set(kOrigin));
-    EXPECT_TRUE(extension->permissions_data()
-                    ->active_permissions()
-                    .HasExplicitAccessToOrigin(kOrigin));
-    EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
-                    ->HasExplicitAccessToOrigin(kOrigin));
-
-    // Revoke the foo.com permission. The extension should no longer have
-    // access to foo.com, and the revokable permissions should be empty.
-    updater.RemovePermissions(extension.get(), *url_permission_set(kOrigin),
-                              PermissionsUpdater::REMOVE_HARD);
-    EXPECT_FALSE(extension->permissions_data()
-                     ->active_permissions()
-                     .HasExplicitAccessToOrigin(kOrigin));
-    EXPECT_TRUE(extension->permissions_data()
-                    ->withheld_permissions()
-                    .HasExplicitAccessToOrigin(kOrigin));
-    EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
-  }
-
-  {
     // Make sure policy restriction updates update permission data.
     URLPatternSet default_policy_blocked_hosts;
     URLPatternSet default_policy_allowed_hosts;
@@ -571,4 +504,166 @@
   EXPECT_TRUE(prefs->GetRuntimeGrantedPermissions(extension->id())->IsEmpty());
 }
 
+TEST_F(PermissionsUpdaterTest, RevokingPermissionsWithRuntimeHostPermissions) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
+
+  InitializeEmptyExtensionService();
+
+  constexpr struct {
+    const char* permission;
+    const char* test_url;
+  } test_cases[] = {
+      {"http://*/*", "http://foo.com"},
+      {"http://google.com/*", "http://google.com"},
+  };
+
+  for (const auto& test_case : test_cases) {
+    std::string test_name =
+        base::StringPrintf("%s, %s", test_case.permission, test_case.test_url);
+    SCOPED_TRACE(test_name);
+    scoped_refptr<const Extension> extension =
+        CreateExtensionWithOptionalPermissions(
+            std::make_unique<base::ListValue>(),
+            ListBuilder().Append(test_case.permission).Build(), test_name);
+    PermissionsUpdater updater(profile());
+    updater.InitializePermissions(extension.get());
+
+    ScriptingPermissionsModifier(profile(), extension)
+        .SetWithholdHostPermissions(true);
+
+    // Host access was withheld, so the extension shouldn't have access to the
+    // test site.
+    const GURL kOrigin(test_case.test_url);
+
+    EXPECT_FALSE(extension->permissions_data()
+                     ->active_permissions()
+                     .HasExplicitAccessToOrigin(kOrigin));
+    EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
+    EXPECT_TRUE(extension->permissions_data()
+                    ->withheld_permissions()
+                    .HasExplicitAccessToOrigin(kOrigin));
+
+    URLPatternSet url_pattern_set;
+    url_pattern_set.AddOrigin(URLPattern::SCHEME_ALL, kOrigin);
+    const PermissionSet permission_set(APIPermissionSet(),
+                                       ManifestPermissionSet(), url_pattern_set,
+                                       URLPatternSet());
+    // Give the extension access to the test site. Now, the test site permission
+    // should be revokable.
+    updater.AddPermissions(extension.get(), permission_set);
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .HasExplicitAccessToOrigin(kOrigin));
+    EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
+                    ->HasExplicitAccessToOrigin(kOrigin));
+
+    // Revoke the test site permission. The extension should no longer have
+    // access to test site, and the revokable permissions should be empty.
+    updater.RemovePermissions(extension.get(), permission_set,
+                              PermissionsUpdater::REMOVE_HARD);
+    EXPECT_FALSE(extension->permissions_data()
+                     ->active_permissions()
+                     .HasExplicitAccessToOrigin(kOrigin));
+    EXPECT_TRUE(extension->permissions_data()
+                    ->withheld_permissions()
+                    .HasExplicitAccessToOrigin(kOrigin));
+    EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
+  }
+}
+
+TEST_F(PermissionsUpdaterTest, ChromeFaviconIsNotARevokableHost) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
+
+  InitializeEmptyExtensionService();
+
+  URLPattern chrome_favicon_pattern(Extension::kValidHostPermissionSchemes,
+                                    "chrome://favicon/");
+
+  {
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("favicon extension")
+            .AddPermissions({"https://example.com/*", "chrome://favicon/*"})
+            .Build();
+    URLPattern example_com_pattern(Extension::kValidHostPermissionSchemes,
+                                   "https://example.com/*");
+    PermissionsUpdater updater(profile());
+    updater.InitializePermissions(extension.get());
+
+    // To start, the extension should have both example.com and chrome://favicon
+    // permissions.
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(chrome_favicon_pattern));
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(example_com_pattern));
+
+    // Only example.com should be revokable - chrome://favicon is not a real
+    // host permission.
+    std::unique_ptr<const PermissionSet> revokable_permissions =
+        updater.GetRevokablePermissions(extension.get());
+    EXPECT_FALSE(revokable_permissions->explicit_hosts().ContainsPattern(
+        chrome_favicon_pattern));
+    EXPECT_TRUE(revokable_permissions->explicit_hosts().ContainsPattern(
+        example_com_pattern));
+
+    // Withholding host permissions shouldn't withhold example.com.
+    ScriptingPermissionsModifier(profile(), extension)
+        .SetWithholdHostPermissions(true);
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(chrome_favicon_pattern));
+    EXPECT_FALSE(extension->permissions_data()
+                     ->active_permissions()
+                     .explicit_hosts()
+                     .ContainsPattern(example_com_pattern));
+  }
+  {
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("all urls extension")
+            .AddPermission("<all_urls>")
+            .Build();
+    URLPattern all_urls_pattern(Extension::kValidHostPermissionSchemes,
+                                "<all_urls>");
+    PermissionsUpdater updater(profile());
+    updater.InitializePermissions(extension.get());
+
+    // <all_urls> (strangely) includes the chrome://favicon/ permission.
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(chrome_favicon_pattern));
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(all_urls_pattern));
+
+    std::unique_ptr<const PermissionSet> revokable_permissions =
+        updater.GetRevokablePermissions(extension.get());
+    // TODO(https://crbug.com/859600): <all_urls> will report containing
+    // chrome://favicon/, even though it shouldn't since the scheme doesn't
+    // match.
+    // EXPECT_FALSE(revokable_permissions->explicit_hosts().ContainsPattern(
+    //     chrome_favicon_pattern));
+    EXPECT_TRUE(revokable_permissions->explicit_hosts().ContainsPattern(
+        all_urls_pattern));
+
+    ScriptingPermissionsModifier(profile(), extension)
+        .SetWithholdHostPermissions(true);
+    EXPECT_TRUE(extension->permissions_data()
+                    ->active_permissions()
+                    .explicit_hosts()
+                    .ContainsPattern(chrome_favicon_pattern));
+    EXPECT_FALSE(extension->permissions_data()
+                     ->active_permissions()
+                     .explicit_hosts()
+                     .ContainsPattern(all_urls_pattern));
+  }
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/scripting_permissions_modifier.cc b/chrome/browser/extensions/scripting_permissions_modifier.cc
index 8e2b49e9..d8ff8d6 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier.cc
@@ -20,20 +20,13 @@
 
 namespace {
 
-// The entry into the ExtensionPrefs for allowing an extension to script on
-// all urls without explicit permission.
-const char kExtensionAllowedOnAllUrlsPrefName[] =
+// The entry into the ExtensionPrefs indicating that an extension should be
+// granted all the requested host permissions without requiring explicit runtime
+// permission from the user. The preference name is different for legacy
+// reasons.
+const char kGrantExtensionAllHostPermissionsPrefName[] =
     "extension_can_script_all_urls";
 
-URLPatternSet FilterImpliedAllHostsPatterns(const URLPatternSet& patterns) {
-  URLPatternSet result;
-  for (const URLPattern& pattern : patterns) {
-    if (pattern.MatchesEffectiveTld())
-      result.AddPattern(pattern);
-  }
-  return result;
-}
-
 // Returns true if Chrome can potentially withhold permissions from the
 // extension.
 bool CanWithholdFromExtension(const Extension& extension) {
@@ -49,40 +42,58 @@
                                                       extension.location());
 }
 
-// Partitions |permissions| into two sets of permissions, placing any
-// all-hosts-like permissions into |withheld_permissions_out| and the rest
-// into |granted_permissions_out|.
+// Partitions |requested_permissions| into two sets of permissions, granted and
+// withheld. Granted permissions are added to |granted_permissions_out|, and
+// consist of any non-host permissions or host permissions that are present in
+// |runtime_granted_permissions|. Withheld permissions are added to
+// |withheld_permissions_out|, and are any host permissions that are not in
+// |granted_runtime_permissions|.
 void PartitionPermissions(
-    const PermissionSet& permissions,
+    const PermissionSet& requested_permissions,
+    const PermissionSet& runtime_granted_permissions,
     std::unique_ptr<const PermissionSet>* granted_permissions_out,
     std::unique_ptr<const PermissionSet>* withheld_permissions_out) {
-  auto segregate_url_permissions = [](const URLPatternSet& patterns,
-                                      URLPatternSet* granted,
-                                      URLPatternSet* withheld) {
-    for (const URLPattern& pattern : patterns) {
-      if (pattern.MatchesEffectiveTld())
-        withheld->AddPattern(pattern);
-      else
-        granted->AddPattern(pattern);
-    }
-  };
+  auto segregate_url_permissions =
+      [](const URLPatternSet& requested_patterns,
+         const URLPatternSet& runtime_granted_patterns, URLPatternSet* granted,
+         URLPatternSet* withheld) {
+        for (const URLPattern& pattern : requested_patterns) {
+          // The chrome://favicon permission is special. It is requested by
+          // extensions to access stored favicons, but is not a traditional
+          // host permission. Since it cannot be reasonably runtime-granted
+          // while the user is on the site (i.e., the user never visits
+          // chrome://favicon/), we auto-grant it and treat it like an API
+          // permission.
+          bool is_chrome_favicon =
+              pattern.host() == "favicon" && pattern.scheme() == "chrome";
+          bool is_runtime_granted =
+              runtime_granted_patterns.ContainsPattern(pattern);
+          if (is_chrome_favicon || is_runtime_granted)
+            granted->AddPattern(pattern);
+          else
+            withheld->AddPattern(pattern);
+        }
+      };
 
   URLPatternSet granted_explicit_hosts;
   URLPatternSet withheld_explicit_hosts;
   URLPatternSet granted_scriptable_hosts;
   URLPatternSet withheld_scriptable_hosts;
-  segregate_url_permissions(permissions.explicit_hosts(),
+  segregate_url_permissions(requested_permissions.explicit_hosts(),
+                            runtime_granted_permissions.explicit_hosts(),
                             &granted_explicit_hosts, &withheld_explicit_hosts);
-  segregate_url_permissions(permissions.scriptable_hosts(),
+  segregate_url_permissions(requested_permissions.scriptable_hosts(),
+                            runtime_granted_permissions.scriptable_hosts(),
                             &granted_scriptable_hosts,
                             &withheld_scriptable_hosts);
 
-  granted_permissions_out->reset(
-      new PermissionSet(permissions.apis(), permissions.manifest_permissions(),
-                        granted_explicit_hosts, granted_scriptable_hosts));
-  withheld_permissions_out->reset(
-      new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        withheld_explicit_hosts, withheld_scriptable_hosts));
+  *granted_permissions_out = std::make_unique<PermissionSet>(
+      requested_permissions.apis(),
+      requested_permissions.manifest_permissions(), granted_explicit_hosts,
+      granted_scriptable_hosts);
+  *withheld_permissions_out = std::make_unique<PermissionSet>(
+      APIPermissionSet(), ManifestPermissionSet(), withheld_explicit_hosts,
+      withheld_scriptable_hosts);
 }
 
 // Returns true if the extension should even be considered for being affected
@@ -103,7 +114,7 @@
     const ExtensionPrefs& prefs,
     const ExtensionId& id) {
   bool permissions_allowed = false;
-  if (!prefs.ReadPrefAsBoolean(id, kExtensionAllowedOnAllUrlsPrefName,
+  if (!prefs.ReadPrefAsBoolean(id, kGrantExtensionAllHostPermissionsPrefName,
                                &permissions_allowed)) {
     return base::nullopt;
   }
@@ -121,7 +132,7 @@
   // withhold permissions. Invert the boolean for backwards compatibility.
   bool permissions_allowed = !should_withhold;
   prefs->UpdateExtensionPref(
-      id, kExtensionAllowedOnAllUrlsPrefName,
+      id, kGrantExtensionAllHostPermissionsPrefName,
       std::make_unique<base::Value>(permissions_allowed));
 }
 
@@ -138,19 +149,20 @@
 
 ScriptingPermissionsModifier::~ScriptingPermissionsModifier() {}
 
-void ScriptingPermissionsModifier::SetWithholdAllUrls(bool should_withhold) {
+void ScriptingPermissionsModifier::SetWithholdHostPermissions(
+    bool should_withhold) {
   DCHECK(CanAffectExtension());
 
-  if (HasWithheldAllUrls() == should_withhold)
+  if (HasWithheldHostPermissions() == should_withhold)
     return;
 
   SetWithholdPermissionsPrefValue(extension_prefs_, extension_->id(),
                                   should_withhold);
 
   if (should_withhold)
-    WithholdImpliedAllHosts();
+    WithholdHostPermissions();
   else
-    GrantWithheldImpliedAllHosts();
+    GrantWithheldHostPermissions();
 
   // If this was an update to permissions, we also need to sync the change.
   // TODO(devlin): This isn't currently necessary. We should remove it and add
@@ -161,7 +173,7 @@
     sync_service->SyncExtensionChangeIfNeeded(*extension_);
 }
 
-bool ScriptingPermissionsModifier::HasWithheldAllUrls() const {
+bool ScriptingPermissionsModifier::HasWithheldHostPermissions() const {
   DCHECK(CanAffectExtension());
 
   base::Optional<bool> pref_value =
@@ -177,12 +189,16 @@
   if (!ShouldConsiderExtension(*extension_))
     return false;
 
-  // The extension can be affected if it currently has all-hosts-style
-  // permissions, or if it did and they are actively withheld.
-  return extension_->permissions_data()
-             ->active_permissions()
-             .ShouldWarnAllHosts() ||
-         extension_->permissions_data()->HasWithheldImpliedAllHosts();
+  // The extension can be affected if it currently has host permissions, or if
+  // it did and they are actively withheld.
+  return !extension_->permissions_data()
+              ->active_permissions()
+              .effective_hosts()
+              .is_empty() ||
+         !extension_->permissions_data()
+              ->withheld_permissions()
+              .effective_hosts()
+              .is_empty();
 }
 
 void ScriptingPermissionsModifier::GrantHostPermission(const GURL& url) {
@@ -213,32 +229,9 @@
   DCHECK(CanAffectExtension());
 
   GURL origin = url.GetOrigin();
-  // If the extension doesn't have access to the host, it clearly hasn't been
-  // granted permission.
-  if (!extension_->permissions_data()
-           ->active_permissions()
-           .effective_hosts()
-           .MatchesURL(origin)) {
-    return false;
-  }
-
-  // Check which permissions would have been withheld. If access to the host
-  // would have otherwise been withheld, then we know that access has been
-  // explicitly granted.
-  // TODO(devlin): This seems wrong, and won't work with trying to grant or
-  // withhold e.g. optional permissions. It's also overly expensive.
-  const PermissionSet& required_permissions =
-      PermissionsParser::GetRequiredPermissions(extension_.get());
-  std::unique_ptr<const PermissionSet> granted_permissions;
-  std::unique_ptr<const PermissionSet> withheld_permissions;
-  PartitionPermissions(required_permissions, &granted_permissions,
-                       &withheld_permissions);
-  if (!granted_permissions->effective_hosts().MatchesURL(origin) &&
-      withheld_permissions->effective_hosts().MatchesURL(origin)) {
-    return true;
-  }
-
-  return false;
+  return extension_prefs_->GetRuntimeGrantedPermissions(extension_->id())
+      ->effective_hosts()
+      .MatchesURL(origin);
 }
 
 void ScriptingPermissionsModifier::RemoveGrantedHostPermission(
@@ -282,15 +275,20 @@
     should_withhold = pref_value.has_value() && pref_value.value() == true;
   }
 
-  should_withhold &= permissions.ShouldWarnAllHosts();
+  should_withhold &= !permissions.effective_hosts().is_empty();
   if (!should_withhold) {
     *granted_permissions_out = permissions.Clone();
     withheld_permissions_out->reset(new PermissionSet());
     return;
   }
 
-  PartitionPermissions(permissions, granted_permissions_out,
-                       withheld_permissions_out);
+  // Only grant host permissions that the user has explicitly granted at
+  // runtime through the runtime host permissions feature or the optional
+  // permissions API.
+  std::unique_ptr<const PermissionSet> runtime_granted_permissions =
+      extension_prefs.GetRuntimeGrantedPermissions(extension.id());
+  PartitionPermissions(permissions, *runtime_granted_permissions,
+                       granted_permissions_out, withheld_permissions_out);
 }
 
 std::unique_ptr<const PermissionSet>
@@ -301,33 +299,35 @@
 
   std::unique_ptr<const PermissionSet> granted_permissions;
   std::unique_ptr<const PermissionSet> withheld_permissions;
+
+  // Revokable permissions are those that would be withheld if there were no
+  // runtime-granted permissions.
+  PermissionSet empty_runtime_granted_permissions;
   PartitionPermissions(extension_->permissions_data()->active_permissions(),
-                       &granted_permissions, &withheld_permissions);
+                       empty_runtime_granted_permissions, &granted_permissions,
+                       &withheld_permissions);
 
   return withheld_permissions;
 }
 
-void ScriptingPermissionsModifier::GrantWithheldImpliedAllHosts() {
+void ScriptingPermissionsModifier::GrantWithheldHostPermissions() {
   const PermissionSet& withheld =
       extension_->permissions_data()->withheld_permissions();
 
-  PermissionSet permissions(
-      APIPermissionSet(), ManifestPermissionSet(),
-      FilterImpliedAllHostsPatterns(withheld.explicit_hosts()),
-      FilterImpliedAllHostsPatterns(withheld.scriptable_hosts()));
+  PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
+                            withheld.explicit_hosts(),
+                            withheld.scriptable_hosts());
   PermissionsUpdater(browser_context_)
       .AddPermissions(extension_.get(), permissions);
 }
 
-void ScriptingPermissionsModifier::WithholdImpliedAllHosts() {
-  const PermissionSet& active =
-      extension_->permissions_data()->active_permissions();
-  PermissionSet permissions(
-      APIPermissionSet(), ManifestPermissionSet(),
-      FilterImpliedAllHostsPatterns(active.explicit_hosts()),
-      FilterImpliedAllHostsPatterns(active.scriptable_hosts()));
+void ScriptingPermissionsModifier::WithholdHostPermissions() {
+  // TODO(devlin): By using PermissionsUpdater::REMOVE_HARD, this will also
+  // affect granted_permissions in preferences. It shouldn't. We should
+  // introduce another enum to PermissionsModifier for removing only from
+  // runtime granted permissions.
   PermissionsUpdater(browser_context_)
-      .RemovePermissions(extension_.get(), permissions,
+      .RemovePermissions(extension_.get(), *GetRevokablePermissions(),
                          PermissionsUpdater::REMOVE_HARD);
 }
 
diff --git a/chrome/browser/extensions/scripting_permissions_modifier.h b/chrome/browser/extensions/scripting_permissions_modifier.h
index 88ad28e..a5650ee 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier.h
+++ b/chrome/browser/extensions/scripting_permissions_modifier.h
@@ -31,18 +31,16 @@
                                const scoped_refptr<const Extension>& extension);
   ~ScriptingPermissionsModifier();
 
-  // Sets whether Chrome should withhold <all_urls>-style permissions from the
-  // extension. Used when the features::kRuntimeHostPermissions feature is
-  // enabled.
+  // Sets whether Chrome should withhold host permissions from the extension.
+  // Used when the features::kRuntimeHostPermissions feature is enabled.
   // This may only be called for extensions that can be affected (i.e., for
   // which CanAffectExtension() returns true). Anything else will DCHECK.
-  void SetWithholdAllUrls(bool withhold);
+  void SetWithholdHostPermissions(bool withhold);
 
-  // Returns whether Chrome has withheld <all_urls>-style permissions from the
-  // extension.
+  // Returns whether Chrome has withheld host permissions from the extension.
   // This may only be called for extensions that can be affected (i.e., for
   // which CanAffectExtension() returns true). Anything else will DCHECK.
-  bool HasWithheldAllUrls() const;
+  bool HasWithheldHostPermissions() const;
 
   // Returns true if the associated extension can be affected by
   // features::kRuntimeHostPermissions.
@@ -54,7 +52,9 @@
   void GrantHostPermission(const GURL& url);
 
   // Returns true if the extension has been explicitly granted permission to run
-  // on the origin of |url|.
+  // on the origin of |url|. Note: This checks any runtime-granted permissions,
+  // which includes both granted optional permissions and permissions granted
+  // through the runtime host permissions feature.
   // This may only be called for extensions that can be affected (i.e., for
   // which CanAffectExtension() returns true). Anything else will DCHECK.
   bool HasGrantedHostPermission(const GURL& url) const;
@@ -83,11 +83,11 @@
   std::unique_ptr<const PermissionSet> GetRevokablePermissions() const;
 
  private:
-  // Grants any withheld all-hosts (or all-hosts-like) permissions.
-  void GrantWithheldImpliedAllHosts();
+  // Grants any withheld host permissions.
+  void GrantWithheldHostPermissions();
 
-  // Revokes any granted all-hosts (or all-hosts-like) permissions.
-  void WithholdImpliedAllHosts();
+  // Revokes any granted host permissions.
+  void WithholdHostPermissions();
 
   content::BrowserContext* browser_context_;
 
diff --git a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
index 33765ab..f93daf60 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
@@ -6,6 +6,8 @@
 
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/extensions/chrome_test_extension_loader.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_service_test_base.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/permissions_updater.h"
@@ -13,6 +15,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/crx_file/id_util.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_features.h"
@@ -21,6 +25,7 @@
 #include "extensions/common/url_pattern.h"
 #include "extensions/common/url_pattern_set.h"
 #include "extensions/common/value_builder.h"
+#include "extensions/test/test_extension_dir.h"
 
 namespace extensions {
 
@@ -103,89 +108,94 @@
 
 }  // namespace
 
-TEST_F(ScriptingPermissionsModifierUnitTest, WithholdAndGrantAllHosts) {
+TEST_F(ScriptingPermissionsModifierUnitTest, GrantAndWithholdHostPermissions) {
   InitializeEmptyExtensionService();
 
   // Permissions can only be withheld with the appropriate feature turned on.
   RuntimeHostPermissionsEnabledScope enabled_scope;
 
-  URLPattern google(URLPattern::SCHEME_ALL, "http://www.google.com/*");
-  URLPattern sub_google(URLPattern::SCHEME_ALL, "http://*.google.com/*");
-  URLPattern all_http(URLPattern::SCHEME_ALL, "http://*/*");
-  URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>");
-  URLPattern all_com(URLPattern::SCHEME_ALL, "http://*.com/*");
+  std::vector<std::string> test_cases[] = {
+      {"http://www.google.com/*"},
+      {"http://*/*"},
+      {"<all_urls>"},
+      {"http://*.com/*"},
+      {"http://google.com/*", "<all_urls>"},
+  };
 
-  std::set<URLPattern> all_host_patterns;
-  std::set<URLPattern> safe_patterns;
+  for (const auto& test_case : test_cases) {
+    std::string test_case_name = base::JoinString(test_case, ",");
+    SCOPED_TRACE(test_case_name);
+    std::set<URLPattern> patterns;
+    for (const auto& pattern : test_case)
+      patterns.insert(URLPattern(URLPattern::SCHEME_ALL, pattern));
+    scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
+        patterns, patterns, Manifest::INTERNAL, test_case_name);
 
-  all_host_patterns.insert(all_http);
-  all_host_patterns.insert(all_hosts);
-  all_host_patterns.insert(all_com);
+    PermissionsUpdater(profile()).InitializePermissions(extension.get());
 
-  safe_patterns.insert(google);
-  safe_patterns.insert(sub_google);
+    const PermissionsData* permissions_data = extension->permissions_data();
 
-  std::set<URLPattern> all_patterns =
-      base::STLSetUnion<std::set<URLPattern>>(all_host_patterns, safe_patterns);
+    ScriptingPermissionsModifier modifier(profile(), extension);
+    ASSERT_TRUE(modifier.CanAffectExtension());
 
-  scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
-      all_patterns, all_patterns, Manifest::INTERNAL, "a");
-  const PermissionsData* permissions_data = extension->permissions_data();
-  PermissionsUpdater updater(profile());
-  updater.InitializePermissions(extension.get());
+    // By default, all permissions are granted.
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->active_permissions().scriptable_hosts().patterns(),
+        patterns));
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->active_permissions().explicit_hosts().patterns(),
+        patterns));
+    EXPECT_TRUE(permissions_data->withheld_permissions()
+                    .scriptable_hosts()
+                    .patterns()
+                    .empty());
+    EXPECT_TRUE(permissions_data->withheld_permissions()
+                    .explicit_hosts()
+                    .patterns()
+                    .empty());
 
-  // By default, all permissions are granted.
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().scriptable_hosts().patterns(),
-      all_patterns));
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().explicit_hosts().patterns(),
-      all_patterns));
-  EXPECT_TRUE(permissions_data->withheld_permissions()
-                  .scriptable_hosts()
-                  .patterns()
-                  .empty());
-  EXPECT_TRUE(permissions_data->withheld_permissions()
-                  .explicit_hosts()
-                  .patterns()
-                  .empty());
+    // Then, withhold host permissions.
+    modifier.SetWithholdHostPermissions(true);
 
-  // Then, withhold the all-hosts permissions.
-  ScriptingPermissionsModifier modifier(profile(), extension);
-  modifier.SetWithholdAllUrls(true);
+    EXPECT_TRUE(permissions_data->active_permissions()
+                    .scriptable_hosts()
+                    .patterns()
+                    .empty());
+    // Note: can't use explicit_hosts().empty() here, since chrome://favicon/
+    // will remain will still be present in explicit_hosts() (it's not really a
+    // host permission and isn't withheld). SetsAreEqual() ignores
+    // chrome://favicon in its checks.
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->active_permissions().explicit_hosts().patterns(),
+        std::set<URLPattern>()));
 
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().scriptable_hosts().patterns(),
-      safe_patterns));
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().explicit_hosts().patterns(),
-      safe_patterns));
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
-      all_host_patterns));
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions().explicit_hosts().patterns(),
-      all_host_patterns));
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->withheld_permissions().scriptable_hosts().patterns(),
+        patterns));
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->withheld_permissions().explicit_hosts().patterns(),
+        patterns));
 
-  // Finally, re-grant the withheld permissions.
-  modifier.SetWithholdAllUrls(false);
+    // Finally, re-grant the withheld permissions.
+    modifier.SetWithholdHostPermissions(false);
 
-  // We should be back to our initial state - all requested permissions are
-  // granted.
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().scriptable_hosts().patterns(),
-      all_patterns));
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().explicit_hosts().patterns(),
-      all_patterns));
-  EXPECT_TRUE(permissions_data->withheld_permissions()
-                  .scriptable_hosts()
-                  .patterns()
-                  .empty());
-  EXPECT_TRUE(permissions_data->withheld_permissions()
-                  .explicit_hosts()
-                  .patterns()
-                  .empty());
+    // We should be back to our initial state - all requested permissions are
+    // granted.
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->active_permissions().scriptable_hosts().patterns(),
+        patterns));
+    EXPECT_TRUE(SetsAreEqual(
+        permissions_data->active_permissions().explicit_hosts().patterns(),
+        patterns));
+    EXPECT_TRUE(permissions_data->withheld_permissions()
+                    .scriptable_hosts()
+                    .patterns()
+                    .empty());
+    EXPECT_TRUE(permissions_data->withheld_permissions()
+                    .explicit_hosts()
+                    .patterns()
+                    .empty());
+  }
 }
 
 TEST_F(ScriptingPermissionsModifierUnitTest, SwitchBehavior) {
@@ -211,11 +221,11 @@
   EXPECT_TRUE(
       permissions_data->withheld_permissions().scriptable_hosts().is_empty());
   ScriptingPermissionsModifier modifier(profile(), extension);
-  EXPECT_FALSE(modifier.HasWithheldAllUrls());
+  EXPECT_FALSE(modifier.HasWithheldHostPermissions());
 
   // Revoke access.
-  modifier.SetWithholdAllUrls(true);
-  EXPECT_TRUE(modifier.HasWithheldAllUrls());
+  modifier.SetWithholdHostPermissions(true);
+  EXPECT_TRUE(modifier.HasWithheldHostPermissions());
   EXPECT_TRUE(
       permissions_data->active_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(SetsAreEqual(
@@ -236,7 +246,7 @@
   // withheld.
   enabled_scope = std::make_unique<RuntimeHostPermissionsEnabledScope>();
   updater.InitializePermissions(extension.get());
-  EXPECT_TRUE(modifier.HasWithheldAllUrls());
+  EXPECT_TRUE(modifier.HasWithheldHostPermissions());
   EXPECT_TRUE(
       permissions_data->active_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(SetsAreEqual(
@@ -259,7 +269,7 @@
   PermissionsUpdater(profile()).InitializePermissions(extension.get());
 
   ScriptingPermissionsModifier modifier(profile(), extension);
-  modifier.SetWithholdAllUrls(true);
+  modifier.SetWithholdHostPermissions(true);
 
   const GURL kUrl("https://www.google.com/");
   const GURL kUrl2("https://www.chromium.org/");
@@ -348,4 +358,75 @@
   }
 }
 
+TEST_F(ScriptingPermissionsModifierUnitTest,
+       ExtensionsInitializedWithSavedRuntimeGrantedHostPermissionsAcrossLoad) {
+  // Permissions can only be withheld with the appropriate feature turned on.
+  RuntimeHostPermissionsEnabledScope enabled_scope;
+
+  InitializeEmptyExtensionService();
+
+  const GURL kExampleCom("https://example.com/");
+  const GURL kChromiumOrg("https://chromium.org/");
+  const URLPatternSet kExampleComPatternSet({URLPattern(
+      Extension::kValidHostPermissionSchemes, "https://example.com/")});
+
+  TestExtensionDir test_extension_dir;
+  test_extension_dir.WriteManifest(
+      R"({
+           "name": "foo",
+           "manifest_version": 2,
+           "version": "1",
+           "permissions": ["<all_urls>"]
+         })");
+  ChromeTestExtensionLoader loader(profile());
+  loader.set_grant_permissions(true);
+  scoped_refptr<const Extension> extension =
+      loader.LoadExtension(test_extension_dir.UnpackedPath());
+
+  EXPECT_TRUE(extension->permissions_data()
+                  ->active_permissions()
+                  .explicit_hosts()
+                  .MatchesURL(kExampleCom));
+  EXPECT_TRUE(extension->permissions_data()
+                  ->active_permissions()
+                  .explicit_hosts()
+                  .MatchesURL(kChromiumOrg));
+
+  ScriptingPermissionsModifier(profile(), extension)
+      .SetWithholdHostPermissions(true);
+  EXPECT_FALSE(extension->permissions_data()
+                   ->active_permissions()
+                   .explicit_hosts()
+                   .MatchesURL(kExampleCom));
+  EXPECT_FALSE(extension->permissions_data()
+                   ->active_permissions()
+                   .explicit_hosts()
+                   .MatchesURL(kChromiumOrg));
+
+  ScriptingPermissionsModifier(profile(), extension)
+      .GrantHostPermission(kExampleCom);
+  EXPECT_TRUE(extension->permissions_data()
+                  ->active_permissions()
+                  .explicit_hosts()
+                  .MatchesURL(kExampleCom));
+  EXPECT_FALSE(extension->permissions_data()
+                   ->active_permissions()
+                   .explicit_hosts()
+                   .MatchesURL(kChromiumOrg));
+
+  {
+    TestExtensionRegistryObserver observer(ExtensionRegistry::Get(profile()));
+    service()->ReloadExtension(extension->id());
+    extension = base::WrapRefCounted(observer.WaitForExtensionLoaded());
+  }
+  EXPECT_TRUE(extension->permissions_data()
+                  ->active_permissions()
+                  .explicit_hosts()
+                  .MatchesURL(kExampleCom));
+  EXPECT_FALSE(extension->permissions_data()
+                   ->active_permissions()
+                   .explicit_hosts()
+                   .MatchesURL(kChromiumOrg));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/feedback/feedback_profile_observer.cc b/chrome/browser/feedback/feedback_profile_observer.cc
index cd8ece5..89fe114 100644
--- a/chrome/browser/feedback/feedback_profile_observer.cc
+++ b/chrome/browser/feedback/feedback_profile_observer.cc
@@ -50,10 +50,11 @@
 
 void FeedbackProfileObserver::QueueSingleReport(
     feedback::FeedbackUploader* uploader,
-    const std::string& data) {
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          base::BindOnce(&FeedbackUploaderChrome::QueueReport,
-                                         uploader->AsWeakPtr(), data));
+    std::unique_ptr<std::string> data) {
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&FeedbackUploaderChrome::QueueReport,
+                     uploader->AsWeakPtr(), std::move(data)));
 }
 
 void FeedbackProfileObserver::QueueUnsentReports(
@@ -61,11 +62,11 @@
   feedback::FeedbackUploaderChrome* uploader =
       feedback::FeedbackUploaderFactoryChrome::GetForBrowserContext(context);
   uploader->task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &FeedbackReport::LoadReportsAndQueue,
-          uploader->feedback_reports_path(),
-          base::Bind(&FeedbackProfileObserver::QueueSingleReport, uploader)));
+      FROM_HERE, base::BindOnce(&FeedbackReport::LoadReportsAndQueue,
+                                uploader->feedback_reports_path(),
+                                base::BindRepeating(
+                                    &FeedbackProfileObserver::QueueSingleReport,
+                                    uploader)));
 }
 
 }  // namespace feedback
diff --git a/chrome/browser/feedback/feedback_profile_observer.h b/chrome/browser/feedback/feedback_profile_observer.h
index 6f88388..d8f4dbcf 100644
--- a/chrome/browser/feedback/feedback_profile_observer.h
+++ b/chrome/browser/feedback/feedback_profile_observer.h
@@ -41,7 +41,7 @@
   void QueueUnsentReports(content::BrowserContext* context);
 
   static void QueueSingleReport(feedback::FeedbackUploader* uploader,
-                                const std::string& data);
+                                std::unique_ptr<std::string> data);
 
   // Used to track creation of profiles so we can load any unsent reports
   // for that profile.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index cbe8adec..c09eaae 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -219,6 +219,11 @@
 const char kContextualSuggestionsSlimPeekUIDescription[] =
     "Use a slimmer peek UI for the contextual suggestions bottom sheet.";
 
+const char kContextualSuggestionsOptOutName[] =
+    "Contextual Suggestions Opt-out";
+const char kContextualSuggestionsOptOutDescription[] =
+    "If enabled, allows the user to opt out of contextual suggestions.";
+
 const char kCreditCardAssistName[] = "Credit Card Assisted Filling";
 const char kCreditCardAssistDescription[] =
     "Enable assisted credit card filling on certain sites.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7120fd6..d8f37bde 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -163,6 +163,9 @@
 extern const char kContextualSuggestionsSlimPeekUIName[];
 extern const char kContextualSuggestionsSlimPeekUIDescription[];
 
+extern const char kContextualSuggestionsOptOutName[];
+extern const char kContextualSuggestionsOptOutDescription[];
+
 extern const char kCreditCardAssistName[];
 extern const char kCreditCardAssistDescription[];
 
diff --git a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
index 847fe0d..2cfad92 100644
--- a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
+++ b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
@@ -38,8 +38,7 @@
     clock_ = clock.get();
     emitter_->SetClockForTesting(std::move(clock));
 
-    auto timer = std::make_unique<base::MockTimer>(/*retain_user_task=*/true,
-                                                   /*is_repeating=*/true);
+    auto timer = std::make_unique<base::MockRepeatingTimer>();
     timer_ = timer.get();
     emitter_->SetTimerForTesting(std::move(timer));
 
@@ -85,7 +84,7 @@
   std::unique_ptr<history::HistoryService> history_service_;
   std::unique_ptr<GoogleSearchDomainMixingMetricsEmitter> emitter_;
   base::SimpleTestClock* clock_;  // Not owned.
-  base::MockTimer* timer_;        // Not owned.
+  base::MockRepeatingTimer* timer_;  // Not owned.
 };
 
 TEST_F(GoogleSearchDomainMixingMetricsEmitterTest, FirstStart) {
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc
index fa597c9..e9d912f3 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc
@@ -61,8 +61,7 @@
     media_sink_service_->SetDescriptionServiceForTest(
         std::move(mock_description_service));
 
-    mock_timer_ =
-        new base::MockTimer(true /*retain_user_task*/, false /*is_repeating*/);
+    mock_timer_ = new base::MockOneShotTimer();
     media_sink_service_->SetTimerForTest(base::WrapUnique(mock_timer_));
 
     auto mock_app_discovery_service =
@@ -109,7 +108,7 @@
   TestDialRegistry test_dial_registry_;
   MockDeviceDescriptionService* mock_description_service_;
   MockDialAppDiscoveryService* mock_app_discovery_service_;
-  base::MockTimer* mock_timer_;
+  base::MockOneShotTimer* mock_timer_;
 
   std::unique_ptr<DialMediaSinkServiceImpl> media_sink_service_;
 
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
index 5e408a4..3a9aa68 100644
--- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
+++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service_impl_unittest.cc
@@ -82,8 +82,7 @@
   }
 
   void SetUp() override {
-    auto mock_timer = std::make_unique<base::MockTimer>(
-        true /*retain_user_task*/, false /*is_repeating*/);
+    auto mock_timer = std::make_unique<base::MockOneShotTimer>();
     mock_timer_ = mock_timer.get();
     media_sink_service_impl_.SetTimerForTest(std::move(mock_timer));
   }
@@ -130,7 +129,7 @@
   TestMediaSinkService dial_media_sink_service_;
   std::unique_ptr<cast_channel::MockCastSocketService>
       mock_cast_socket_service_;
-  base::MockTimer* mock_timer_;
+  base::MockOneShotTimer* mock_timer_;
   CastMediaSinkServiceImpl media_sink_service_impl_;
   testing::NiceMock<MockObserver> observer_;
 
diff --git a/chrome/browser/media/router/media_router_metrics.cc b/chrome/browser/media/router/media_router_metrics.cc
index d4140ad..861e3b2 100644
--- a/chrome/browser/media/router/media_router_metrics.cc
+++ b/chrome/browser/media/router/media_router_metrics.cc
@@ -59,12 +59,18 @@
     "MediaRouter.PresentationRequest.AvailabilityUrlType";
 const char MediaRouterMetrics::kHistogramRouteCreationOutcome[] =
     "MediaRouter.Route.CreationOutcome";
+const char MediaRouterMetrics::kHistogramUiDeviceCount[] =
+    "MediaRouter.Ui.Device.Count";
 const char MediaRouterMetrics::kHistogramUiDialogPaint[] =
     "MediaRouter.Ui.Dialog.Paint";
 const char MediaRouterMetrics::kHistogramUiDialogLoadedWithData[] =
     "MediaRouter.Ui.Dialog.LoadedWithData";
 const char MediaRouterMetrics::kHistogramUiFirstAction[] =
     "MediaRouter.Ui.FirstAction";
+const char MediaRouterMetrics::kHistogramStartLocalPosition[] =
+    "MediaRouter.Ui.Action.StartLocalPosition";
+const char MediaRouterMetrics::kHistogramStartLocalSessionSuccessful[] =
+    "MediaRouter.Ui.Action.StartLocalSessionSuccessful";
 
 // static
 void MediaRouterMetrics::RecordMediaRouterDialogOrigin(
@@ -148,4 +154,19 @@
                             SinkIconType::TOTAL_COUNT);
 }
 
+// static
+void MediaRouterMetrics::RecordDeviceCount(int device_count) {
+  UMA_HISTOGRAM_COUNTS_100(kHistogramUiDeviceCount, device_count);
+}
+
+// static
+void MediaRouterMetrics::RecordStartRouteDeviceIndex(int index) {
+  base::UmaHistogramSparse(kHistogramStartLocalPosition, std::min(index, 100));
+}
+
+// static
+void MediaRouterMetrics::RecordStartLocalSessionSuccessful(bool success) {
+  UMA_HISTOGRAM_BOOLEAN(kHistogramStartLocalSessionSuccessful, success);
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_metrics.h b/chrome/browser/media/router/media_router_metrics.h
index 6f676ac9..d6bec41 100644
--- a/chrome/browser/media/router/media_router_metrics.h
+++ b/chrome/browser/media/router/media_router_metrics.h
@@ -89,9 +89,12 @@
   static const char kHistogramMediaSinkType[];
   static const char kHistogramPresentationUrlType[];
   static const char kHistogramRouteCreationOutcome[];
+  static const char kHistogramUiDeviceCount[];
   static const char kHistogramUiDialogPaint[];
   static const char kHistogramUiDialogLoadedWithData[];
   static const char kHistogramUiFirstAction[];
+  static const char kHistogramStartLocalPosition[];
+  static const char kHistogramStartLocalSessionSuccessful[];
 
   // Records where the user clicked to open the Media Router dialog.
   static void RecordMediaRouterDialogOrigin(
@@ -135,6 +138,17 @@
 
   // Records the type of the sink that media is being Cast to.
   static void RecordMediaSinkType(SinkIconType sink_icon_type);
+
+  // Records the number of devices shown in the Cast dialog. The device count
+  // may be 0.
+  static void RecordDeviceCount(int device_count);
+
+  // Records the index of the device the user has started casting to on the
+  // devices list. The index starts at 0.
+  static void RecordStartRouteDeviceIndex(int index);
+
+  // Records whether or not an attempt to start casting was successful.
+  static void RecordStartLocalSessionSuccessful(bool success);
 };
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/media_router_metrics_unittest.cc b/chrome/browser/media/router/media_router_metrics_unittest.cc
index a5dc0907..16e3575 100644
--- a/chrome/browser/media/router/media_router_metrics_unittest.cc
+++ b/chrome/browser/media/router/media_router_metrics_unittest.cc
@@ -189,4 +189,45 @@
                   Bucket(static_cast<int>(SinkIconType::GENERIC), 1)));
 }
 
+TEST(MediaRouterMetricsTest, RecordDeviceCount) {
+  base::HistogramTester tester;
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiDeviceCount, 0);
+
+  MediaRouterMetrics::RecordDeviceCount(30);
+  MediaRouterMetrics::RecordDeviceCount(0);
+
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiDeviceCount, 2);
+  EXPECT_THAT(tester.GetAllSamples(MediaRouterMetrics::kHistogramUiDeviceCount),
+              ElementsAre(Bucket(0, 1), Bucket(30, 1)));
+}
+
+TEST(MediaRouterMetricsTest, RecordStartRouteDeviceIndex) {
+  base::HistogramTester tester;
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStartLocalPosition, 0);
+
+  MediaRouterMetrics::RecordStartRouteDeviceIndex(30);
+  MediaRouterMetrics::RecordStartRouteDeviceIndex(0);
+
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStartLocalPosition, 2);
+  EXPECT_THAT(
+      tester.GetAllSamples(MediaRouterMetrics::kHistogramStartLocalPosition),
+      ElementsAre(Bucket(0, 1), Bucket(30, 1)));
+}
+
+TEST(MediaRouterMetricsTest, RecordStartLocalSessionSuccessful) {
+  base::HistogramTester tester;
+  tester.ExpectTotalCount(
+      MediaRouterMetrics::kHistogramStartLocalSessionSuccessful, 0);
+
+  MediaRouterMetrics::RecordStartLocalSessionSuccessful(true);
+  MediaRouterMetrics::RecordStartLocalSessionSuccessful(false);
+  MediaRouterMetrics::RecordStartLocalSessionSuccessful(true);
+
+  tester.ExpectTotalCount(
+      MediaRouterMetrics::kHistogramStartLocalSessionSuccessful, 3);
+  EXPECT_THAT(tester.GetAllSamples(
+                  MediaRouterMetrics::kHistogramStartLocalSessionSuccessful),
+              ElementsAre(Bucket(false, 1), Bucket(true, 2)));
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
index e5bf097e..1e87cc6 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,7 +26,6 @@
 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #include "ui/views/widget/widget.h"
 
@@ -166,7 +166,7 @@
   task_runner->PostTask(FROM_HERE, run_loop->QuitWhenIdleClosure());
 }
 
-class NativeDesktopMediaListTest : public views::ViewsTestBase {
+class NativeDesktopMediaListTest : public ChromeViewsTestBase {
  public:
   NativeDesktopMediaListTest() = default;
 
@@ -174,7 +174,7 @@
     for (size_t i = 0; i < desktop_widgets_.size(); i++)
       desktop_widgets_[i].reset();
 
-    ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
   void AddNativeWindow(int id) {
diff --git a/chrome/browser/offline_pages/android/background_scheduler_bridge.cc b/chrome/browser/offline_pages/android/background_scheduler_bridge.cc
index 38ba552..1c156c1 100644
--- a/chrome/browser/offline_pages/android/background_scheduler_bridge.cc
+++ b/chrome/browser/offline_pages/android/background_scheduler_bridge.cc
@@ -22,16 +22,6 @@
 namespace offline_pages {
 namespace android {
 
-namespace {
-
-// C++ callback that delegates to Java callback.
-void ProcessingDoneCallback(
-    const ScopedJavaGlobalRef<jobject>& j_callback_obj, bool result) {
-  base::android::RunCallbackAndroid(j_callback_obj, result);
-}
-
-}  // namespace
-
 // JNI call to start request processing in scheduled mode.
 static jboolean JNI_BackgroundSchedulerBridge_StartScheduledProcessing(
     JNIEnv* env,
@@ -55,7 +45,9 @@
       static_cast<net::NetworkChangeNotifier::ConnectionType>(
           j_net_connection_type));
   return coordinator->StartScheduledProcessing(
-      device_conditions, base::Bind(&ProcessingDoneCallback, j_callback_ref));
+      device_conditions,
+      base::BindRepeating(&base::android::RunBooleanCallbackAndroid,
+                          j_callback_ref));
 }
 
 // JNI call to stop request processing in scheduled mode.
@@ -87,7 +79,8 @@
 }
 
 void BackgroundSchedulerBridge::BackupSchedule(
-    const TriggerConditions& trigger_conditions, long delay_in_seconds) {
+    const TriggerConditions& trigger_conditions,
+    int64_t delay_in_seconds) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_conditions =
       CreateTriggerConditions(env, trigger_conditions.require_power_connected,
diff --git a/chrome/browser/offline_pages/android/background_scheduler_bridge.h b/chrome/browser/offline_pages/android/background_scheduler_bridge.h
index 59cb875..d21cfd91 100644
--- a/chrome/browser/offline_pages/android/background_scheduler_bridge.h
+++ b/chrome/browser/offline_pages/android/background_scheduler_bridge.h
@@ -5,9 +5,11 @@
 #ifndef CHROME_BROWSER_OFFLINE_PAGES_ANDROID_BACKGROUND_SCHEDULER_BRIDGE_H_
 #define CHROME_BROWSER_OFFLINE_PAGES_ANDROID_BACKGROUND_SCHEDULER_BRIDGE_H_
 
-#include "components/offline_pages/core/background/scheduler.h"
+#include <stdint.h>
+#include <memory>
 
 #include "base/android/jni_android.h"
+#include "components/offline_pages/core/background/scheduler.h"
 
 namespace offline_pages {
 namespace android {
@@ -22,7 +24,7 @@
   // Scheduler implementation.
   void Schedule(const TriggerConditions& trigger_conditions) override;
   void BackupSchedule(const TriggerConditions& trigger_conditions,
-                      long delay_in_seconds) override;
+                      int64_t delay_in_seconds) override;
   void Unschedule() override;
   const DeviceConditions& GetCurrentDeviceConditions() override;
 
diff --git a/chrome/browser/offline_pages/android/cct_request_observer.cc b/chrome/browser/offline_pages/android/cct_request_observer.cc
index ea678a9..1ff1d993 100644
--- a/chrome/browser/offline_pages/android/cct_request_observer.cc
+++ b/chrome/browser/offline_pages/android/cct_request_observer.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/offline_pages/android/cct_request_observer.h"
 
+#include <utility>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_int_wrapper.h"
 #include "base/android/jni_string.h"
@@ -60,7 +62,7 @@
           env, as_jint(static_cast<int>(status)),
           base::android::ConvertUTF8ToJavaString(env, request.client_id().id));
 
-  base::android::RunCallbackAndroid(j_callback_, callback_info);
+  base::android::RunObjectCallbackAndroid(j_callback_, callback_info);
 }
 
 void CCTRequestObserver::OnChanged(const SavePageRequest& request) {}
diff --git a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc
index 69b895b..c1a1c55f 100644
--- a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc
+++ b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc
@@ -4,6 +4,11 @@
 
 #include "chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.h"
 
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
@@ -109,12 +114,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   JNI_OfflinePageEvaluationBridge_ToJavaOfflinePageList(env, j_result_obj,
                                                         result);
-  base::android::RunCallbackAndroid(j_callback_obj, j_result_obj);
-}
-
-void OnPushRequestsDone(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
-                        bool result) {
-  base::android::RunCallbackAndroid(j_callback_obj, result);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result_obj);
 }
 
 void OnGetAllRequestsDone(
@@ -125,13 +125,13 @@
   ScopedJavaLocalRef<jobjectArray> j_result_obj =
       JNI_OfflinePageEvaluationBridge_CreateJavaSavePageRequests(
           env, std::move(all_requests));
-  base::android::RunCallbackAndroid(j_callback_obj, j_result_obj);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result_obj);
 }
 
 void OnRemoveRequestsDone(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
                           const MultipleItemStatuses& removed_request_results) {
-  base::android::RunCallbackAndroid(j_callback_obj,
-                                    int(removed_request_results.size()));
+  base::android::RunIntCallbackAndroid(
+      j_callback_obj, static_cast<int>(removed_request_results.size()));
 }
 
 std::unique_ptr<KeyedService> GetTestingRequestCoordinator(
@@ -322,10 +322,10 @@
     const JavaParamRef<jobject>& j_callback_obj) {
   ScopedJavaGlobalRef<jobject> j_callback_ref(j_callback_obj);
   DCHECK(request_coordinator_);
-  base::android::RunCallbackAndroid(j_callback_obj, false);
+  base::android::RunBooleanCallbackAndroid(j_callback_obj, false);
 
-  return request_coordinator_->StartImmediateProcessing(
-      base::Bind(&OnPushRequestsDone, j_callback_ref));
+  return request_coordinator_->StartImmediateProcessing(base::BindRepeating(
+      &base::android::RunBooleanCallbackAndroid, j_callback_ref));
 }
 
 void OfflinePageEvaluationBridge::SavePageLater(
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc
index 0a28ef1..0c50e97 100644
--- a/chrome/browser/offline_pages/android/offline_page_bridge.cc
+++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -115,7 +115,7 @@
     const OfflinePageModel::MultipleOfflinePageItemResult& result) {
   JNIEnv* env = base::android::AttachCurrentThread();
   JNI_SavePageRequest_ToJavaOfflinePageList(env, j_result_obj, result);
-  base::android::RunCallbackAndroid(j_callback_obj, j_result_obj);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result_obj);
 }
 
 void SavePageCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
@@ -131,7 +131,8 @@
 
 void DeletePageCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
                         OfflinePageModel::DeletePageResult result) {
-  base::android::RunCallbackAndroid(j_callback_obj, static_cast<int>(result));
+  base::android::RunIntCallbackAndroid(j_callback_obj,
+                                       static_cast<int>(result));
 }
 
 void SelectPageCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
@@ -141,7 +142,7 @@
 
   if (!result.empty())
     j_result = JNI_SavePageRequest_ToJavaOfflinePageItem(env, result.front());
-  base::android::RunCallbackAndroid(j_callback_obj, j_result);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result);
 }
 
 void SingleOfflinePageItemCallback(
@@ -152,7 +153,7 @@
 
   if (result)
     j_result = JNI_SavePageRequest_ToJavaOfflinePageItem(env, *result);
-  base::android::RunCallbackAndroid(j_callback_obj, j_result);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result);
 }
 
 void CheckForNewOfflineContentCallback(
@@ -165,15 +166,7 @@
   ScopedJavaLocalRef<jstring> j_result =
       base::android::ConvertUTF16ToJavaString(env, relevant_host);
 
-  base::android::RunCallbackAndroid(j_callback_obj, j_result);
-}
-
-void GetLaunchUrlByOfflineIdCallback(
-    const ScopedJavaGlobalRef<jobject>& j_callback_obj,
-    const std::string& result) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  base::android::RunCallbackAndroid(j_callback_obj,
-                                    ConvertUTF8ToJavaString(env, result));
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result);
 }
 
 void GetLaunchUrlBySizeAndDigestCallback(
@@ -185,7 +178,7 @@
       Java_OfflinePageBridge_createLoadUrlParams(
           env, ConvertUTF8ToJavaString(env, url.spec()),
           ConvertUTF8ToJavaString(env, extra_headers));
-  base::android::RunCallbackAndroid(j_callback_obj, loadUrlParams);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, loadUrlParams);
 }
 
 void ValidateFileCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
@@ -200,13 +193,7 @@
     launch_url = url;
   else
     launch_url = net::FilePathToFileURL(file_path);
-  GetLaunchUrlByOfflineIdCallback(j_callback_obj, launch_url.spec());
-}
-
-void AcquireFileAccessPermissionCallback(
-    const ScopedJavaGlobalRef<jobject>& j_callback_obj,
-    bool granted) {
-  base::android::RunCallbackAndroid(j_callback_obj, granted);
+  base::android::RunStringCallbackAndroid(j_callback_obj, launch_url.spec());
 }
 
 ScopedJavaLocalRef<jobjectArray> JNI_SavePageRequest_CreateJavaSavePageRequests(
@@ -247,7 +234,7 @@
   ScopedJavaLocalRef<jobjectArray> j_result_obj =
       JNI_SavePageRequest_CreateJavaSavePageRequests(env,
                                                      std::move(all_requests));
-  base::android::RunCallbackAndroid(j_callback_obj, j_result_obj);
+  base::android::RunObjectCallbackAndroid(j_callback_obj, j_result_obj);
 }
 
 UpdateRequestResult ToUpdateRequestResult(ItemActionStatus status) {
@@ -290,15 +277,13 @@
 
 void SavePageLaterCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
                            AddRequestResult value) {
-  base::android::RunCallbackAndroid(j_callback_obj, static_cast<int>(value));
+  base::android::RunIntCallbackAndroid(j_callback_obj, static_cast<int>(value));
 }
 
 void PublishPageDone(
     const ScopedJavaGlobalRef<jobject>& j_published_callback_obj,
     const base::FilePath& file_path,
     SavePageResult result) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-
   base::FilePath file_path_or_empty;
   if (result != SavePageResult::SUCCESS)
     file_path_or_empty = file_path;
@@ -306,9 +291,8 @@
   UMA_HISTOGRAM_ENUMERATION("OfflinePages.Sharing.PublishInternalPageResult",
                             result, SavePageResult::RESULT_COUNT);
 
-  base::android::RunCallbackAndroid(
-      j_published_callback_obj,
-      ConvertUTF8ToJavaString(env, file_path.value()));
+  base::android::RunStringCallbackAndroid(j_published_callback_obj,
+                                          file_path.value());
 }
 
 }  // namespace
@@ -794,7 +778,7 @@
   if (!coordinator) {
     // Callback with null to signal that results are unavailable.
     const JavaParamRef<jobject> empty_result(nullptr);
-    base::android::RunCallbackAndroid(j_callback_obj, empty_result);
+    base::android::RunObjectCallbackAndroid(j_callback_obj, empty_result);
     return;
   }
 
@@ -819,7 +803,7 @@
   if (!coordinator) {
     // Callback with null to signal that results are unavailable.
     const JavaParamRef<jobject> empty_result(nullptr);
-    base::android::RunCallbackAndroid(j_callback_obj, empty_result);
+    base::android::RunObjectCallbackAndroid(j_callback_obj, empty_result);
     return;
   }
 
@@ -965,12 +949,13 @@
     const ScopedJavaGlobalRef<jobject>& j_callback_obj,
     const OfflinePageItem* offline_page) {
   if (!offline_page) {
-    GetLaunchUrlByOfflineIdCallback(j_callback_obj, std::string());
+    base::android::RunStringCallbackAndroid(j_callback_obj, std::string());
     return;
   }
 
   if (offline_page_model_->IsArchiveInInternalDir(offline_page->file_path)) {
-    GetLaunchUrlByOfflineIdCallback(j_callback_obj, offline_page->url.spec());
+    base::android::RunStringCallbackAndroid(j_callback_obj,
+                                            offline_page->url.spec());
     return;
   }
 
@@ -1034,12 +1019,12 @@
   content::WebContents* web_contents =
       content::WebContents::FromJavaWebContents(j_web_contents);
   if (!web_contents) {
-    AcquireFileAccessPermissionCallback(j_callback_ref, false);
+    base::android::RunBooleanCallbackAndroid(j_callback_ref, false);
     return;
   }
   OfflinePageUtils::AcquireFileAccessPermission(
-      web_contents,
-      base::BindOnce(&AcquireFileAccessPermissionCallback, j_callback_ref));
+      web_contents, base::BindOnce(&base::android::RunBooleanCallbackAndroid,
+                                   j_callback_ref));
 }
 
 void OfflinePageBridge::NotifyIfDoneLoading() const {
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
index a9c9a7f..487544b 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -234,7 +234,7 @@
 
   // Returns the mock timer used for buffering updates in the
   // PageLoadMetricsUpdateDispatcher.
-  base::MockTimer* GetMostRecentTimer() {
+  base::MockOneShotTimer* GetMostRecentTimer() {
     return embedder_interface_->GetMockTimer();
   }
 
@@ -248,7 +248,7 @@
     // If sending the timing update caused the PageLoadMetricsUpdateDispatcher
     // to schedule a buffering timer, then fire it now so metrics are dispatched
     // to observers.
-    base::MockTimer* mock_timer = GetMostRecentTimer();
+    base::MockOneShotTimer* mock_timer = GetMostRecentTimer();
     if (mock_timer && mock_timer->IsRunning())
       mock_timer->Fire();
   }
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
index 25e4297..623b2885 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
@@ -92,7 +92,7 @@
   // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
   // schedule a buffering timer, then fire it now so metrics are dispatched to
   // observers.
-  base::MockTimer* mock_timer = GetMockTimer();
+  base::MockOneShotTimer* mock_timer = GetMockTimer();
   if (mock_timer && mock_timer->IsRunning())
     mock_timer->Fire();
 }
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.css b/chrome/browser/resources/local_ntp/most_visited_single.css
index b4394c6..c04d74c 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.css
+++ b/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -381,7 +381,8 @@
   opacity: 1;
   padding: var(--md-tile-padding);
   position: relative;
-  transition-property: background, border-color, box-shadow, opacity;
+  transition-property:
+      background, border-color, box-shadow, opacity, text-shadow;
   width: var(--md-tile-width);
 }
 
@@ -412,6 +413,7 @@
 
 body.dark-theme .md-tile:active .md-title {
   color: rgba(33, 32, 36, 0.86);
+  text-shadow: none;
 }
 
 body.dark-theme .md-tile:active .md-menu::after {
@@ -500,6 +502,7 @@
 
 body.dark-theme .md-title {
   color: rgb(248, 249, 250);
+  text-shadow: 0 0 8px 0 rgba(0,0,0,0.5);
 }
 
 .md-menu {
diff --git a/chrome/browser/resources/md_bookmarks/app.html b/chrome/browser/resources/md_bookmarks/app.html
index 67cefaf..16ad179 100644
--- a/chrome/browser/resources/md_bookmarks/app.html
+++ b/chrome/browser/resources/md_bookmarks/app.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr/ui/splitter.html">
 <link rel="import" href="chrome://bookmarks/api_listener.html">
 <link rel="import" href="chrome://bookmarks/command_manager.html">
@@ -19,7 +20,7 @@
   <template>
     <style>
       :host {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         display: flex;
         flex-direction: column;
         height: 100%;
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.html b/chrome/browser/resources/md_bookmarks/command_manager.html
index 12447ac7..9285409 100644
--- a/chrome/browser/resources/md_bookmarks/command_manager.html
+++ b/chrome/browser/resources/md_bookmarks/command_manager.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr/ui/command.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
 <link rel="import" href="chrome://bookmarks/dialog_focus_manager.html">
@@ -19,7 +20,7 @@
 
       .sublabel {
         -webkit-margin-start: 8px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         text-align: end;
         width: 3ch;
       }
diff --git a/chrome/browser/resources/md_bookmarks/dnd_chip.html b/chrome/browser/resources/md_bookmarks/dnd_chip.html
index a36fab5..bb7c77b 100644
--- a/chrome/browser/resources/md_bookmarks/dnd_chip.html
+++ b/chrome/browser/resources/md_bookmarks/dnd_chip.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://bookmarks/shared_style.html">
@@ -51,7 +52,7 @@
       #icon-wrapper {
         background: white;
         border-radius: 12px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         height: 24px;
         position: relative;
         width: 24px;
diff --git a/chrome/browser/resources/md_bookmarks/folder_node.html b/chrome/browser/resources/md_bookmarks/folder_node.html
index 012f0dad..358e7772 100644
--- a/chrome/browser/resources/md_bookmarks/folder_node.html
+++ b/chrome/browser/resources/md_bookmarks/folder_node.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://bookmarks/actions.html">
@@ -38,7 +39,7 @@
 
       #folder-label {
         -webkit-padding-end: 8px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         flex-grow: 1;
       }
 
@@ -52,7 +53,7 @@
       }
 
       #arrow {
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         margin: 0 8px;
       }
 
diff --git a/chrome/browser/resources/md_bookmarks/item.html b/chrome/browser/resources/md_bookmarks/item.html
index 44b6bd68..a031adb 100644
--- a/chrome/browser/resources/md_bookmarks/item.html
+++ b/chrome/browser/resources/md_bookmarks/item.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://bookmarks/actions.html">
@@ -37,7 +38,7 @@
 
       #website-url {
         -webkit-margin-start: 20px;
-        /* Transparent version of --secondary-text-color */
+        /* Transparent version of --cr-secondary-text-color */
         color: rgba(0, 0, 0, 0.54);
         display: none;
         flex: 1;
@@ -49,7 +50,7 @@
       }
 
       #icon {
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         flex: none;
       }
 
diff --git a/chrome/browser/resources/md_bookmarks/shared_style.html b/chrome/browser/resources/md_bookmarks/shared_style.html
index bfdd246..353cd3e 100644
--- a/chrome/browser/resources/md_bookmarks/shared_style.html
+++ b/chrome/browser/resources/md_bookmarks/shared_style.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://bookmarks/shared_vars.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <dom-module id="shared-style">
   <template>
@@ -9,7 +10,7 @@
       }
 
       paper-icon-button-light.more-vert-button div {
-        border: 2px solid var(--secondary-text-color);
+        border: 2px solid var(--cr-secondary-text-color);
         border-radius: 2px;
         margin: 1px 8px;
         pointer-events: none;
diff --git a/chrome/browser/resources/md_bookmarks/shared_vars.html b/chrome/browser/resources/md_bookmarks/shared_vars.html
index a51a40d..b4489f77 100644
--- a/chrome/browser/resources/md_bookmarks/shared_vars.html
+++ b/chrome/browser/resources/md_bookmarks/shared_vars.html
@@ -14,8 +14,6 @@
     --iron-icon-height: 20px;
     --iron-icon-width: 20px;
     --min-sidebar-width: 256px;
-    --primary-text-color: var(--google-grey-900);
-    --secondary-text-color: var(--google-grey-refresh-700);
     --splitter-width: 15px;
   }
 </style>
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html
index 13481a8..9afa904 100644
--- a/chrome/browser/resources/md_history/app.html
+++ b/chrome/browser/resources/md_history/app.html
@@ -1,4 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/cr/ui.html">
 <link rel="import" href="chrome://resources/html/cr/ui/command.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-media-query/iron-media-query.html">
@@ -17,7 +19,7 @@
   <template>
     <style include="shared-style">
       :host {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         display: block;
         height: 100%;
         line-height: 1.54;  /* 20px. */
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html
index 64aae9e..f80fda1 100644
--- a/chrome/browser/resources/md_history/history_item.html
+++ b/chrome/browser/resources/md_history/history_item.html
@@ -79,7 +79,7 @@
       /* #checkbox[unresolved] styling is necessary since cr-checkbox is being
          lazy-loaded. */
       #checkbox[unresolved] {
-        border: 2px solid var(--secondary-text-color);
+        border: 2px solid var(--cr-secondary-text-color);
         border-radius: 2px;
         content: '';
         display: block;
@@ -95,7 +95,7 @@
 
       #domain {
         -webkit-margin-start: 16px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         flex-shrink: 0;
       }
 
diff --git a/chrome/browser/resources/md_history/shared_style.html b/chrome/browser/resources/md_history/shared_style.html
index 37273cbd..6b30fd7 100644
--- a/chrome/browser/resources/md_history/shared_style.html
+++ b/chrome/browser/resources/md_history/shared_style.html
@@ -1,5 +1,6 @@
 <link rel="import" href="chrome://history/shared_vars.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <dom-module id="shared-style">
   <template>
@@ -43,7 +44,7 @@
 
       .website-title {
         -webkit-margin-start: 16px;
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         overflow: hidden;
         text-decoration: none;
         text-overflow: ellipsis;
@@ -63,7 +64,7 @@
       }
 
       paper-icon-button-light.more-vert-button div {
-        border: 2px solid var(--secondary-text-color);
+        border: 2px solid var(--cr-secondary-text-color);
         border-radius: 2px;
         margin: 1px 8px;
         pointer-events: none;
diff --git a/chrome/browser/resources/md_history/shared_vars.html b/chrome/browser/resources/md_history/shared_vars.html
index 5fbfc8e..ee1e436 100644
--- a/chrome/browser/resources/md_history/shared_vars.html
+++ b/chrome/browser/resources/md_history/shared_vars.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
 
 <custom-style>
 <style is="custom-style">
@@ -27,8 +26,6 @@
     --iron-icon-height: var(--cr-icon-size);
     --iron-icon-width: var(--cr-icon-size);
     --link-color: var(--google-blue-700);
-    --primary-text-color: var(--google-grey-900);
-    --secondary-text-color: var(--google-grey-refresh-700);
     --separator-color: rgba(0, 0, 0, 0.08);
     --side-bar-width: 256px;
     --sidebar-footer-text-color: #6e6e6e;
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html
index 3bae105..9efd7cc 100644
--- a/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -33,7 +33,7 @@
       }
 
       #last-update-time {
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
       }
 
       #title-left-content {
@@ -49,7 +49,7 @@
 
       #right-buttons {
         -webkit-margin-end: 12px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
       }
 
       #collapse {
diff --git a/chrome/browser/resources/md_history/synced_device_manager.html b/chrome/browser/resources/md_history/synced_device_manager.html
index 90054b9..0679f90 100644
--- a/chrome/browser/resources/md_history/synced_device_manager.html
+++ b/chrome/browser/resources/md_history/synced_device_manager.html
@@ -1,4 +1,5 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/html/cr/ui/focus_grid.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
@@ -6,6 +7,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://history/shared_style.html">
 <link rel="import" href="chrome://history/synced_device_card.html">
 
@@ -46,7 +48,7 @@
       }
 
       #sign-in-promo-desc {
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         font-size: 123%;
         margin-top: 10px;
       }
diff --git a/chrome/browser/resources/md_user_manager/create_profile.html b/chrome/browser/resources/md_user_manager/create_profile.html
index 6eea5e1..3bda994 100644
--- a/chrome/browser/resources/md_user_manager/create_profile.html
+++ b/chrome/browser/resources/md_user_manager/create_profile.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -25,7 +26,7 @@
       }
 
       .container {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         width: var(--page-width);
       }
 
diff --git a/chrome/browser/resources/md_user_manager/error_dialog.html b/chrome/browser/resources/md_user_manager/error_dialog.html
index cd2feba9..dcefc70 100644
--- a/chrome/browser/resources/md_user_manager/error_dialog.html
+++ b/chrome/browser/resources/md_user_manager/error_dialog.html
@@ -2,12 +2,13 @@
 
 <link rel="import" href="/shared_styles.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <dom-module id="error-dialog">
   <template>
     <style include="shared-styles">
       :host {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
       }
 
       #message {
diff --git a/chrome/browser/resources/md_user_manager/shared_styles.html b/chrome/browser/resources/md_user_manager/shared_styles.html
index 6291983..bd8feb6 100644
--- a/chrome/browser/resources/md_user_manager/shared_styles.html
+++ b/chrome/browser/resources/md_user_manager/shared_styles.html
@@ -1,3 +1,4 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
@@ -7,7 +8,6 @@
       :root {
         --error-color: var(--google-red-700);
         --page-width: 624px;
-        --primary-text-color: var(--google-grey-900);
         --title-icon-color: var(--paper-grey-500);
         --user-manager-separator-line: 1px solid rgba(0, 0, 0, .12);
       }
diff --git a/chrome/browser/resources/md_user_manager/user_manager.html b/chrome/browser/resources/md_user_manager/user_manager.html
index b069169..9b375fb 100644
--- a/chrome/browser/resources/md_user_manager/user_manager.html
+++ b/chrome/browser/resources/md_user_manager/user_manager.html
@@ -87,7 +87,7 @@
     .pod {
       @apply --cr-card-elevation;
       border-radius: var(--cr-card-border-radius);
-      color: var(--primary-text-color);
+      color: var(--cr-primary-text-color);
       cursor: default;
       height: auto;
       transform: none;
@@ -133,7 +133,6 @@
 
     .pod .main-pane .name-container .name,
     .reauth-hint-container .reauth-name-hint {
-      color: inherit;
       font-size: inherit;
       margin: 0;
       padding: 0;
@@ -282,8 +281,12 @@
       height: auto;
     }
 
+    .action-box-menu-title-name {
+      color: var(--cr-primary-text-color);
+    }
+
     .action-box-menu-title-email {
-      color: var(--paper-grey-600);
+      color: var(--cr-secondary-text-color);
     }
 
     .action-box-menu-remove {
diff --git a/chrome/browser/resources/md_user_manager/user_manager_tutorial.html b/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
index 1b380431..c6b4913 100644
--- a/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
+++ b/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
@@ -63,7 +63,7 @@
       }
 
       .slide-contents {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         padding: 0 20px;
         text-align: center;
       }
diff --git a/chrome/browser/resources/pdf/elements/shared-vars.html b/chrome/browser/resources/pdf/elements/shared-vars.html
index da5f14a..2ba13040 100644
--- a/chrome/browser/resources/pdf/elements/shared-vars.html
+++ b/chrome/browser/resources/pdf/elements/shared-vars.html
@@ -5,7 +5,6 @@
 <custom-style>
 <style is="custom-style">
   html {
-    --primary-text-color: var(--google-grey-900);
     --iron-icon-height: 20px;
     --iron-icon-width: 20px;
     --paper-icon-button: {
diff --git a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
index 95d7588..c042447 100644
--- a/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
+++ b/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
@@ -1,7 +1,9 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <dom-module id="viewer-toolbar-dropdown">
   <template>
@@ -29,7 +31,7 @@
         @apply --shadow-elevation-2dp;
         background-color: rgb(256, 256, 256);
         border-radius: 4px;
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         overflow-y: hidden;
         padding-bottom: 2px;
         width: 260px;
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index ce73eea..b189a1b 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -20,7 +20,7 @@
       h2 {
         align-items: center;
         align-self: flex-start;
-        color: var(--google-grey-700);
+        color: var(--google-grey-refresh-700);
         display: flex;
         font-size: inherit;
         font-weight: 500;
@@ -326,7 +326,7 @@
       }
 
       .column-header {
-        color: var(--google-grey-700);
+        color: var(--google-grey-refresh-700);
         font-size: inherit;
         font-weight: 400;
       }
diff --git a/chrome/browser/resources/settings/settings_vars_css.html b/chrome/browser/resources/settings/settings_vars_css.html
index 08ace9e..f967fea 100644
--- a/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -1,6 +1,5 @@
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 
 <!-- Common css variables for Material Design settings. -->
 <custom-style>
@@ -29,7 +28,7 @@
       padding-top: 0;
     }
 
-    --settings-nav-grey: rgb(90, 90, 90);
+    --settings-nav-grey: var(--google-grey-refresh-700);
 
     --settings-page-vertical-margin: 21px;
 
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
index bb5bb09..b837fdd 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service_android.cc
@@ -21,7 +21,7 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaParamRef;
 using base::android::JavaRef;
-using base::android::RunCallbackAndroid;
+using base::android::RunBooleanCallbackAndroid;
 using base::android::ScopedJavaGlobalRef;
 
 void JNI_ChildAccountService_ListenForChildStatusReceived(
@@ -31,10 +31,9 @@
   ProfileManager* profile_manager = g_browser_process->profile_manager();
   ChildAccountService* service = ChildAccountServiceFactory::GetForProfile(
       profile_manager->GetLastUsedProfile());
-  // Needed to disambiguate RunCallbackAndroid
-  void (*runCallback)(const JavaRef<jobject>&, bool) = &RunCallbackAndroid;
-  service->AddChildStatusReceivedCallback(base::BindOnce(
-      runCallback, ScopedJavaGlobalRef<jobject>(callback), true));
+  service->AddChildStatusReceivedCallback(
+      base::BindOnce(&RunBooleanCallbackAndroid,
+                     ScopedJavaGlobalRef<jobject>(callback), true));
 }
 
 void ReauthenticateChildAccount(content::WebContents* web_contents,
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
index f35f89d..228bee6 100644
--- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -245,6 +245,48 @@
 }
 
 IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTestIncludingUssTests,
+                       CommitLocalCreations) {
+  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+  // Starting state:
+  // other_node
+  //    -> top
+  //      -> tier1_a
+  //        -> http://mail.google.com  "tier1_a_url0"
+  //        -> http://www.pandora.com  "tier1_a_url1"
+  //        -> http://www.facebook.com "tier1_a_url2"
+  //      -> tier1_b
+  //        -> http://www.nhl.com "tier1_b_url0"
+  const BookmarkNode* top = AddFolder(
+      kSingleProfileIndex, GetOtherNode(kSingleProfileIndex), 0, "top");
+  const BookmarkNode* tier1_a =
+      AddFolder(kSingleProfileIndex, top, 0, "tier1_a");
+  const BookmarkNode* tier1_b =
+      AddFolder(kSingleProfileIndex, top, 1, "tier1_b");
+  const BookmarkNode* tier1_a_url0 =
+      AddURL(kSingleProfileIndex, tier1_a, 0, "tier1_a_url0",
+             GURL("http://mail.google.com"));
+  const BookmarkNode* tier1_a_url1 =
+      AddURL(kSingleProfileIndex, tier1_a, 1, "tier1_a_url1",
+             GURL("http://www.pandora.com"));
+  const BookmarkNode* tier1_a_url2 =
+      AddURL(kSingleProfileIndex, tier1_a, 2, "tier1_a_url2",
+             GURL("http://www.facebook.com"));
+  const BookmarkNode* tier1_b_url0 =
+      AddURL(kSingleProfileIndex, tier1_b, 0, "tier1_b_url0",
+             GURL("http://www.nhl.com"));
+  EXPECT_TRUE(tier1_a_url0);
+  EXPECT_TRUE(tier1_a_url1);
+  EXPECT_TRUE(tier1_a_url2);
+  EXPECT_TRUE(tier1_b_url0);
+  // Setup sync, wait for its completion, and make sure changes were synced.
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+  ASSERT_TRUE(
+      UpdatedProgressMarkerChecker(GetSyncService(kSingleProfileIndex)).Wait());
+  EXPECT_TRUE(ModelMatchesVerifier(kSingleProfileIndex));
+}
+
+IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTestIncludingUssTests,
                        InjectedBookmark) {
   std::string title = "Montreal Canadiens";
   fake_server::EntityBuilderFactory entity_builder_factory;
diff --git a/chrome/browser/task_manager/test_task_manager.cc b/chrome/browser/task_manager/test_task_manager.cc
index b12d21f..6fe031a 100644
--- a/chrome/browser/task_manager/test_task_manager.cc
+++ b/chrome/browser/task_manager/test_task_manager.cc
@@ -9,8 +9,7 @@
 TestTaskManager::TestTaskManager()
     : handle_(base::kNullProcessHandle),
       pid_(base::kNullProcessId) {
-  set_timer_for_testing(
-      std::unique_ptr<base::Timer>(new base::MockTimer(true, true)));
+  set_timer_for_testing(std::make_unique<base::MockRepeatingTimer>());
 }
 
 TestTaskManager::~TestTaskManager() {
diff --git a/chrome/browser/ui/android/context_menu_helper.cc b/chrome/browser/ui/android/context_menu_helper.cc
index 07855448..c1c8dab 100644
--- a/chrome/browser/ui/android/context_menu_helper.cc
+++ b/chrome/browser/ui/android/context_menu_helper.cc
@@ -6,7 +6,7 @@
 
 #include <stdint.h>
 
-#include <vector>
+#include <map>
 
 #include "base/android/callback_android.h"
 #include "base/android/jni_string.h"
@@ -51,14 +51,14 @@
 
  protected:
   void OnImageDecoded(const SkBitmap& decoded_image) override {
-    base::android::RunCallbackAndroid(jcallback_,
-                                      gfx::ConvertToJavaBitmap(&decoded_image));
+    base::android::RunObjectCallbackAndroid(
+        jcallback_, gfx::ConvertToJavaBitmap(&decoded_image));
     delete this;
   }
 
   void OnDecodeImageFailed() override {
     base::android::ScopedJavaLocalRef<jobject> j_bitmap;
-    base::android::RunCallbackAndroid(jcallback_, j_bitmap);
+    base::android::RunObjectCallbackAndroid(jcallback_, j_bitmap);
     delete this;
   }
 
@@ -77,7 +77,7 @@
     const base::android::JavaRef<jobject>& jcallback,
     const std::vector<uint8_t>& thumbnail_data,
     const gfx::Size& original_size) {
-  base::android::RunCallbackAndroid(jcallback, thumbnail_data);
+  base::android::RunByteArrayCallbackAndroid(jcallback, thumbnail_data);
 }
 
 void OnRetrieveImageForContextMenu(
@@ -94,7 +94,7 @@
     : web_contents_(web_contents) {
   JNIEnv* env = base::android::AttachCurrentThread();
   java_obj_.Reset(
-      env, Java_ContextMenuHelper_create(env, reinterpret_cast<long>(this),
+      env, Java_ContextMenuHelper_create(env, reinterpret_cast<int64_t>(this),
                                          web_contents_->GetJavaWebContents())
                .obj());
   DCHECK(!java_obj_.is_null());
diff --git a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc
index ec6ac58..5654f87 100644
--- a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc
+++ b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc
@@ -80,7 +80,7 @@
   ASSERT_TRUE(extension);
   extensions::ScriptingPermissionsModifier(profile(),
                                            base::WrapRefCounted(extension))
-      .SetWithholdAllUrls(true);
+      .SetWithholdHostPermissions(true);
 
   content::WebContents* tab =
       browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
index c73c1ea..28b2981 100644
--- a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
+++ b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
@@ -693,7 +693,7 @@
     extension_ = LoadExtension(extension_dir_.UnpackedPath());
     ASSERT_TRUE(extension_);
     extensions::ScriptingPermissionsModifier(profile(), extension_)
-        .SetWithholdAllUrls(true);
+        .SetWithholdHostPermissions(true);
   }
 
   const extensions::Extension* extension() const { return extension_.get(); }
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
index 394f565..e162057 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
 #include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
 #include "chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h"
-#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/browser/suggestion.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -20,7 +20,6 @@
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/test/event_generator.h"
-#include "ui/views/test/views_test_base.h"
 
 namespace {
 
@@ -112,18 +111,13 @@
   std::vector<autofill::Suggestion> suggestions_;
 };
 
-class AutofillPopupViewNativeViewsTest : public views::ViewsTestBase {
+class AutofillPopupViewNativeViewsTest : public ChromeViewsTestBase {
  public:
   AutofillPopupViewNativeViewsTest() = default;
   ~AutofillPopupViewNativeViewsTest() override = default;
 
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
-
-    // The layout provider is meant to be a singleton, but it is not initialized
-    // for unit tests. Constructing one here makes it globally available, which
-    // is later used by the view during initialization.
-    layout_provider_ = std::make_unique<ChromeLayoutProvider>();
+    ChromeViewsTestBase::SetUp();
 
     CreateWidget();
     generator_.reset(new ui::test::EventGenerator(widget_.GetNativeWindow()));
@@ -134,7 +128,7 @@
     if (!widget_.IsClosed())
       widget_.Close();
     view_.reset();
-    views::ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
   void CreateAndShowView(const std::vector<int>& ids) {
@@ -163,7 +157,6 @@
   std::unique_ptr<ui::test::EventGenerator> generator_;
 
  private:
-  std::unique_ptr<ChromeLayoutProvider> layout_provider_;
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewNativeViewsTest);
 };
 
diff --git a/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc b/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc
index fd649db..c925fad 100644
--- a/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc
+++ b/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc
@@ -73,8 +73,7 @@
   void SetUp() override {
     std::unique_ptr<TestConfirmQuitBubble> bubble =
         std::make_unique<TestConfirmQuitBubble>();
-    std::unique_ptr<base::MockTimer> timer =
-        std::make_unique<base::MockTimer>(false, false);
+    auto timer = std::make_unique<base::MockOneShotTimer>();
     bubble_ = bubble.get();
     timer_ = timer.get();
     controller_.reset(new TestConfirmQuitBubbleController(
@@ -112,7 +111,9 @@
   TestConfirmQuitBubble* bubble_;
 
   // Owned by |controller_|.
-  base::MockTimer* timer_;
+  base::MockOneShotTimer* timer_;
+
+  bool quit_called_ = false;
 };
 
 // Pressing and holding the shortcut should quit.
diff --git a/chrome/browser/ui/views/download/download_item_view_unittest.cc b/chrome/browser/ui/views/download/download_item_view_unittest.cc
index 1f17176..fff7f40 100644
--- a/chrome/browser/ui/views/download/download_item_view_unittest.cc
+++ b/chrome/browser/ui/views/download/download_item_view_unittest.cc
@@ -5,11 +5,11 @@
 #include "chrome/browser/ui/views/download/download_item_view.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/test/views_test_base.h"
 
-using DownloadItemViewDangerousDownloadLabelTest = views::ViewsTestBase;
+using DownloadItemViewDangerousDownloadLabelTest = ChromeViewsTestBase;
 
 TEST_F(DownloadItemViewDangerousDownloadLabelTest, AdjustTextAndGetSize) {
   // For very short label that can fit in a single line, no need to do any
diff --git a/chrome/browser/ui/views/frame/browser_frame_ash.h b/chrome/browser/ui/views/frame/browser_frame_ash.h
index 687010e1..fa2a308 100644
--- a/chrome/browser/ui/views/frame/browser_frame_ash.h
+++ b/chrome/browser/ui/views/frame/browser_frame_ash.h
@@ -19,11 +19,6 @@
  public:
   BrowserFrameAsh(BrowserFrame* browser_frame, BrowserView* browser_view);
 
-  // The color used for the frame when showing a non-tabbed WebUI, such as
-  // the Settings window.
-  static constexpr SkColor kMdWebUiFrameColor =
-      SkColorSetARGB(0xff, 0x25, 0x4f, 0xae);
-
  protected:
   ~BrowserFrameAsh() override;
 
diff --git a/chrome/browser/ui/views/frame/browser_frame_mash.cc b/chrome/browser/ui/views/frame/browser_frame_mash.cc
index a742b6a7..d29d2ef 100644
--- a/chrome/browser/ui/views/frame/browser_frame_mash.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_mash.cc
@@ -75,15 +75,6 @@
   properties[ash::mojom::kCanConsumeSystemKeys_Property] =
       mojo::ConvertTo<std::vector<uint8_t>>(
           static_cast<int64_t>(browser->is_app()));
-  // Set the frame color for WebUI windows, e.g. settings.
-  if (!browser->is_type_tabbed() && browser->is_trusted_source()) {
-    properties[ui::mojom::WindowManager::kFrameActiveColor_Property] =
-        mojo::ConvertTo<std::vector<uint8_t>>(
-            static_cast<int64_t>(BrowserFrameAsh::kMdWebUiFrameColor));
-    properties[ui::mojom::WindowManager::kFrameInactiveColor_Property] =
-        mojo::ConvertTo<std::vector<uint8_t>>(
-            static_cast<int64_t>(BrowserFrameAsh::kMdWebUiFrameColor));
-  }
 
   aura::WindowTreeHostMusInitParams window_tree_host_init_params =
       aura::CreateInitParamsForTopLevel(
diff --git a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
index b19334b..976f809 100644
--- a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
@@ -15,19 +15,13 @@
 
 @interface NSWindow (PrivateAPI)
 + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
-
-// Available in later point releases of 10.10. On 10.11+, use the public
-// -performWindowDragWithEvent: instead.
-- (void)beginWindowDragWithEvent:(NSEvent*)event;
 @end
 
-// Weak lets Chrome launch even if a future macOS doesn't have NSThemeFrame.
-WEAK_IMPORT_ATTRIBUTE
-@interface NSThemeFrame : NSView
+@interface NSThemeFrame (PrivateAPI)
 - (CGFloat)_titlebarHeight;
 @end
 
-@interface BrowserWindowFrame : NSThemeFrame
+@interface BrowserWindowFrame : NativeWidgetMacNSWindowTitledFrame
 @end
 
 @implementation BrowserWindowFrame
@@ -78,20 +72,6 @@
   return NSZeroRect;
 }
 
-// Lets the window be dragged by its title bar on 10.11 and older.
-- (void)mouseDown:(NSEvent*)event {
-  if (@available(macOS 10.12, *))
-    ;  // Not needed on 10.12 and up.
-  else if (@available(macOS 10.11, *))
-    [self.window performWindowDragWithEvent:event];
-  else if ([self.window
-               respondsToSelector:@selector(beginWindowDragWithEvent:)])
-    [self.window beginWindowDragWithEvent:event];
-  else
-    NOTREACHED();
-  [super mouseDown:event];
-}
-
 @end
 
 @implementation BrowserNativeWidgetWindow
@@ -107,13 +87,6 @@
   return [super frameViewClassForStyleMask:windowStyle];
 }
 
-// The base implementation returns YES if the window's frame view is a custom
-// class, which causes undesirable changes in behavior. AppKit NSWindow
-// subclasses are known to override it and return NO.
-- (BOOL)_usesCustomDrawing {
-  return NO;
-}
-
 // Handle "Move focus to the window toolbar" configured in System Preferences ->
 // Keyboard -> Shortcuts -> Keyboard. Usually Ctrl+F5. The argument (|unknown|)
 // tends to just be nil.
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index e8c24f2..43cbfebb 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
-#include "chrome/browser/ui/views/frame/browser_frame_ash.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/hosted_app_button_container.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
@@ -61,6 +60,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
 #include "ui/views/mus/desktop_window_tree_host_mus.h"
 #include "ui/views/mus/window_manager_frame_values.h"
 #include "ui/views/rect_based_targeting_utils.h"
@@ -69,6 +69,10 @@
 
 namespace {
 
+// The color used for the frame when showing a non-tabbed WebUI, such as
+// the Settings window.
+constexpr SkColor kMdWebUiFrameColor = SkColorSetARGB(0xff, 0x25, 0x4f, 0xae);
+
 bool IsMash() {
   return !features::IsAshInBrowserProcess();
 }
@@ -113,6 +117,14 @@
   return views::WindowManagerFrameValues::instance();
 }
 
+// TODO(estade): This is copied from ash::FrameCaptionButton. De-dupe.
+int GetControlButtonSpacing() {
+  constexpr int kTouchOptimizedCaptionButtonsSpacing = 8;
+  return ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
+             ? kTouchOptimizedCaptionButtonsSpacing
+             : 0;
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -175,6 +187,13 @@
     AddChildView(caption_button_container_);
   }
 
+  Browser* browser = browser_view()->browser();
+  if (IsMash() &&
+      extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser(
+          browser_view()->browser())) {
+    SetUpForHostedApp(nullptr);
+  }
+
   // Initializing the TabIconView is expensive, so only do it if we need to.
   if (browser_view()->ShouldShowWindowIcon()) {
     window_icon_ = new TabIconView(this, nullptr);
@@ -183,7 +202,6 @@
     window_icon_->Update();
   }
 
-  Browser* browser = browser_view()->browser();
   if (browser->is_app() && IsV1AppBackButtonEnabled())
     browser->command_controller()->AddCommandObserver(IDC_BACK, this);
 
@@ -340,11 +358,20 @@
         tab_strip_bounds.Intersect(GetLocalBounds());
         new_tab_button_bounds.Intersect(GetLocalBounds());
       }
+
       additional_client_area.push_back(tab_strip_bounds);
+
       if (!new_tab_button_bounds.IsEmpty())
         additional_client_area.push_back(new_tab_button_bounds);
     }
   }
+
+  if (hosted_app_button_container_) {
+    gfx::Rect bounds = hosted_app_button_container_->ConvertRectToWidget(
+        hosted_app_button_container_->GetLocalBounds());
+    additional_client_area.push_back(bounds);
+  }
+
   aura::WindowTreeHostMus* window_tree_host_mus =
       static_cast<aura::WindowTreeHostMus*>(
           GetWidget()->GetNativeWindow()->GetHost());
@@ -418,7 +445,6 @@
 
 int BrowserNonClientFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
   if (hosted_app_button_container_) {
-    DCHECK(!IsMash());
     gfx::Point client_point(point);
     View::ConvertPointToTarget(this, hosted_app_button_container_,
                                &client_point);
@@ -453,11 +479,11 @@
 }
 
 void BrowserNonClientFrameViewAsh::ResetWindowControls() {
-  if (IsMash())
-    return;
+  if (!IsMash()) {
+    caption_button_container_->SetVisible(true);
+    caption_button_container_->ResetWindowControls();
+  }
 
-  caption_button_container_->SetVisible(true);
-  caption_button_container_->ResetWindowControls();
   if (hosted_app_button_container_)
     hosted_app_button_container_->RefreshContentSettingViews();
 }
@@ -477,11 +503,10 @@
 void BrowserNonClientFrameViewAsh::ActivationChanged(bool active) {
   BrowserNonClientFrameView::ActivationChanged(active);
 
-  if (IsMash())
-    return;
-
   const bool should_paint_as_active = ShouldPaintAsActive();
-  frame_header_->SetPaintAsActive(should_paint_as_active);
+
+  if (!IsMash())
+    frame_header_->SetPaintAsActive(should_paint_as_active);
 
   if (hosted_app_button_container_)
     hosted_app_button_container_->SetPaintAsActive(should_paint_as_active);
@@ -517,6 +542,20 @@
     if (profile_indicator_icon())
       LayoutIncognitoButton();
 
+    if (hosted_app_extras_container_) {
+      // TODO(estade): can Ash tell us the bounds of the caption buttons so
+      // Chrome doesn't have to re-calculate them?
+      gfx::Size hosted_app_size =
+          hosted_app_extras_container_->GetPreferredSize();
+      gfx::Size caption_button_size =
+          GetAshLayoutSize(ash::AshLayoutSize::kNonBrowserCaption);
+      hosted_app_extras_container_->SetBounds(
+          width() -
+              (GetControlButtonSpacing() + caption_button_size.width()) * 3 -
+              hosted_app_size.width(),
+          0, hosted_app_size.width(), caption_button_size.height());
+    }
+
     BrowserNonClientFrameView::Layout();
 
     UpdateClientArea();
@@ -623,8 +662,27 @@
   inactive_frame_overlay_image_registration_ = update_window_image(
       ash::kFrameImageOverlayInactiveKey, GetFrameOverlayImage(false));
 
-  window->SetProperty(ash::kFrameActiveColorKey, GetFrameColor(true));
-  window->SetProperty(ash::kFrameInactiveColorKey, GetFrameColor(false));
+  base::Optional<SkColor> active_color, inactive_color;
+  if (!UsePackagedAppHeaderStyle(browser_view()->browser())) {
+    active_color = GetFrameColor(true);
+    inactive_color = GetFrameColor(false);
+  } else if (extensions::HostedAppBrowserController::
+                 IsForExperimentalHostedAppBrowser(browser_view()->browser())) {
+    base::Optional<SkColor> theme_color =
+        browser_view()->browser()->hosted_app_controller()->GetThemeColor();
+    window->SetProperty(ash::kFrameIsThemedByHostedAppKey, !!theme_color);
+
+    if (theme_color)
+      active_color = SkColorSetA(*theme_color, SK_AlphaOPAQUE);
+  } else {
+    active_color = kMdWebUiFrameColor;
+  }
+
+  if (active_color) {
+    window->SetProperty(ash::kFrameActiveColorKey, *active_color);
+    window->SetProperty(ash::kFrameInactiveColorKey,
+                        inactive_color.value_or(*active_color));
+  }
 
   BrowserNonClientFrameView::OnThemeChanged();
 }
@@ -926,60 +984,20 @@
   DCHECK(!IsMash());
 
   std::unique_ptr<ash::FrameHeader> header;
-
   Browser* browser = browser_view()->browser();
   if (!UsePackagedAppHeaderStyle(browser)) {
     header = std::make_unique<ash::CustomFrameHeader>(
         frame(), this, this, !browser_view()->IsRegularOrGuestSession(),
         caption_button_container_);
   } else {
-    std::unique_ptr<ash::DefaultFrameHeader> default_frame_header =
-        std::make_unique<ash::DefaultFrameHeader>(frame(), this,
-                                                  caption_button_container_);
-    // TODO(alancutter): Move this branch into a new HostedAppFrameHeader class.
+    auto default_frame_header = std::make_unique<ash::DefaultFrameHeader>(
+        frame(), this, caption_button_container_);
     if (extensions::HostedAppBrowserController::
             IsForExperimentalHostedAppBrowser(browser)) {
-      SkColor active_color = ash::FrameCaptionButton::GetButtonColor(
-          ash::FrameCaptionButton::ColorMode::kDefault,
-          ash::kDefaultFrameColor);
-
-      // Hosted apps apply a theme color if specified by the extension.
-      base::Optional<SkColor> theme_color =
-          browser->hosted_app_controller()->GetThemeColor();
-      if (theme_color) {
-        theme_color = SkColorSetA(theme_color.value(), SK_AlphaOPAQUE);
-        default_frame_header->SetThemeColor(*theme_color);
-        active_color = ash::FrameCaptionButton::GetButtonColor(
-            ash::FrameCaptionButton::ColorMode::kThemed, *theme_color);
-      }
-
-      // Add the container for extra hosted app buttons (e.g app menu button).
-      const float inactive_alpha_ratio =
-          ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
-      SkColor inactive_color =
-          SkColorSetA(active_color, 255 * inactive_alpha_ratio);
-      hosted_app_button_container_ = new HostedAppButtonContainer(
-          browser_view(), active_color, inactive_color);
-      caption_button_container_->AddChildViewAt(hosted_app_button_container_,
-                                                0);
-
-      // Add the origin text.
-      frame_header_origin_text_ =
-          std::make_unique<ash::FrameHeaderOriginText>(
-              browser->hosted_app_controller()->GetFormattedUrlOrigin(),
-              active_color, inactive_color)
-              .release();
-      AddChildView(frame_header_origin_text_);
-
-      // Schedule the title bar animation.
-      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE,
-          base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation,
-                         weak_factory_.GetWeakPtr()),
-          kTitlebarAnimationDelay);
+      SetUpForHostedApp(default_frame_header.get());
     } else if (!browser->is_app()) {
-      default_frame_header->SetFrameColors(BrowserFrameAsh::kMdWebUiFrameColor,
-                                           BrowserFrameAsh::kMdWebUiFrameColor);
+      default_frame_header->SetFrameColors(kMdWebUiFrameColor,
+                                           kMdWebUiFrameColor);
     }
     header = std::move(default_frame_header);
   }
@@ -989,8 +1007,70 @@
   return header;
 }
 
+void BrowserNonClientFrameViewAsh::SetUpForHostedApp(
+    ash::DefaultFrameHeader* header) {
+  SkColor active_color = ash::FrameCaptionButton::GetButtonColor(
+      ash::FrameCaptionButton::ColorMode::kDefault, ash::kDefaultFrameColor);
+
+  // Hosted apps apply a theme color if specified by the extension.
+  Browser* browser = browser_view()->browser();
+  base::Optional<SkColor> theme_color =
+      browser->hosted_app_controller()->GetThemeColor();
+  if (theme_color) {
+    theme_color = SkColorSetA(*theme_color, SK_AlphaOPAQUE);
+
+    // Not necessary in Mash as the frame colors are set in OnThemeChanged().
+    if (!IsMash()) {
+      frame()->GetNativeWindow()->SetProperty(
+          ash::kFrameIsThemedByHostedAppKey,
+          !!browser->hosted_app_controller()->GetThemeColor());
+      header->SetFrameColors(*theme_color, *theme_color);
+    }
+
+    active_color = ash::FrameCaptionButton::GetButtonColor(
+        ash::FrameCaptionButton::ColorMode::kThemed, *theme_color);
+  }
+
+  // Add the container for extra hosted app buttons (e.g app menu button).
+  const float inactive_alpha_ratio =
+      ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
+  SkColor inactive_color =
+      SkColorSetA(active_color, 255 * inactive_alpha_ratio);
+  hosted_app_button_container_ = new HostedAppButtonContainer(
+      browser_view(), active_color, inactive_color);
+
+  // Add the origin text.
+  frame_header_origin_text_ = new ash::FrameHeaderOriginText(
+      browser->hosted_app_controller()->GetFormattedUrlOrigin(), active_color,
+      inactive_color);
+
+  if (IsMash()) {
+    hosted_app_extras_container_ = new views::View();
+    auto layout = std::make_unique<views::BoxLayout>(
+        views::BoxLayout::kHorizontal, gfx::Insets(),
+        GetControlButtonSpacing());
+    layout->set_cross_axis_alignment(
+        views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
+    layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_END);
+    hosted_app_extras_container_->SetLayoutManager(std::move(layout));
+    AddChildView(hosted_app_extras_container_);
+
+    hosted_app_extras_container_->AddChildView(frame_header_origin_text_);
+    hosted_app_extras_container_->AddChildView(hosted_app_button_container_);
+  } else {
+    caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0);
+    AddChildView(frame_header_origin_text_);
+  }
+
+  // Schedule the title bar animation.
+  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation,
+                     weak_factory_.GetWeakPtr()),
+      kTitlebarAnimationDelay);
+}
+
 void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() {
-  DCHECK(!IsMash());
   frame_header_origin_text_->StartSlideAnimation();
   hosted_app_button_container_->StartTitlebarAnimation(
       frame_header_origin_text_->AnimationDuration());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index fd40610..75caf98c 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -31,6 +31,7 @@
 class TabIconView;
 
 namespace ash {
+class DefaultFrameHeader;
 class FrameCaptionButton;
 class FrameCaptionButtonContainerView;
 class FrameHeaderOriginText;
@@ -187,6 +188,10 @@
   // Creates the frame header for the browser window.
   std::unique_ptr<ash::FrameHeader> CreateFrameHeader();
 
+  // Creates views and does other setup for a hosted app.
+  // TODO(estade): remove the parameter as it's unused in Mash.
+  void SetUpForHostedApp(ash::DefaultFrameHeader* header);
+
   // Triggers the hosted app origin and icon animations, assumes the hosted
   // app UI elements exist.
   void StartHostedAppAnimation();
@@ -210,6 +215,11 @@
   // Owned by views hierarchy.
   ash::FrameHeaderOriginText* frame_header_origin_text_ = nullptr;
 
+  // A view that contains the extra views used for hosted apps
+  // (|hosted_app_button_container_| and |frame_header_origin_text_|).
+  // Only used in Mash.
+  views::View* hosted_app_extras_container_ = nullptr;
+
   // Ash's mojom::SplitViewController.
   ash::mojom::SplitViewControllerPtr split_view_controller_;
 
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc
index 8ded202..76bd9b6 100644
--- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc
@@ -9,9 +9,9 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/nav_button_provider.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/image_button.h"
-#include "ui/views/test/views_test_base.h"
 
 namespace {
 
@@ -132,13 +132,13 @@
 
 }  // namespace
 
-class DesktopLinuxBrowserFrameViewLayoutTest : public views::ViewsTestBase {
+class DesktopLinuxBrowserFrameViewLayoutTest : public ChromeViewsTestBase {
  public:
   DesktopLinuxBrowserFrameViewLayoutTest() {}
   ~DesktopLinuxBrowserFrameViewLayoutTest() override {}
 
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
+    ChromeViewsTestBase::SetUp();
 
     delegate_.reset(new TestLayoutDelegate);
     nav_button_provider_ = std::make_unique<::TestNavButtonProvider>();
@@ -162,7 +162,7 @@
   void TearDown() override {
     widget_->CloseNow();
 
-    views::ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
  protected:
diff --git a/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.mm b/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.mm
index 11cfc59..577b47d 100644
--- a/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.mm
+++ b/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.mm
@@ -6,31 +6,13 @@
 
 @interface NSWindow (PrivateAPI)
 + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
-- (void)beginWindowDragWithEvent:(NSEvent*)event
-    NS_DEPRECATED_MAC(10_10, 10_11, "Use performWindowDragWithEvent: instead.");
 @end
 
-// Weak lets Chrome launch even if a future macOS doesn't have NSThemeFrame.
-WEAK_IMPORT_ATTRIBUTE
-@interface NSThemeFrame : NSView
-@end
-
-@interface NativeWidgetMacFramelessNSWindowFrame : NSThemeFrame
+@interface NativeWidgetMacFramelessNSWindowFrame
+    : NativeWidgetMacNSWindowTitledFrame
 @end
 
 @implementation NativeWidgetMacFramelessNSWindowFrame
-
-// If a mouseDown: falls through to the frame view, turn it into a window drag.
-- (void)mouseDown:(NSEvent*)event {
-  if (@available(macOS 10.11, *))
-    [self.window performWindowDragWithEvent:event];
-  else if (@available(macOS 10.10, *))
-    [self.window beginWindowDragWithEvent:event];
-  else
-    NOTREACHED();
-  [super mouseDown:event];
-}
-
 - (BOOL)_hidingTitlebar {
   return YES;
 }
@@ -45,8 +27,4 @@
   return [super frameViewClassForStyleMask:windowStyle];
 }
 
-- (BOOL)_usesCustomDrawing {
-  return NO;
-}
-
 @end
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index 8a7ecf1..bca0d03 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
 #include "chrome/browser/ui/views/tab_icon_view.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "components/signin/core/browser/profile_management_switches.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/image/image_skia.h"
@@ -19,7 +20,6 @@
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/test/views_test_base.h"
 
 namespace {
 
@@ -88,13 +88,13 @@
 
 }  // namespace
 
-class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase {
+class OpaqueBrowserFrameViewLayoutTest : public ChromeViewsTestBase {
  public:
   OpaqueBrowserFrameViewLayoutTest() {}
   ~OpaqueBrowserFrameViewLayoutTest() override {}
 
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
+    ChromeViewsTestBase::SetUp();
 
     delegate_.reset(new TestLayoutDelegate);
     auto layout = std::make_unique<OpaqueBrowserFrameViewLayout>();
@@ -131,7 +131,7 @@
   void TearDown() override {
     widget_->CloseNow();
 
-    views::ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
  protected:
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
index c9ea4e6..c36397032 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
@@ -14,7 +15,6 @@
 #include "ui/views/animation/test/ink_drop_host_view_test_api.h"
 #include "ui/views/animation/test/test_ink_drop.h"
 #include "ui/views/controls/image_view.h"
-#include "ui/views/test/views_test_base.h"
 
 #if defined(OS_CHROMEOS)
 #include "ui/aura/window.h"
@@ -118,24 +118,11 @@
 
 }  // namespace
 
-class IconLabelBubbleViewTest : public views::ViewsTestBase {
- public:
-  IconLabelBubbleViewTest()
-      : views::ViewsTestBase(),
-        widget_(nullptr),
-        view_(nullptr),
-        ink_drop_(nullptr),
-        steady_reached_(false),
-        shrinking_reached_(false),
-        minimum_size_reached_(false),
-        previous_width_(0),
-        initial_image_x_(0) {}
-  ~IconLabelBubbleViewTest() override {}
-
+class IconLabelBubbleViewTest : public ChromeViewsTestBase {
  protected:
-  // views::ViewsTestBase:
+  // ChromeViewsTestBase:
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
+    ChromeViewsTestBase::SetUp();
     gfx::FontList font_list;
 
     CreateWidget();
@@ -152,7 +139,7 @@
     if (widget_ && !widget_->IsClosed())
       widget_->Close();
 
-    ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
   void VerifyWithAnimationStep(int step) {
@@ -265,16 +252,16 @@
     return view_->GetImageView()->bounds();
   }
 
-  views::Widget* widget_;
-  TestIconLabelBubbleView* view_;
-  TestInkDrop* ink_drop_;
+  views::Widget* widget_ = nullptr;
+  TestIconLabelBubbleView* view_ = nullptr;
+  TestInkDrop* ink_drop_ = nullptr;
   std::unique_ptr<ui::test::EventGenerator> generator_;
 
-  bool steady_reached_;
-  bool shrinking_reached_;
-  bool minimum_size_reached_;
-  int previous_width_;
-  int initial_image_x_;
+  bool steady_reached_ = false;
+  bool shrinking_reached_ = false;
+  bool minimum_size_reached_ = false;
+  int previous_width_ = 0;
+  int initial_image_x_ = 0;
 };
 
 // Tests layout rules for IconLabelBubbleView while simulating animation.
@@ -377,7 +364,7 @@
 #if defined(OS_CHROMEOS)
 // Verifies IconLabelBubbleView::CalculatePreferredSize() doesn't crash when
 // there is a widget but no compositor.
-using IconLabelBubbleViewCrashTest = views::ViewsTestBase;
+using IconLabelBubbleViewCrashTest = ChromeViewsTestBase;
 
 TEST_F(IconLabelBubbleViewCrashTest,
        GetPreferredSizeDoesntCrashWhenNoCompositor) {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index faa5a3b..87e128f 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -159,7 +159,7 @@
 
   // TODO(tommycli): This is a placeholder duration. Replace this with the real
   // value once UX decides.
-  text_indent_animation_.SetSlideDuration(200);
+  text_indent_animation_.SetSlideDuration(60);
 }
 
 LocationBarView::~LocationBarView() {
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
index 9413cb0..f4a10d69 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -4,7 +4,10 @@
 
 #include "chrome/browser/ui/views/media_router/cast_dialog_view.h"
 
+#include "base/location.h"
 #include "base/optional.h"
+#include "base/time/time.h"
+#include "chrome/browser/media/router/media_router_metrics.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/media_router/cast_dialog_controller.h"
 #include "chrome/browser/ui/media_router/cast_dialog_model.h"
@@ -15,6 +18,7 @@
 #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h"
 #include "chrome/common/media_router/media_sink.h"
 #include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
@@ -52,9 +56,11 @@
 // static
 void CastDialogView::ShowDialog(views::View* anchor_view,
                                 CastDialogController* controller,
-                                Browser* browser) {
+                                Browser* browser,
+                                const base::Time& start_time) {
   DCHECK(!instance_);
-  instance_ = new CastDialogView(anchor_view, controller, browser);
+  DCHECK(!start_time.is_null());
+  instance_ = new CastDialogView(anchor_view, controller, browser, start_time);
   views::Widget* widget =
       views::BubbleDialogDelegateView::CreateBubble(instance_);
   widget->Show();
@@ -125,6 +131,7 @@
     for (MediaCastMode cast_mode : {PRESENTATION, TAB_MIRROR, DESKTOP_MIRROR}) {
       if ((cast_mode & selected_source_) &&
           base::ContainsKey(sink.cast_modes, cast_mode)) {
+        MediaRouterMetrics::RecordStartRouteDeviceIndex(selected_sink_index_);
         controller_->StartCasting(sink.id, cast_mode);
         break;
       }
@@ -161,11 +168,14 @@
 
 CastDialogView::CastDialogView(views::View* anchor_view,
                                CastDialogController* controller,
-                               Browser* browser)
+                               Browser* browser,
+                               const base::Time& start_time)
     : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
       selected_source_(kTabSource),
       controller_(controller),
-      browser_(browser) {
+      browser_(browser),
+      start_time_(start_time),
+      weak_factory_(this) {
   ShowNoSinksView();
 }
 
@@ -200,6 +210,15 @@
   return gfx::Size(width, GetHeightForWidth(width));
 }
 
+void CastDialogView::OnPaint(gfx::Canvas* canvas) {
+  views::BubbleDialogDelegateView::OnPaint(canvas);
+  if (!start_time_.is_null()) {
+    MediaRouterMetrics::RecordMediaRouterDialogPaint(base::Time::Now() -
+                                                     start_time_);
+    start_time_ = base::Time();
+  }
+}
+
 void CastDialogView::Init() {
   auto* provider = ChromeLayoutProvider::Get();
   set_margins(
@@ -211,6 +230,7 @@
                   0));
   SetLayoutManager(std::make_unique<views::FillLayout>());
   controller_->AddObserver(this);
+  RecordSinkCountWithDelay();
 }
 
 void CastDialogView::WindowClosing() {
@@ -335,6 +355,20 @@
     SizeToContents();
 }
 
+void CastDialogView::RecordSinkCountWithDelay() {
+  // Record the number of sinks after three seconds. This is consistent with the
+  // WebUI dialog.
+  content::BrowserThread::PostDelayedTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&CastDialogView::RecordSinkCount,
+                     weak_factory_.GetWeakPtr()),
+      base::TimeDelta::FromSeconds(3));
+}
+
+void CastDialogView::RecordSinkCount() {
+  media_router::MediaRouterMetrics::RecordDeviceCount(sink_buttons_.size());
+}
+
 // static
 CastDialogView* CastDialogView::instance_ = nullptr;
 
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.h b/chrome/browser/ui/views/media_router/cast_dialog_view.h
index 97e1f1f..7a09abf0 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view.h
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/media_router/cast_dialog_controller.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/views/bubble/bubble_dialog_delegate.h"
@@ -16,6 +17,10 @@
 
 class Browser;
 
+namespace gfx {
+class Canvas;
+}  // namespace gfx
+
 namespace media_router {
 
 class CastDialogSinkButton;
@@ -33,7 +38,8 @@
   // currently shown.
   static void ShowDialog(views::View* anchor_view,
                          CastDialogController* controller,
-                         Browser* browser);
+                         Browser* browser,
+                         const base::Time& start_time);
 
   // No-op if the dialog is currently not shown.
   static void HideDialog();
@@ -68,6 +74,7 @@
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
+  void OnPaint(gfx::Canvas* canvas) override;
 
   // ui::SimpleMenuModel::Delegate:
   bool IsCommandIdChecked(int command_id) const override;
@@ -92,7 +99,8 @@
  private:
   CastDialogView(views::View* anchor_view,
                  CastDialogController* controller,
-                 Browser* browser);
+                 Browser* browser,
+                 const base::Time& start_time);
   ~CastDialogView() override;
 
   // views::BubbleDialogDelegateView:
@@ -120,6 +128,12 @@
 
   void MaybeSizeToContents();
 
+  // Posts a delayed task to record an UMA metric for the number of sinks shown.
+  void RecordSinkCountWithDelay();
+
+  // Records an UMA metric for the number of sinks shown.
+  void RecordSinkCount();
+
   // The singleton dialog instance. This is a nullptr when a dialog is not
   // shown.
   static CastDialogView* instance_;
@@ -159,6 +173,11 @@
   std::unique_ptr<ui::SimpleMenuModel> sources_menu_model_;
   std::unique_ptr<views::MenuRunner> sources_menu_runner_;
 
+  // The time when the dialog UI started initializing.
+  base::Time start_time_;
+
+  base::WeakPtrFactory<CastDialogView> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CastDialogView);
 };
 
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
index 7a9241c..aa593e9 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/media_router/cast_dialog_controller.h"
 #include "chrome/browser/ui/media_router/cast_dialog_model.h"
@@ -101,7 +102,7 @@
               dialog_ = static_cast<CastDialogView*>(observer);
             })));
     CastDialogView::ShowDialog(anchor_widget_->GetContentsView(), &controller_,
-                               nullptr);
+                               nullptr, base::Time::Now());
 
     dialog_->OnModelUpdated(model);
   }
@@ -148,7 +149,7 @@
 
   EXPECT_CALL(controller_, AddObserver(_));
   CastDialogView::ShowDialog(anchor_widget_->GetContentsView(), &controller_,
-                             nullptr);
+                             nullptr, base::Time::Now());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(CastDialogView::IsShowing());
   EXPECT_NE(nullptr, CastDialogView::GetCurrentDialogWidget());
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
index 296c702..2aa954f 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -75,6 +75,7 @@
 }
 
 void MediaRouterDialogControllerViews::CreateMediaRouterDialog() {
+  base::Time dialog_creation_time = base::Time::Now();
   MediaRouterDialogControllerImplBase::CreateMediaRouterDialog();
 
   ui_ = std::make_unique<MediaRouterViewsUI>();
@@ -93,7 +94,8 @@
   views::View* action_view = browser_actions->GetViewForId(
       ComponentToolbarActionsFactory::kMediaRouterActionId);
   CastDialogView::ShowDialog(action_view, ui_.get(),
-                             chrome::FindBrowserWithWebContents(initiator()));
+                             chrome::FindBrowserWithWebContents(initiator()),
+                             dialog_creation_time);
   CastDialogView::GetCurrentDialogWidget()->AddObserver(this);
 }
 
diff --git a/chrome/browser/ui/views/media_router/media_router_views_ui.cc b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
index d58bc61..9b054bd 100644
--- a/chrome/browser/ui/views/media_router/media_router_views_ui.cc
+++ b/chrome/browser/ui/views/media_router/media_router_views_ui.cc
@@ -7,8 +7,10 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/media/router/media_router_metrics.h"
 #include "chrome/browser/ui/media_router/media_sink_with_cast_modes.h"
 #include "chrome/browser/ui/media_router/ui_media_sink.h"
+#include "chrome/common/media_router/route_request_result.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
index 96dc8b0..53b073f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "chrome/browser/ui/omnibox/omnibox_theme.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/test_omnibox_client.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -17,7 +18,6 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/event_utils.h"
 #include "ui/gfx/image/image.h"
-#include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
@@ -49,10 +49,10 @@
 
 }  // namespace
 
-class OmniboxResultViewTest : public views::ViewsTestBase {
+class OmniboxResultViewTest : public ChromeViewsTestBase {
  public:
   void SetUp() override {
-    ViewsTestBase::SetUp();
+    ChromeViewsTestBase::SetUp();
 
     edit_model_ = std::make_unique<OmniboxEditModel>(
         nullptr, nullptr, std::make_unique<TestOmniboxClient>());
@@ -77,7 +77,7 @@
 
   void TearDown() override {
     widget_.reset();
-    views::ViewsTestBase::TearDown();
+    ChromeViewsTestBase::TearDown();
   }
 
   ui::MouseEvent CreateEvent(ui::EventType type, int flags) {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 8e6735d..db14f9f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -944,7 +944,7 @@
     return Textfield::HandleAccessibleAction(action_data);
 
   if (action_data.action == ax::mojom::Action::kSetValue) {
-    SetUserText(action_data.value, true);
+    SetUserText(base::UTF8ToUTF16(action_data.value), true);
     return true;
   } else if (action_data.action == ax::mojom::Action::kReplaceSelectedText) {
     model()->SetInputInProgress(true);
@@ -952,7 +952,7 @@
       SelectRange(saved_selection_for_focus_change_);
       saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
     }
-    InsertOrReplaceText(action_data.value);
+    InsertOrReplaceText(base::UTF8ToUTF16(action_data.value));
     TextChanged();
     return true;
   } else if (action_data.action == ax::mojom::Action::kSetSelection) {
diff --git a/chrome/browser/ui/views/payments/validating_textfield_unittest.cc b/chrome/browser/ui/views/payments/validating_textfield_unittest.cc
index e3daf65..a37c1b0 100644
--- a/chrome/browser/ui/views/payments/validating_textfield_unittest.cc
+++ b/chrome/browser/ui/views/payments/validating_textfield_unittest.cc
@@ -11,13 +11,13 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/views/payments/validation_delegate.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/test/views_test_base.h"
 
 namespace payments {
 
-class ValidatingTextfieldTest : public views::ViewsTestBase {
+class ValidatingTextfieldTest : public ChromeViewsTestBase {
  public:
   ValidatingTextfieldTest() {}
   ~ValidatingTextfieldTest() override {}
diff --git a/chrome/browser/ui/views/payments/view_stack_unittest.cc b/chrome/browser/ui/views/payments/view_stack_unittest.cc
index 60c0c75..857a599 100644
--- a/chrome/browser/ui/views/payments/view_stack_unittest.cc
+++ b/chrome/browser/ui/views/payments/view_stack_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/observer_list.h"
 #include "base/run_loop.h"
 #include "chrome/browser/ui/views/payments/view_stack.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "ui/gfx/animation/test_animation_delegate.h"
-#include "ui/views/test/views_test_base.h"
 
 class TestStackView : public views::View {
  public:
@@ -43,7 +43,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestStackView);
 };
 
-class ViewStackTest : public views::ViewsTestBase {
+class ViewStackTest : public ChromeViewsTestBase {
  public:
   ViewStackTest() : view_stack_(std::make_unique<ViewStack>()) {
     view_stack_->SetBounds(0, 0, 10, 10);
diff --git a/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc b/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
index 20afbeb..d1a4850d 100644
--- a/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
+++ b/chrome/browser/ui/views/sync/bubble_sync_promo_view_unittest.cc
@@ -12,14 +12,14 @@
 #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "components/signin/core/browser/account_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_constants.h"
 #include "ui/gfx/range/range.h"
 #include "ui/views/controls/styled_label.h"
-#include "ui/views/test/views_test_base.h"
 
-class BubbleSyncPromoViewTest : public views::ViewsTestBase,
+class BubbleSyncPromoViewTest : public ChromeViewsTestBase,
                                 public BubbleSyncPromoDelegate {
  public:
   BubbleSyncPromoViewTest() {}
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 6287f573..dca6391 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -13,6 +13,7 @@
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/numerics/ranges.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -100,6 +101,10 @@
 // right edges of the tab.
 constexpr int kSeparatorThickness = 1;
 
+// The amount of padding inside the interior path to clip children against when
+// tabs are very narrow.
+constexpr int kChildClipPadding = 1;
+
 // Under material refresh, the spec for the favicon or title text is 12dips from
 // the left vertical edge of the tab. This edge is in the middle of the tab end
 // cap. The end cap is 16dips, the middle of which is 8dips. This value is the
@@ -124,20 +129,25 @@
   return extra_space / 2;
 }
 
-// Returns the width of the tab endcap in DIP.  Pre-refresh, this is the
-// width of the curve making up either the outer or inner edge of the stroke.
-int GetTabEndcapWidth() {
-  constexpr int kEndcapWidth[] = {16, 18, 24, 16, 16};
-  return kEndcapWidth[MD::GetMode()];
+// For non-material-refresh mode, returns the width of the tab endcap in DIP.
+// More precisely, this is the width of the curve making up either the outer or
+// inner edge of the stroke.
+//
+// These two curves are horizontally offset by 1 px (regardless of scale); the
+// total width of the endcap from tab outer edge to the inside end of the stroke
+// inner edge is (GetTabEndcapWidthForLayout() * scale) + 1.
+int GetTabEndcapWidthForLayout() {
+  const int mode = MD::GetMode();
+  DCHECK_LE(mode, 2);
+
+  constexpr int kEndcapWidth[] = {16, 18, 24};
+  return kEndcapWidth[mode];
 }
 
-// Pre-refresh, endcaps paint slightly differently than they layout.
+// For painting the endcaps, the top corners are actually shifted outwards 0.5
+// DIP from the grid.
 float GetTabEndcapWidthForPainting() {
-  DCHECK(!MD::IsRefreshUi());
-
-  // For painting the endcaps, the top corners are actually shifted outwards 0.5
-  // DIP from the grid.
-  return GetTabEndcapWidth() - 0.5f;
+  return GetTabEndcapWidthForLayout() - 0.5f;
 }
 
 void DrawHighlight(gfx::Canvas* canvas,
@@ -156,12 +166,11 @@
 
 // Scales |bounds| by scale and aligns so that the layout portion is snapped to
 // the pixel grid.  This ensures adjacent tabs meet up exactly during painting.
-const gfx::RectF ScaleAndAlignBounds(const gfx::Rect& bounds,
-                                     float endcap_width,
-                                     float scale) {
+const gfx::RectF ScaleAndAlignBounds(const gfx::Rect& bounds, float scale) {
   // Convert full bounds to layout bounds and scale from DIP to px.
   gfx::RectF aligned_bounds(bounds);
-  aligned_bounds.Inset(endcap_width / 2, 0);
+  const int corner_radius = Tab::GetCornerRadius();
+  aligned_bounds.Inset(corner_radius, 0);
   aligned_bounds.Scale(scale);
 
   // Snap layout bounds to nearest pixels.
@@ -177,7 +186,7 @@
 
   // Convert back to full bounds.  The endcap widths are not rounded, since it's
   // OK if the corners do not snap to the pixel grid.
-  aligned_bounds.Inset(-(endcap_width / 2) * scale, 0);
+  aligned_bounds.Inset(-corner_radius * scale, 0);
   return aligned_bounds;
 }
 
@@ -197,11 +206,23 @@
 gfx::Path GetRefreshInteriorPath(float scale,
                                  const gfx::Rect& bounds,
                                  float horizontal_inset) {
-  const float endcap_width = GetTabEndcapWidth();
-  const float radius = (endcap_width / 2) * scale;
+  // TODO(pkasting): Fix this to work better with stroke heights > 0.
 
-  const gfx::RectF aligned_bounds =
-      ScaleAndAlignBounds(bounds, endcap_width, scale);
+  // Compute |extension| as the width outside the separators.  This is a fixed
+  // value equal to the normal corner radius.
+  const float ideal_radius = Tab::GetCornerRadius();
+  const float extension = ideal_radius * scale;
+  // As the separators get closer together, shrink the radius so the top (inner)
+  // corners touch.
+  const float radius =
+      base::ClampToRange((bounds.width() - ideal_radius * 2) / 2, 0.f,
+                         ideal_radius) *
+      scale;
+  // When the radius shrinks, it leaves a gap between the bottom (outer) corners
+  // and the edge of the tab.
+  const float corner_gap = extension - radius;
+
+  const gfx::RectF aligned_bounds = ScaleAndAlignBounds(bounds, scale);
   const float left = aligned_bounds.x();
   const float top = aligned_bounds.y() + Tab::GetStrokeHeight();
   const float right = aligned_bounds.right();
@@ -215,15 +236,16 @@
   // Bottom right.
   gfx::Path right_path;
   right_path.moveTo(right, bottom);
+  right_path.rLineTo(-corner_gap, 0);
   right_path.arcTo(radius, radius, 0, SkPath::kSmall_ArcSize,
-                   SkPath::kCW_Direction, right - radius, bottom - radius);
+                   SkPath::kCW_Direction, right - extension, bottom - radius);
 
   // Right vertical.
-  right_path.lineTo(right - radius, top + radius);
+  right_path.lineTo(right - extension, top + radius);
 
   // Top right.
   right_path.arcTo(radius, radius, 0, SkPath::kSmall_ArcSize,
-                   SkPath::kCCW_Direction, right - radius * 2, top);
+                   SkPath::kCCW_Direction, right - extension - radius, top);
 
   // Top/bottom edges of right side.
   right_path.lineTo(left, top);
@@ -232,16 +254,16 @@
 
   // Top left.
   gfx::Path left_path;
-  left_path.moveTo(left + radius * 2, top);
+  left_path.moveTo(left + extension + radius, top);
   left_path.arcTo(radius, radius, 0, SkPath::kSmall_ArcSize,
-                  SkPath::kCCW_Direction, left + radius, top + radius);
+                  SkPath::kCCW_Direction, left + extension, top + radius);
 
   // Left vertical.
-  left_path.lineTo(left + radius, bottom - radius);
+  left_path.lineTo(left + extension, bottom - radius);
 
   // Bottom left.
   left_path.arcTo(radius, radius, 0, SkPath::kSmall_ArcSize,
-                  SkPath::kCW_Direction, left, bottom);
+                  SkPath::kCW_Direction, left + corner_gap, bottom);
 
   // Bottom/top edges of left side.
   left_path.lineTo(right, bottom);
@@ -310,12 +332,20 @@
                                bool extend_to_top,
                                float scale,
                                float stroke_thickness) {
-  const float endcap_width = GetTabEndcapWidth();
-  const float outer_radius = (endcap_width / 2) * scale - stroke_thickness;
-  const float inner_radius = (endcap_width / 2) * scale + stroke_thickness;
+  // TODO(pkasting): Fix this to work better with stroke heights > 0.
 
-  const gfx::RectF aligned_bounds =
-      ScaleAndAlignBounds(bounds, endcap_width, scale);
+  // See comments in GetRefreshInteriorPath().
+  const float ideal_radius = Tab::GetCornerRadius();
+  const float extension = ideal_radius * scale;
+  const float radius =
+      base::ClampToRange((bounds.width() - ideal_radius * 2) / 2, 0.f,
+                         ideal_radius) *
+      scale;
+  const float outer_radius = std::max(radius - stroke_thickness, 0.f);
+  const float inner_radius = radius * 2 - outer_radius;
+  const float corner_gap = extension - outer_radius;
+
+  const gfx::RectF aligned_bounds = ScaleAndAlignBounds(bounds, scale);
   const float left = aligned_bounds.x();
   const float top = aligned_bounds.y();
   const float right = aligned_bounds.right();
@@ -325,38 +355,41 @@
   gfx::Path path;
   path.moveTo(left, bottom);
   path.rLineTo(0, -stroke_thickness);
+  path.rLineTo(corner_gap, 0);
   path.arcTo(outer_radius, outer_radius, 0, SkPath::kSmall_ArcSize,
-             SkPath::kCCW_Direction, left + outer_radius,
+             SkPath::kCCW_Direction, left + extension,
              bottom - stroke_thickness - outer_radius);
 
   if (extend_to_top) {
     // Left vertical.
-    path.lineTo(left + outer_radius, top);
+    path.lineTo(left + extension, top);
 
     // Top edge.
-    path.lineTo(right - outer_radius, top);
+    path.lineTo(right - extension, top);
   } else {
     // Left vertical.
-    path.lineTo(left + outer_radius, top + inner_radius);
+    path.lineTo(left + extension, top + inner_radius);
 
     // Top left.
     path.arcTo(inner_radius, inner_radius, 0, SkPath::kSmall_ArcSize,
-               SkPath::kCW_Direction, left + outer_radius + inner_radius, top);
+               SkPath::kCW_Direction, left + extension + inner_radius, top);
 
     // Top edge.
-    path.lineTo(right - outer_radius - inner_radius, top);
+    path.lineTo(right - extension - inner_radius, top);
 
     // Top right.
     path.arcTo(inner_radius, inner_radius, 0, SkPath::kSmall_ArcSize,
-               SkPath::kCW_Direction, right - outer_radius, top + inner_radius);
+               SkPath::kCW_Direction, right - extension, top + inner_radius);
   }
 
   // Right vertical.
-  path.lineTo(right - outer_radius, bottom - stroke_thickness - outer_radius);
+  path.lineTo(right - extension, bottom - stroke_thickness - outer_radius);
 
   // Bottom right.
   path.arcTo(outer_radius, outer_radius, 0, SkPath::kSmall_ArcSize,
-             SkPath::kCCW_Direction, right, bottom - stroke_thickness);
+             SkPath::kCCW_Direction, right - corner_gap,
+             bottom - stroke_thickness);
+  path.rLineTo(corner_gap, 0);
   path.rLineTo(0, stroke_thickness);
 
   // Bottom edge.
@@ -463,8 +496,7 @@
 
   // This will cause calls to GetContentsBounds to return only the rectangle
   // inside the tab shape, rather than to its extents.
-  SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetStrokeHeight(), GetTabEndcapWidth())));
+  SetBorder(views::CreateEmptyBorder(GetContentsInsets()));
 
   title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
   title_->SetElideBehavior(gfx::FADE_TAIL);
@@ -554,7 +586,7 @@
 void Tab::ShowContextMenuForView(views::View* source,
                                  const gfx::Point& point,
                                  ui::MenuSourceType source_type) {
-  if (!closing())
+  if (!closing_)
     controller_->ShowContextMenuForTab(this, point, source_type);
 }
 
@@ -875,22 +907,21 @@
 }
 
 void Tab::PaintChildren(const views::PaintInfo& info) {
-  // Clip children to 1 dp inside the tab's fill path.  This has no effect
-  // except when the tab is too narrow to completely show even one icon, at
-  // which point this serves to clip the favicon.
+  // Clip children based on the tab's fill path.  This has no effect except when
+  // the tab is too narrow to completely show even one icon, at which point this
+  // serves to clip the favicon.
   ui::ClipRecorder clip_recorder(info.context());
   // The paint recording scale for tabs is consistent along the x and y axis.
   const float paint_recording_scale = info.paint_recording_scale_x();
-  constexpr int kFaviconPadding = 1;
   clip_recorder.ClipPathWithAntiAliasing(
-      GetInteriorPath(paint_recording_scale, bounds(), kFaviconPadding));
+      GetInteriorPath(paint_recording_scale, bounds(), kChildClipPadding));
   View::PaintChildren(info);
 }
 
 void Tab::OnPaint(gfx::Canvas* canvas) {
   // Don't paint if we're narrower than we can render correctly. (This should
   // only happen during animations).
-  if (width() < GetMinimumInactiveWidth() && !data().pinned)
+  if (!MD::IsRefreshUi() && (width() < GetMinimumInactiveWidth()))
     return;
 
   gfx::Path clip;
@@ -912,12 +943,6 @@
   OnButtonColorMaybeChanged();
 }
 
-int Tab::GetCornerRadius() const {
-  // TODO(pkasting): This should vary as the tab width decreases.
-  return ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
-      views::EMPHASIS_HIGH);
-}
-
 SkColor Tab::GetAlertIndicatorColor(TabAlertState state) const {
   const bool is_touch_optimized = MD::IsTouchOptimizedUiEnabled();
   // If theme provider is not yet available, return the default button
@@ -1089,12 +1114,20 @@
 
 // static
 int Tab::GetMinimumInactiveWidth() {
-  return GetTabEndcapWidth() * 2;
+  if (!MD::IsRefreshUi())
+    return GetContentsInsets().width();
+
+  // Allow the favicon to shrink until only the middle 4 DIP are visible.
+  constexpr int kFaviconMinWidth = 4;
+  // kSeparatorThickness is only added for the leading separator, because the
+  // trailing separator is part of the overlap.
+  return kSeparatorThickness + (kChildClipPadding * 2) + kFaviconMinWidth +
+         GetOverlap();
 }
 
 // static
 int Tab::GetMinimumActiveWidth() {
-  return TabCloseButton::GetWidth() + GetMinimumInactiveWidth();
+  return TabCloseButton::GetWidth() + GetContentsInsets().width();
 }
 
 // static
@@ -1106,7 +1139,7 @@
 // static
 int Tab::GetPinnedWidth() {
   constexpr int kTabPinnedContentWidth = 23;
-  return kTabPinnedContentWidth + GetMinimumInactiveWidth();
+  return kTabPinnedContentWidth + GetContentsInsets().width();
 }
 
 // static
@@ -1123,7 +1156,7 @@
   // * The endcap width is enough for the whole stroke outer curve, i.e. the
   //   side diagonal plus the curves on both its ends.
   // * The bottom and top curve together are 4 DIP wide, so the diagonal is
-  //   (endcap_width - 4) DIP wide.
+  //   (endcap width - 4) DIP wide.
   // * The bottom and top curve are each 1.5 px high.  Additionally, there is an
   //   extra 1 px below the bottom curve and (scale - 1) px above the top curve,
   //   so the diagonal is ((height - 1.5 - 1.5) * scale - 1 - (scale - 1)) px
@@ -1134,10 +1167,23 @@
 }
 
 // static
+int Tab::GetCornerRadius() {
+  return ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
+      views::EMPHASIS_HIGH);
+}
+
+// static
+gfx::Insets Tab::GetContentsInsets() {
+  const int endcap_width = MD::IsRefreshUi() ? (GetCornerRadius() * 2)
+                                             : GetTabEndcapWidthForLayout();
+  return gfx::Insets(GetStrokeHeight(), endcap_width);
+}
+
+// static
 int Tab::GetOverlap() {
-  // We want to overlap the endcap portions entirely. Under refresh, we want to
-  // overlap by an extra dip on each end in order overlap the separators.
-  return GetTabEndcapWidth() + (MD::IsRefreshUi() ? kSeparatorThickness : 0);
+  // For refresh, overlap the separators.
+  return MD::IsRefreshUi() ? (GetCornerRadius() * 2 + kSeparatorThickness)
+                           : GetTabEndcapWidthForLayout();
 }
 
 // static
@@ -1355,18 +1401,15 @@
   gfx::ScopedCanvas scoped_canvas(canvas);
   const float scale = canvas->UndoDeviceScaleFactor();
 
-  const float endcap_width = GetTabEndcapWidth();
-  const gfx::RectF aligned_bounds =
-      ScaleAndAlignBounds(bounds(), endcap_width, scale);
-
+  const gfx::RectF aligned_bounds = ScaleAndAlignBounds(bounds(), scale);
+  const int corner_radius = GetCornerRadius();
   const float separator_height = GetTabSeparatorHeight() * scale;
   gfx::RectF leading_separator_bounds(
-      aligned_bounds.x() + (endcap_width / 2) * scale,
+      aligned_bounds.x() + corner_radius * scale,
       aligned_bounds.y() + (aligned_bounds.height() - separator_height) / 2,
       kSeparatorThickness * scale, separator_height);
   gfx::RectF trailing_separator_bounds(
-      aligned_bounds.right() - (endcap_width / 2) * scale -
-          kSeparatorThickness * scale,
+      aligned_bounds.right() - (corner_radius + kSeparatorThickness) * scale,
       leading_separator_bounds.y(), kSeparatorThickness * scale,
       separator_height);
 
@@ -1382,12 +1425,12 @@
   // If the subsequent tab is active, don't consider its hover animation value.
   // Without this active check and the subsequent tab is also dragged, the
   // trailing separator on this tab will appear invisible (alpha = 0).
-  Tab* subsequent_tab = controller_->GetSubsequentTab(this);
+  const Tab* subsequent_tab = controller_->GetSubsequentTab(this);
   float leading_alpha;
   float trailing_alpha = leading_alpha =
       std::max(hover_controller_.GetAnimationValue(),
                subsequent_tab && !subsequent_tab->IsActive()
-                   ? subsequent_tab->hover_controller()->GetAnimationValue()
+                   ? subsequent_tab->hover_controller_.GetAnimationValue()
                    : 0);
   // When the tab's bounds are animating, inversely fade the leading or trailing
   // separator based on the NTB position, the tab's index, and how close to the
@@ -1426,14 +1469,20 @@
 void Tab::UpdateIconVisibility() {
   // TODO(pkasting): This whole function should go away, and we should simply
   // compute child visibility state in Layout().
-  center_favicon_ = false;
+
+  // Don't adjust whether we're centering the favicon during tab closure; let it
+  // stay however it was prior to closing the tab.  This prevents the icon from
+  // sliding left at the end of closing a non-narrow tab.
+  if (!closing_)
+    center_favicon_ = false;
+
   showing_icon_ = showing_alert_indicator_ = false;
   extra_padding_before_content_ = false;
 
   if (height() < GetLayoutConstant(TAB_HEIGHT))
     return;
 
-  int available_width = std::max(0, width() - GetMinimumInactiveWidth());
+  int available_width = GetContentsBounds().width();
 
   const bool is_touch_optimized = MD::IsTouchOptimizedUiEnabled();
   const int favicon_width = gfx::kFaviconSize;
@@ -1510,7 +1559,10 @@
       if (!showing_close_button_ && !showing_alert_indicator_ &&
           !showing_icon_ && has_favicon) {
         showing_icon_ = true;
-        center_favicon_ = true;
+
+        // See comments near top of function on why this conditional is here.
+        if (!closing_)
+          center_favicon_ = true;
       }
     }
     extra_padding_before_content_ =
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index f1643bf..3e496b9 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -110,9 +110,6 @@
   void set_detached() { detached_ = true; }
   bool detached() const { return detached_; }
 
-  // Returns the radius of the outer corners of the tab shape.
-  int GetCornerRadius() const;
-
   // Returns the color used for the alert indicator icon.
   SkColor GetAlertIndicatorColor(TabAlertState state) const;
 
@@ -204,6 +201,12 @@
   // horizontal deltas from those.
   static float GetInverseDiagonalSlope();
 
+  // Returns the radius of the outer corners of the tab shape.
+  static int GetCornerRadius();
+
+  // Returns the insets to use for laying out tab contents.
+  static gfx::Insets GetContentsInsets();
+
   // Returns the overlap between adjacent tabs.
   static int GetOverlap();
 
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h
index a45428e..07988df 100644
--- a/chrome/browser/ui/views/tabs/tab_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -111,7 +111,7 @@
 
   // Returns the next tab in the model order. Returns nullptr if there
   // isn't another tab beyond the given tab.
-  virtual Tab* GetSubsequentTab(Tab* tab) = 0;
+  virtual const Tab* GetSubsequentTab(const Tab* tab) = 0;
 
   // Invoked when a mouse event occurs on |source|.
   virtual void OnMouseEventInTab(views::View* source,
@@ -157,7 +157,7 @@
   // If the given tab is animating to its target destination, this returns the
   // target bounds. If the tab isn't moving this will return the current bounds
   // of the given tab.
-  virtual gfx::Rect GetTabAnimationTargetBounds(Tab* tab) = 0;
+  virtual gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) = 0;
 
   // Returns the accessible tab name for this tab.
   virtual base::string16 GetAccessibleTabName(const Tab* tab) const = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index a19c349..1d6bc07f 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -546,21 +546,63 @@
 }
 
 void TabStrip::RemoveTabAt(content::WebContents* contents, int model_index) {
+  const bool first_unpinned_tab = model_index == GetPinnedTabCount();
+
+  if (!touch_layout_)
+    PrepareForAnimation();
+
+  Tab* tab = tab_at(model_index);
+  tab->set_closing(true);
+
+  int old_x = tabs_.ideal_bounds(model_index).x();
+  RemoveTabFromViewModel(model_index);
+
   if (touch_layout_) {
-    Tab* tab = tab_at(model_index);
-    tab->set_closing(true);
-    int old_x = tabs_.ideal_bounds(model_index).x();
-    // We still need to paint the tab until we actually remove it. Put it in
-    // tabs_closing_map_ so we can find it.
-    RemoveTabFromViewModel(model_index);
     touch_layout_->RemoveTab(model_index,
                              GenerateIdealBoundsForPinnedTabs(nullptr), old_x);
-    ScheduleRemoveTabAnimation(tab);
-  } else if (in_tab_close_ && model_index != GetModelCount()) {
-    StartMouseInitiatedRemoveTabAnimation(model_index);
-  } else {
-    StartRemoveTabAnimation(model_index);
   }
+
+  GenerateIdealBounds();
+  AnimateToIdealBounds();
+
+  // TODO(pkasting): When closing multiple tabs, we get repeated RemoveTabAt()
+  // calls, each of which closes a new tab and thus generates different ideal
+  // bounds.  We should update the animations of any other tabs that are
+  // currently being closed to reflect the new ideal bounds, or else change from
+  // removing one tab at a time to animating the removal of all tabs at once.
+
+  // Compute the target bounds for animating this tab closed.  The tab's left
+  // edge should stay joined to the right edge of the previous tab, if any.
+  gfx::Rect tab_bounds = tab->bounds();
+  int desired_x = TabStartX();
+  if (model_index > 0) {
+    desired_x = ideal_bounds(model_index - 1).right() - Tab::GetOverlap();
+    if (first_unpinned_tab)
+      desired_x += GetPinnedToNonPinnedOffset();
+  }
+  tab_bounds.set_x(desired_x);
+
+  // The tab should animate to the width of the overlap in order to close at the
+  // same speed the surrounding tabs are moving, since at this width the
+  // subsequent tab is naturally positioned at the same X coordinate.
+  tab_bounds.set_width(Tab::GetOverlap());
+
+  // Animate the tab closed.
+  bounds_animator_.AnimateViewTo(tab, tab_bounds);
+  bounds_animator_.SetAnimationDelegate(
+      tab, std::make_unique<RemoveTabDelegate>(this, tab));
+
+  // TODO(pkasting): The first part of this conditional doesn't really make
+  // sense to me.  Why is each condition justified?
+  if ((touch_layout_ || !in_tab_close_ || model_index == GetModelCount()) &&
+      TabDragController::IsAttachedTo(this)) {
+    // Don't animate the new tab button when dragging tabs. Otherwise it looks
+    // like the new tab button magically appears from beyond the end of the tab
+    // strip.
+    bounds_animator_.StopAnimatingView(new_tab_button_);
+    new_tab_button_->SetBoundsRect(new_tab_button_bounds_);
+  }
+
   SwapLayoutIfNecessary();
 
   for (TabStripObserver& observer : observers_)
@@ -1037,7 +1079,7 @@
   return view && view->id() == VIEW_ID_TAB ? static_cast<Tab*>(view) : nullptr;
 }
 
-Tab* TabStrip::GetSubsequentTab(Tab* tab) {
+const Tab* TabStrip::GetSubsequentTab(const Tab* tab) {
   int index = GetModelIndexOfTab(tab);
   if (index < 0)
     return nullptr;
@@ -1150,7 +1192,7 @@
   return id;
 }
 
-gfx::Rect TabStrip::GetTabAnimationTargetBounds(Tab* tab) {
+gfx::Rect TabStrip::GetTabAnimationTargetBounds(const Tab* tab) {
   return bounds_animator_.GetTargetBounds(tab);
 }
 
@@ -1309,7 +1351,7 @@
   if (MD::IsRefreshUi() && GetNewTabButtonPosition() == TRAILING) {
     float separator_height = Tab::GetTabSeparatorHeight();
     gfx::RectF separator_bounds(
-        new_tab_button_bounds_.x() - Tab::GetOverlap() / 2,
+        new_tab_button_bounds_.x() - Tab::GetCornerRadius(),
         (height() - separator_height) / 2, 1, separator_height);
     cc::PaintFlags flags;
     flags.setAntiAlias(true);
@@ -1473,12 +1515,24 @@
 
   GenerateIdealBounds();
 
-  // Set the current bounds to be the correct place but 0 width.
+  // Insert the tab just after the current right edge of the previous tab, if
+  // any.
   gfx::Rect bounds = ideal_bounds(model_index);
-  bounds.set_width(0);
-  tab_at(model_index)->SetBoundsRect(bounds);
+  if (model_index > 0) {
+    int desired_x =
+        tab_at(model_index - 1)->bounds().right() - Tab::GetOverlap();
+    if (model_index == GetPinnedTabCount())
+      desired_x += GetPinnedToNonPinnedOffset();
+    bounds.set_x(desired_x);
+  }
+
+  // Start at the width of the overlap in order to animate at the same speed the
+  // surrounding tabs are moving, since at this width the subsequent tab is
+  // naturally positioned at the same X coordinate.
+  bounds.set_width(Tab::GetOverlap());
 
   // Animate in to the full width.
+  tab_at(model_index)->SetBoundsRect(bounds);
   AnimateToIdealBounds();
 }
 
@@ -1488,39 +1542,6 @@
   AnimateToIdealBounds();
 }
 
-void TabStrip::StartRemoveTabAnimation(int model_index) {
-  PrepareForAnimation();
-
-  // Mark the tab as closing.
-  Tab* tab = tab_at(model_index);
-  tab->set_closing(true);
-
-  RemoveTabFromViewModel(model_index);
-
-  ScheduleRemoveTabAnimation(tab);
-}
-
-void TabStrip::ScheduleRemoveTabAnimation(Tab* tab) {
-  // Start an animation for the tabs.
-  GenerateIdealBounds();
-  AnimateToIdealBounds();
-
-  // Animate the tab being closed to zero width.
-  gfx::Rect tab_bounds = tab->bounds();
-  tab_bounds.set_width(0);
-  bounds_animator_.AnimateViewTo(tab, tab_bounds);
-  bounds_animator_.SetAnimationDelegate(
-      tab, std::make_unique<RemoveTabDelegate>(this, tab));
-
-  // Don't animate the new tab button when dragging tabs. Otherwise it looks
-  // like the new tab button magically appears from beyond the end of the tab
-  // strip.
-  if (TabDragController::IsAttachedTo(this)) {
-    bounds_animator_.StopAnimatingView(new_tab_button_);
-    new_tab_button_->SetBoundsRect(new_tab_button_bounds_);
-  }
-}
-
 void TabStrip::AnimateToIdealBounds() {
   for (int i = 0; i < tab_count(); ++i) {
     // If the tab is being dragged manually, skip it.
@@ -1528,7 +1549,14 @@
     if (tab->dragging() && !bounds_animator_.IsAnimating(tab))
       continue;
 
-    bounds_animator_.AnimateViewTo(tab, ideal_bounds(i));
+    // Also skip tabs already being animated to the same ideal bounds.  Calling
+    // AnimateViewTo() again restarts the animation, which changes the timing of
+    // how the tab animates, leading to hitches.
+    const gfx::Rect& target_bounds = ideal_bounds(i);
+    if (bounds_animator_.GetTargetBounds(tab) == target_bounds)
+      continue;
+
+    bounds_animator_.AnimateViewTo(tab, target_bounds);
 
     // Set an animation delegate for the tab so it will clip appropriately.
     // Don't do this if dragging() is true.  In this case the tab was
@@ -1543,7 +1571,9 @@
     }
   }
 
-  bounds_animator_.AnimateViewTo(new_tab_button_, new_tab_button_bounds_);
+  if (bounds_animator_.GetTargetBounds(new_tab_button_) !=
+      new_tab_button_bounds_)
+    bounds_animator_.AnimateViewTo(new_tab_button_, new_tab_button_bounds_);
 }
 
 bool TabStrip::ShouldHighlightCloseButtonAfterRemove() {
@@ -1581,7 +1611,7 @@
     // space where the outer (lower) corners are, which should be treated as
     // part of the grab area, so decrease the size of the remaining grab area by
     // that width.
-    width -= tab_at(tab_count() - 1)->GetCornerRadius();
+    width -= Tab::GetCornerRadius();
   }
 
   return width;
@@ -2253,28 +2283,6 @@
   AnimateToIdealBounds();
 }
 
-void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) {
-  PrepareForAnimation();
-
-  Tab* tab_closing = tab_at(model_index);
-  tab_closing->set_closing(true);
-
-  // We still need to paint the tab until we actually remove it. Put it in
-  // tabs_closing_map_ so we can find it.
-  RemoveTabFromViewModel(model_index);
-
-  GenerateIdealBounds();
-  AnimateToIdealBounds();
-
-  gfx::Rect tab_bounds = tab_closing->bounds();
-  tab_bounds.set_width(0);
-  bounds_animator_.AnimateViewTo(tab_closing, tab_bounds);
-
-  // Register delegate to do cleanup when done.
-  bounds_animator_.SetAnimationDelegate(
-      tab_closing, std::make_unique<RemoveTabDelegate>(this, tab_closing));
-}
-
 bool TabStrip::IsPointInTab(Tab* tab,
                             const gfx::Point& point_in_tabstrip_coords) {
   if (!tab->visible())
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 17e448da..db3b95a 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -255,7 +255,7 @@
   void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override;
   bool EndDrag(EndDragReason reason) override;
   Tab* GetTabAt(Tab* tab, const gfx::Point& tab_in_tab_coordinates) override;
-  Tab* GetSubsequentTab(Tab* tab) override;
+  const Tab* GetSubsequentTab(const Tab* tab) override;
   void OnMouseEventInTab(views::View* source,
                          const ui::MouseEvent& event) override;
   bool ShouldPaintTab(
@@ -270,7 +270,7 @@
   SkColor GetTabForegroundColor(TabState state) const override;
   base::string16 GetAccessibleTabName(const Tab* tab) const override;
   int GetBackgroundResourceId(bool* custom_image) const override;
-  gfx::Rect GetTabAnimationTargetBounds(Tab* tab) override;
+  gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override;
 
   // MouseWatcherListener:
   void MouseMovedOutOfHost() override;
@@ -338,13 +338,6 @@
   // move.
   void StartMoveTabAnimation();
 
-  // Starts the remove tab animation.
-  void StartRemoveTabAnimation(int model_index);
-
-  // Schedules the animations and bounds changes necessary for a remove tab
-  // animation.
-  void ScheduleRemoveTabAnimation(Tab* tab);
-
   // Animates all the views to their ideal bounds.
   // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds
   // currently set in ideal_bounds.
@@ -538,7 +531,6 @@
   // Starts various types of TabStrip animations.
   void StartResizeLayoutAnimation();
   void StartPinnedTabAnimation();
-  void StartMouseInitiatedRemoveTabAnimation(int model_index);
 
   // Returns true if the specified point in TabStrip coords is within the
   // hit-test region of the specified Tab.
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index 90cff0e..af0e43a 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -15,13 +15,13 @@
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_icon.h"
 #include "chrome/grit/theme_resources.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/models/list_selection_model.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 
 using views::Widget;
@@ -70,7 +70,7 @@
   Tab* GetTabAt(Tab* tab, const gfx::Point& tab_in_tab_coordinates) override {
     return nullptr;
   }
-  Tab* GetSubsequentTab(Tab* tab) override { return nullptr; }
+  const Tab* GetSubsequentTab(const Tab* tab) override { return nullptr; }
   void OnMouseEventInTab(views::View* source,
                          const ui::MouseEvent& event) override {}
   bool ShouldPaintTab(
@@ -95,7 +95,7 @@
     *custom_image = false;
     return IDR_THEME_TAB_BACKGROUND;
   }
-  gfx::Rect GetTabAnimationTargetBounds(Tab* tab) override {
+  gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override {
     return tab->bounds();
   }
   base::string16 GetAccessibleTabName(const Tab* tab) const override {
@@ -110,7 +110,7 @@
   DISALLOW_COPY_AND_ASSIGN(FakeTabController);
 };
 
-class TabTest : public views::ViewsTestBase {
+class TabTest : public ChromeViewsTestBase {
  public:
   TabTest() {}
   ~TabTest() override {}
diff --git a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
index 1a2a17c..82cc5a2 100644
--- a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
@@ -737,8 +737,7 @@
     DVLOG(1) << "Unable to extract args.";
     return;
   }
-  base::UmaHistogramSparse("MediaRouter.Ui.Action.StartLocalPosition",
-                           std::min(index, 100));
+  MediaRouterMetrics::RecordStartRouteDeviceIndex(index);
 }
 
 void MediaRouterWebUIMessageHandler::OnReportFilter(const base::ListValue*) {
@@ -800,9 +799,8 @@
     DVLOG(1) << "Unable to extract args.";
     return;
   }
-
-  UMA_HISTOGRAM_BOOLEAN("MediaRouter.Ui.Action.StartLocalSessionSuccessful",
-                        route_created_successfully);
+  MediaRouterMetrics::RecordStartLocalSessionSuccessful(
+      route_created_successfully);
 }
 
 void MediaRouterWebUIMessageHandler::OnReportRouteCreationOutcome(
@@ -841,7 +839,7 @@
     DVLOG(1) << "Unable to extract args.";
     return;
   }
-  UMA_HISTOGRAM_COUNTS_100("MediaRouter.Ui.Device.Count", sink_count);
+  MediaRouterMetrics::RecordDeviceCount(sink_count);
 }
 
 void MediaRouterWebUIMessageHandler::OnReportTimeToClickSink(
diff --git a/chrome/browser/vr/speech_recognizer_unittest.cc b/chrome/browser/vr/speech_recognizer_unittest.cc
index 525d4cf..b838e0a 100644
--- a/chrome/browser/vr/speech_recognizer_unittest.cc
+++ b/chrome/browser/vr/speech_recognizer_unittest.cc
@@ -364,8 +364,8 @@
   speech_recognizer_->Start();
   base::RunLoop().RunUntilIdle();
 
-  auto mock_timer = std::make_unique<base::MockTimer>(false, false);
-  base::MockTimer* timer_ptr = mock_timer.get();
+  auto mock_timer = std::make_unique<base::MockOneShotTimer>();
+  base::MockOneShotTimer* timer_ptr = mock_timer.get();
   speech_recognizer_->SetSpeechTimerForTest(std::move(mock_timer));
 
   fake_speech_recognition_manager_->FakeSpeechRecognitionEvent(SOUND_START);
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index 153fab6..0604b7a 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -22,6 +22,7 @@
   "+components/metrics/call_stack_profile_metrics_provider.h",
   "+components/metrics/call_stack_profile_params.h",
   "+components/metrics/child_call_stack_profile_collector.h",
+  "+components/metrics/call_stack_profile_builder.h",
   "+components/metrics/client_info.h",
   "+components/metrics/metrics_pref_names.h",
   "+components/nacl/common",
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml
index 0d63986..1c4469d 100644
--- a/chrome/common/extensions/docs/server2/app.yaml
+++ b/chrome/common/extensions/docs/server2/app.yaml
@@ -1,5 +1,5 @@
 application: chrome-apps-doc
-version: 3-56-0
+version: 3-57-0
 runtime: python27
 api_version: 1
 threadsafe: false
diff --git a/chrome/common/media_router/discovery/media_sink_service_base.cc b/chrome/common/media_router/discovery/media_sink_service_base.cc
index 9f62d24..fc68861 100644
--- a/chrome/common/media_router/discovery/media_sink_service_base.cc
+++ b/chrome/common/media_router/discovery/media_sink_service_base.cc
@@ -72,7 +72,8 @@
   StartTimer();
 }
 
-void MediaSinkServiceBase::SetTimerForTest(std::unique_ptr<base::Timer> timer) {
+void MediaSinkServiceBase::SetTimerForTest(
+    std::unique_ptr<base::OneShotTimer> timer) {
   discovery_timer_ = std::move(timer);
 }
 
diff --git a/chrome/common/media_router/discovery/media_sink_service_base.h b/chrome/common/media_router/discovery/media_sink_service_base.h
index b244606..fa7c038 100644
--- a/chrome/common/media_router/discovery/media_sink_service_base.h
+++ b/chrome/common/media_router/discovery/media_sink_service_base.h
@@ -67,7 +67,7 @@
   const base::flat_map<MediaSink::Id, MediaSinkInternal>& GetSinks() const;
   const MediaSinkInternal* GetSinkById(const MediaSink::Id& sink_id) const;
 
-  void SetTimerForTest(std::unique_ptr<base::Timer> timer);
+  void SetTimerForTest(std::unique_ptr<base::OneShotTimer> timer);
 
  protected:
   // Called when |discovery_timer_| expires. Informs subclass to report device
@@ -100,7 +100,7 @@
   // the metrics are recorded accurately, a small delay is introduced after a
   // sink list change in order for the discovery process to reach a steady
   // state before the metrics are recorded.
-  std::unique_ptr<base::Timer> discovery_timer_;
+  std::unique_ptr<base::OneShotTimer> discovery_timer_;
 
   // The following fields exist temporarily for sending back discovered sinks to
   // the Media Router extension.
diff --git a/chrome/common/media_router/test/test_helper.cc b/chrome/common/media_router/test/test_helper.cc
index 1bd4289..3318eb2 100644
--- a/chrome/common/media_router/test/test_helper.cc
+++ b/chrome/common/media_router/test/test_helper.cc
@@ -15,9 +15,7 @@
 
 TestMediaSinkService::TestMediaSinkService(
     const OnSinksDiscoveredCallback& callback)
-    : MediaSinkServiceBase(callback),
-      timer_(new base::MockTimer(true /*retain_user_task*/,
-                                 false /*is_repeating*/)) {
+    : MediaSinkServiceBase(callback), timer_(new base::MockOneShotTimer()) {
   SetTimerForTest(base::WrapUnique(timer_));
 }
 
diff --git a/chrome/common/media_router/test/test_helper.h b/chrome/common/media_router/test/test_helper.h
index a6b2d7c..543ae95 100644
--- a/chrome/common/media_router/test/test_helper.h
+++ b/chrome/common/media_router/test/test_helper.h
@@ -19,11 +19,11 @@
   explicit TestMediaSinkService(const OnSinksDiscoveredCallback& callback);
   ~TestMediaSinkService() override;
 
-  base::MockTimer* timer() { return timer_; }
+  base::MockOneShotTimer* timer() { return timer_; }
 
  private:
   // Owned by MediaSinkService.
-  base::MockTimer* timer_;
+  base::MockOneShotTimer* timer_;
   DISALLOW_COPY_AND_ASSIGN(TestMediaSinkService);
 };
 #endif  // !defined(OS_ANDROID)
diff --git a/chrome/common/page_load_metrics/test/weak_mock_timer.cc b/chrome/common/page_load_metrics/test/weak_mock_timer.cc
index 0fe222af..18abcd6a 100644
--- a/chrome/common/page_load_metrics/test/weak_mock_timer.cc
+++ b/chrome/common/page_load_metrics/test/weak_mock_timer.cc
@@ -7,13 +7,12 @@
 namespace page_load_metrics {
 namespace test {
 
-WeakMockTimer::WeakMockTimer()
-    : MockTimer(false /* retain_user_task */, false /* is_repeating */) {}
+WeakMockTimer::WeakMockTimer() {}
 
 WeakMockTimerProvider::WeakMockTimerProvider() {}
 WeakMockTimerProvider::~WeakMockTimerProvider() {}
 
-base::MockTimer* WeakMockTimerProvider::GetMockTimer() const {
+base::MockOneShotTimer* WeakMockTimerProvider::GetMockTimer() const {
   return timer_.get();
 }
 
diff --git a/chrome/common/page_load_metrics/test/weak_mock_timer.h b/chrome/common/page_load_metrics/test/weak_mock_timer.h
index 185b586..20f5c46 100644
--- a/chrome/common/page_load_metrics/test/weak_mock_timer.h
+++ b/chrome/common/page_load_metrics/test/weak_mock_timer.h
@@ -13,7 +13,7 @@
 namespace test {
 
 // WeakMockTimer is a MockTimer that allows clients to keep WeakPtr<>s to it.
-class WeakMockTimer : public base::MockTimer,
+class WeakMockTimer : public base::MockOneShotTimer,
                       public base::SupportsWeakPtr<WeakMockTimer> {
  public:
   WeakMockTimer();
@@ -29,7 +29,7 @@
   WeakMockTimerProvider();
   virtual ~WeakMockTimerProvider();
 
-  base::MockTimer* GetMockTimer() const;
+  base::MockOneShotTimer* GetMockTimer() const;
   void SetMockTimer(base::WeakPtr<WeakMockTimer> timer);
 
  private:
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index a48aa80..c81dc1d05 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -548,10 +548,10 @@
 const char kLanguagePreloadEnginesSyncable[] =
     "settings.language.preload_engines_syncable";
 
-// A string pref (comma-separated list) set to the extension IMEs to be enabled.
-const char kLanguageEnabledExtensionImes[] =
-    "settings.language.enabled_extension_imes";
-const char kLanguageEnabledExtensionImesSyncable[] =
+// A string pref (comma-separated list) set to the extension and ARC IMEs to be
+// enabled.
+const char kLanguageEnabledImes[] = "settings.language.enabled_extension_imes";
+const char kLanguageEnabledImesSyncable[] =
     "settings.language.enabled_extension_imes_syncable";
 
 // A boolean pref set to true if the IME menu is activated.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index ec4043b9..75538d8 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -212,8 +212,8 @@
 extern const char kLanguagePreferredLanguagesSyncable[];
 extern const char kLanguagePreloadEngines[];
 extern const char kLanguagePreloadEnginesSyncable[];
-extern const char kLanguageEnabledExtensionImes[];
-extern const char kLanguageEnabledExtensionImesSyncable[];
+extern const char kLanguageEnabledImes[];
+extern const char kLanguageEnabledImesSyncable[];
 extern const char kLanguageImeMenuActivated[];
 extern const char kLanguageShouldMergeInputMethods[];
 extern const char kLanguageSendFunctionKeys[];
diff --git a/chrome/common/thread_profiler.cc b/chrome/common/thread_profiler.cc
index c363302..a82a03a 100644
--- a/chrome/common/thread_profiler.cc
+++ b/chrome/common/thread_profiler.cc
@@ -15,6 +15,7 @@
 #include "base/threading/sequence_local_storage_slot.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/common/stack_sampling_configuration.h"
+#include "components/metrics/call_stack_profile_builder.h"
 #include "components/metrics/call_stack_profile_metrics_provider.h"
 #include "components/metrics/call_stack_profile_params.h"
 #include "components/metrics/child_call_stack_profile_collector.h"
@@ -192,12 +193,11 @@
     return;
 
   auto profile_builder =
-      std::make_unique<StackSamplingProfiler::SamplingProfileBuilder>(
-          BindRepeating(
-              &ThreadProfiler::ReceiveStartupProfile,
-              GetReceiverCallback(CallStackProfileParams(
-                  GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP,
-                  CallStackProfileParams::MAY_SHUFFLE))));
+      std::make_unique<CallStackProfileBuilder>(BindRepeating(
+          &ThreadProfiler::ReceiveStartupProfile,
+          GetReceiverCallback(CallStackProfileParams(
+              GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP,
+              CallStackProfileParams::MAY_SHUFFLE))));
 
   startup_profiler_ = std::make_unique<StackSamplingProfiler>(
       base::PlatformThread::CurrentId(), kSamplingParams,
@@ -276,12 +276,10 @@
 void ThreadProfiler::StartPeriodicSamplingCollection() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // NB: Destroys the previous profiler as side effect.
-  auto profile_builder =
-      std::make_unique<StackSamplingProfiler::SamplingProfileBuilder>(
-          BindRepeating(&ThreadProfiler::ReceivePeriodicProfile,
-                        GetReceiverCallback(periodic_profile_params_),
-                        owning_thread_task_runner_,
-                        weak_factory_.GetWeakPtr()));
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      BindRepeating(&ThreadProfiler::ReceivePeriodicProfile,
+                    GetReceiverCallback(periodic_profile_params_),
+                    owning_thread_task_runner_, weak_factory_.GetWeakPtr()));
 
   periodic_profiler_ = std::make_unique<StackSamplingProfiler>(
       base::PlatformThread::CurrentId(), kSamplingParams,
diff --git a/chrome/renderer/page_load_metrics/page_timing_metrics_sender_unittest.cc b/chrome/renderer/page_load_metrics/page_timing_metrics_sender_unittest.cc
index 24b9282..710dbf8d 100644
--- a/chrome/renderer/page_load_metrics/page_timing_metrics_sender_unittest.cc
+++ b/chrome/renderer/page_load_metrics/page_timing_metrics_sender_unittest.cc
@@ -13,19 +13,18 @@
 namespace page_load_metrics {
 
 // Thin wrapper around PageTimingMetricsSender that provides access to the
-// MockTimer instance.
+// MockOneShotTimer instance.
 class TestPageTimingMetricsSender : public PageTimingMetricsSender {
  public:
   explicit TestPageTimingMetricsSender(
       std::unique_ptr<PageTimingSender> page_timing_sender,
       mojom::PageLoadTimingPtr initial_timing)
-      : PageTimingMetricsSender(
-            std::move(page_timing_sender),
-            std::unique_ptr<base::Timer>(new base::MockTimer(false, false)),
-            std::move(initial_timing)) {}
+      : PageTimingMetricsSender(std::move(page_timing_sender),
+                                std::make_unique<base::MockOneShotTimer>(),
+                                std::move(initial_timing)) {}
 
-  base::MockTimer* mock_timer() const {
-    return reinterpret_cast<base::MockTimer*>(timer());
+  base::MockOneShotTimer* mock_timer() const {
+    return static_cast<base::MockOneShotTimer*>(timer());
   }
 };
 
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.cold_state_personalized_signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.cold_state_personalized_signin_promo.Nexus_5-19.png
index dfc46d3..fab4239 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.cold_state_personalized_signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.cold_state_personalized_signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png
index d179fb3..2763193 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.hot_state_personalized_signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.hot_state_personalized_signin_promo.Nexus_5-19.png
index ba17c3a..1ca9efc 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.hot_state_personalized_signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.hot_state_personalized_signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-cold_state_personalized_signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-cold_state_personalized_signin_promo.Nexus_5-19.png
index 204de464..1058711 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-cold_state_personalized_signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-cold_state_personalized_signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-download_snippet_placeholder.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-download_snippet_placeholder.Nexus_5-19.png
index 4ac852f..71f0a6e 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-download_snippet_placeholder.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-download_snippet_placeholder.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-hot_state_personalized_signin_promo.Nexus_5-19.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-hot_state_personalized_signin_promo.Nexus_5-19.png
index 8238b94..7acef6cc 100644
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-hot_state_personalized_signin_promo.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-hot_state_personalized_signin_promo.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/BookmarkTest.bookmark_manager_folder_selected.Nexus_5-19.png b/chrome/test/data/android/render_tests/BookmarkTest.bookmark_manager_folder_selected.Nexus_5-19.png
index 9c34a1d..04d36d1 100644
--- a/chrome/test/data/android/render_tests/BookmarkTest.bookmark_manager_folder_selected.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/BookmarkTest.bookmark_manager_folder_selected.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.modern-new_tab_page_scrolled.Nexus_5-19.png b/chrome/test/data/android/render_tests/NewTabPageTest.modern-new_tab_page_scrolled.Nexus_5-19.png
index b3c9e046c..54f9dcf 100644
--- a/chrome/test/data/android/render_tests/NewTabPageTest.modern-new_tab_page_scrolled.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/NewTabPageTest.modern-new_tab_page_scrolled.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png
index 17522570a..d7167e3 100644
--- a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_classic_offline.Nexus_5-19.png b/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_classic_offline.Nexus_5-19.png
index 4b90d83..a58d9fb 100644
--- a/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_classic_offline.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_classic_offline.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_modern_offline.Nexus_5-19.png b/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_modern_offline.Nexus_5-19.png
index d764304..497ec0c 100644
--- a/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_modern_offline.Nexus_5-19.png
+++ b/chrome/test/data/android/render_tests/TileGridLayoutTest.tile_modern_offline.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/webui/cr_elements/cr_input_test.js b/chrome/test/data/webui/cr_elements/cr_input_test.js
index 8d77808..a6445c7 100644
--- a/chrome/test/data/webui/cr_elements/cr_input_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_input_test.js
@@ -157,6 +157,8 @@
   });
 
   test('focusState', function() {
+    assertFalse(crInput.hasAttribute('focused_'));
+
     const underline = crInput.$.underline;
     const label = crInput.$.label;
     const originalLabelColor = getComputedStyle(label).color;
@@ -168,11 +170,19 @@
         test_util.eventToPromise('transitionend', underline);
 
     input.focus();
+    assertTrue(crInput.hasAttribute('focused_'));
     assertTrue(originalLabelColor != getComputedStyle(label).color);
-    return whenTransitionEnd.then(() => {
-      assertEquals('1', getComputedStyle(underline).opacity);
-      assertTrue(0 != underline.offsetWidth);
-    });
+    return whenTransitionEnd
+        .then(() => {
+          assertEquals('1', getComputedStyle(underline).opacity);
+          assertTrue(0 != underline.offsetWidth);
+        })
+        .then(() => {
+          input.blur();
+          assertFalse(crInput.hasAttribute('focused_'));
+          assertEquals('0', getComputedStyle(underline).opacity);
+          assertEquals(0, underline.offsetWidth);
+        });
   });
 
   test('invalidState', function() {
diff --git a/chrome/test/views/accessibility_checker_unittest.cc b/chrome/test/views/accessibility_checker_unittest.cc
index 9167092..97cc9f4c 100644
--- a/chrome/test/views/accessibility_checker_unittest.cc
+++ b/chrome/test/views/accessibility_checker_unittest.cc
@@ -5,14 +5,14 @@
 #include "chrome/test/views/accessibility_checker.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/test/views/chrome_views_test_base.h"
 #include "testing/gtest/include/gtest/gtest-spi.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/button/image_button.h"
-#include "ui/views/test/views_test_base.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
-typedef views::ViewsTestBase AccessibilityCheckerTest;
+using AccessibilityCheckerTest = ChromeViewsTestBase;
 
 // Test that a view that is not accessible will fail the accessibility audit.
 TEST_F(AccessibilityCheckerTest, VerifyAccessibilityCheckerFailAndPass) {
diff --git a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
index 8228318..76e328f 100644
--- a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -392,7 +392,7 @@
               params->opt_args.additional_properties,
               &replace_selected_text_params));
       action->action = ax::mojom::Action::kReplaceSelectedText;
-      action->value = base::UTF8ToUTF16(replace_selected_text_params.value);
+      action->value = replace_selected_text_params.value;
       break;
     }
     case api::automation::ACTION_TYPE_SETVALUE: {
@@ -401,7 +401,7 @@
           api::automation_internal::SetValueParams::Populate(
               params->opt_args.additional_properties, &set_value_params));
       action->action = ax::mojom::Action::kSetValue;
-      action->value = base::UTF8ToUTF16(set_value_params.value);
+      action->value = set_value_params.value;
       break;
     }
     // These actions are currently unused by any existing clients of
diff --git a/chromecast/device/bluetooth/le/BUILD.gn b/chromecast/device/bluetooth/le/BUILD.gn
index 4ceb8fff..8e2fc00 100644
--- a/chromecast/device/bluetooth/le/BUILD.gn
+++ b/chromecast/device/bluetooth/le/BUILD.gn
@@ -64,6 +64,7 @@
   ]
   deps = [
     ":le",
+    "//base",
     "//chromecast/public",
     "//testing/gmock",
   ]
diff --git a/chromecast/device/bluetooth/le/mock_gatt_client_manager.h b/chromecast/device/bluetooth/le/mock_gatt_client_manager.h
index 46ecd42..f900ef3 100644
--- a/chromecast/device/bluetooth/le/mock_gatt_client_manager.h
+++ b/chromecast/device/bluetooth/le/mock_gatt_client_manager.h
@@ -5,6 +5,7 @@
 #ifndef CHROMECAST_DEVICE_BLUETOOTH_LE_MOCK_GATT_CLIENT_MANAGER_H_
 #define CHROMECAST_DEVICE_BLUETOOTH_LE_MOCK_GATT_CLIENT_MANAGER_H_
 
+#include "base/containers/flat_set.h"
 #include "chromecast/device/bluetooth/le/gatt_client_manager.h"
 #include "chromecast/device/bluetooth/le/mock_remote_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -18,12 +19,12 @@
   ~MockGattClientManager();
 
   void AddObserver(Observer* o) override {
-    DCHECK(o && !observer_);
-    observer_ = o;
+    DCHECK(o && !observers_.count(o));
+    observers_.insert(o);
   }
   void RemoveObserver(Observer* o) override {
-    DCHECK(o && o == observer_);
-    observer_ = nullptr;
+    DCHECK(o && observers_.count(o));
+    observers_.erase(o);
   }
 
   MOCK_METHOD1(
@@ -42,7 +43,7 @@
   MOCK_METHOD1(NotifyConnect, void(const bluetooth_v2_shlib::Addr& addr));
   MOCK_METHOD0(task_runner, scoped_refptr<base::SingleThreadTaskRunner>());
 
-  Observer* observer_ = nullptr;
+  base::flat_set<Observer*> observers_;
 };
 
 }  // namespace bluetooth
diff --git a/chromecast/media/cma/backend/audio_decoder_for_mixer.cc b/chromecast/media/cma/backend/audio_decoder_for_mixer.cc
index 59529cd..8a7725e 100644
--- a/chromecast/media/cma/backend/audio_decoder_for_mixer.cc
+++ b/chromecast/media/cma/backend/audio_decoder_for_mixer.cc
@@ -188,6 +188,19 @@
   return rate;
 }
 
+bool AudioDecoderForMixer::GetTimestampedPts(int64_t* timestamp,
+                                             int64_t* pts) const {
+  if (last_push_timestamp_ == kInvalidTimestamp ||
+      last_push_pts_ == kInvalidTimestamp)
+    return false;
+
+  // Hmm this timestamp may be in the future. That should be fine, but it's
+  // a bit weird.
+  *timestamp = last_push_timestamp_;
+  *pts = last_push_pts_;
+  return true;
+}
+
 int64_t AudioDecoderForMixer::GetCurrentPts() const {
   if (paused_pts_ != kInvalidTimestamp)
     return paused_pts_;
diff --git a/chromecast/media/cma/backend/audio_decoder_for_mixer.h b/chromecast/media/cma/backend/audio_decoder_for_mixer.h
index 6a88a7e..5ac2e86 100644
--- a/chromecast/media/cma/backend/audio_decoder_for_mixer.h
+++ b/chromecast/media/cma/backend/audio_decoder_for_mixer.h
@@ -46,6 +46,7 @@
   virtual bool Pause();
   virtual bool Resume();
   virtual float SetPlaybackRate(float rate);
+  virtual bool GetTimestampedPts(int64_t* timestamp, int64_t* pts) const;
   virtual int64_t GetCurrentPts() const;
 
   // MediaPipelineBackend::AudioDecoder implementation:
diff --git a/chromecast/media/cma/backend/video/av_sync_video.cc b/chromecast/media/cma/backend/video/av_sync_video.cc
index 90571ac..276ce06 100644
--- a/chromecast/media/cma/backend/video/av_sync_video.cc
+++ b/chromecast/media/cma/backend/video/av_sync_video.cc
@@ -19,7 +19,6 @@
 namespace media {
 
 namespace {
-const int64_t kInvalidTimestamp = std::numeric_limits<int64_t>::min();
 
 // Threshold where the audio and video pts are far enough apart such that we
 // want to do a small correction.
@@ -111,33 +110,22 @@
     first_video_pts_received_ = true;
   }
 
-  // TODO(almasrymina): using GetCurrentPts is vulnerable to pairing it with an
-  // outdated 'now' if the thread gets descheduled in between. We currently see
-  // extraneous corrections on real hardware and it's probably due to this.
-  //
-  // Consider either going back to a NotifyAudioBufferPushed approach that
-  // works, or improving GetCurrentPts such as it returns the timestamp this
-  // was last updated at.
-  // TODO(almasrymina): b/78592779. AudioDecoderForMixer::GetCurrentPts seems
-  // to return invalid values which are not kInvalidTimestamp, for unknown
-  // reasons. As a workaround until that issue is root caused, ignore
-  // GetCurrentPts values that are way off.
-  int64_t audio_pts = backend_->audio_decoder()->GetCurrentPts();
-  if (abs(audio_pts - new_current_vpts) >
-          base::TimeDelta::FromHours(1).InMicroseconds() ||
-      audio_pts == kInvalidTimestamp) {
-    LOG(WARNING) << "Audio decoder returned invalid pts=" << audio_pts
-                 << " new_current_vpts=" << new_current_vpts;
-  } else {
-    audio_pts_->AddSample(now, backend_->audio_decoder()->GetCurrentPts(), 1.0);
+  int64_t new_current_apts = 0;
+  int64_t new_apts_timestamp = 0;
 
-    if (!first_audio_pts_received_) {
-      LOG(INFO) << "Audio starting at difference="
-                << (backend_->MonotonicClockNow() -
-                    backend_->audio_decoder()->GetCurrentPts()) -
-                       playback_start_timestamp_us_;
-      first_audio_pts_received_ = true;
-    }
+  if (!backend_->audio_decoder()->GetTimestampedPts(&new_apts_timestamp,
+                                                    &new_current_apts)) {
+    LOG(ERROR) << "Failed to get APTS.";
+    return;
+  }
+
+  audio_pts_->AddSample(new_apts_timestamp, new_current_apts, 1.0);
+
+  if (!first_audio_pts_received_) {
+    LOG(INFO) << "Audio starting at difference="
+              << (new_apts_timestamp - new_current_apts) -
+                     playback_start_timestamp_us_;
+    first_audio_pts_received_ = true;
   }
 
   if (video_pts_->num_samples() < 10 || audio_pts_->num_samples() < 20) {
@@ -150,10 +138,13 @@
   int64_t current_vpts;
   double vpts_slope;
   double apts_slope;
-  video_pts_->EstimateY(now, &current_vpts, &error);
-  audio_pts_->EstimateY(now, &current_apts, &error);
-  video_pts_->EstimateSlope(&vpts_slope, &error);
-  audio_pts_->EstimateSlope(&apts_slope, &error);
+  if (!video_pts_->EstimateY(now, &current_vpts, &error) ||
+      !audio_pts_->EstimateY(now, &current_apts, &error) ||
+      !video_pts_->EstimateSlope(&vpts_slope, &error) ||
+      !audio_pts_->EstimateSlope(&apts_slope, &error)) {
+    VLOG(3) << "Failed to get linear regression estimate.";
+    return;
+  }
 
   error_->AddSample(now, current_apts - current_vpts, 1.0);
 
@@ -165,14 +156,17 @@
   }
 
   int64_t difference;
-  error_->EstimateY(now, &difference, &error);
+  if (!error_->EstimateY(now, &difference, &error)) {
+    VLOG(3) << "Failed to get linear regression estimate.";
+    return;
+  }
 
   VLOG(3) << "Pts_monitor."
           << " difference=" << difference / 1000 << " apts_slope=" << apts_slope
           << " vpts_slope=" << vpts_slope
           << " current_audio_playback_rate_=" << current_audio_playback_rate_
           << " current_vpts=" << new_current_vpts
-          << " current_apts=" << backend_->audio_decoder()->GetCurrentPts()
+          << " current_apts=" << new_current_apts
           << " current_time=" << backend_->MonotonicClockNow()
           << " video_start_error="
           << (new_vpts_timestamp - new_current_vpts -
@@ -183,26 +177,20 @@
   ++av_sync_difference_count_;
 
   if (abs(difference) > kSoftCorrectionThresholdUs) {
-    SoftCorrection(now);
+    SoftCorrection(now, current_vpts, current_apts, apts_slope, vpts_slope,
+                   difference);
   } else {
-    InSyncCorrection(now);
+    InSyncCorrection(now, current_vpts, current_apts, apts_slope, vpts_slope,
+                     difference);
   }
 }
 
-void AvSyncVideo::SoftCorrection(int64_t now) {
-  int64_t current_apts = 0;
-  int64_t current_vpts = 0;
-  int64_t difference = 0;
-  double error = 0.0;
-  double apts_slope = 0.0;
-  double vpts_slope = 0.0;
-
-  video_pts_->EstimateY(now, &current_vpts, &error);
-  audio_pts_->EstimateY(now, &current_apts, &error);
-  video_pts_->EstimateSlope(&vpts_slope, &error);
-  audio_pts_->EstimateSlope(&apts_slope, &error);
-  error_->EstimateY(now, &difference, &error);
-
+void AvSyncVideo::SoftCorrection(int64_t now,
+                                 int64_t current_vpts,
+                                 int64_t current_apts,
+                                 double apts_slope,
+                                 double vpts_slope,
+                                 int64_t difference) {
   if (audio_pts_->num_samples() < 50) {
     VLOG(4) << "Not enough apts samples=" << audio_pts_->num_samples();
     return;
@@ -253,23 +241,16 @@
 // sufficiently close to each other, and we no longer need to bridge a gap
 // between them. This method will have it so that vpts_slope == apts_slope, and
 // the content should continue to play in sync from here on out.
-void AvSyncVideo::InSyncCorrection(int64_t now) {
+void AvSyncVideo::InSyncCorrection(int64_t now,
+                                   int64_t current_vpts,
+                                   int64_t current_apts,
+                                   double apts_slope,
+                                   double vpts_slope,
+                                   int64_t difference) {
   if (audio_pts_->num_samples() < 50 || !in_soft_correction_) {
     return;
   }
 
-  int64_t current_apts = 0;
-  int64_t current_vpts = 0;
-  int64_t difference = 0;
-  double error = 0.0;
-  double apts_slope = 0.0;
-  double vpts_slope = 0.0;
-
-  video_pts_->EstimateY(now, &current_vpts, &error);
-  audio_pts_->EstimateY(now, &current_apts, &error);
-  video_pts_->EstimateSlope(&vpts_slope, &error);
-  audio_pts_->EstimateSlope(&apts_slope, &error);
-
   current_audio_playback_rate_ *= vpts_slope / apts_slope;
   current_audio_playback_rate_ =
       backend_->audio_decoder()->SetPlaybackRate(current_audio_playback_rate_);
@@ -340,6 +321,11 @@
   backend_->video_decoder()->GetCurrentPts(&accurate_vpts_timestamp,
                                            &accurate_vpts);
 
+  int64_t accurate_apts = 0;
+  int64_t accurate_apts_timestamp = 0;
+  backend_->video_decoder()->GetCurrentPts(&accurate_apts_timestamp,
+                                           &accurate_apts);
+
   LOG(INFO) << "Playback diagnostics:"
             << " CurrentContentRefreshRate="
             << backend_->video_decoder()->GetCurrentContentRefreshRate()
@@ -352,15 +338,17 @@
             << accurate_vpts_timestamp - accurate_vpts -
                    playback_start_timestamp_us_
             << " audio_start_error_estimate="
-            << backend_->MonotonicClockNow() -
-                   backend_->audio_decoder()->GetCurrentPts() -
+            << accurate_apts_timestamp - accurate_apts -
                    playback_start_timestamp_us_;
 
   int64_t current_vpts = 0;
   int64_t current_apts = 0;
   double error = 0.0;
-  video_pts_->EstimateY(current_time, &current_vpts, &error);
-  audio_pts_->EstimateY(current_time, &current_apts, &error);
+  if (!video_pts_->EstimateY(current_time, &current_vpts, &error) ||
+      !audio_pts_->EstimateY(current_time, &current_apts, &error)) {
+    VLOG(3) << "Failed to get linear regression estimate.";
+    return;
+  }
 
   if (delegate_) {
     delegate_->NotifyAvSyncPlaybackStatistics(
diff --git a/chromecast/media/cma/backend/video/av_sync_video.h b/chromecast/media/cma/backend/video/av_sync_video.h
index c96b31d..ce03cf8 100644
--- a/chromecast/media/cma/backend/video/av_sync_video.h
+++ b/chromecast/media/cma/backend/video/av_sync_video.h
@@ -59,8 +59,18 @@
   void StopAvSync();
   void GatherPlaybackStatistics();
 
-  void SoftCorrection(int64_t now);
-  void InSyncCorrection(int64_t now);
+  void SoftCorrection(int64_t now,
+                      int64_t current_vpts,
+                      int64_t current_apts,
+                      double apts_slope,
+                      double vpts_slope,
+                      int64_t difference);
+  void InSyncCorrection(int64_t now,
+                        int64_t current_vpts,
+                        int64_t current_apts,
+                        double apts_slope,
+                        double vpts_slope,
+                        int64_t difference);
 
   Delegate* delegate_ = nullptr;
 
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn
index 867112d..e9ea1d7 100644
--- a/chromeos/components/tether/BUILD.gn
+++ b/chromeos/components/tether/BUILD.gn
@@ -142,7 +142,7 @@
     # TODO(hansberry): Remove //chromeos/services/secure_channel dependency when
     # SecureChannelClient migration is complete.
     "//chromeos/services/secure_channel",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
+    "//chromeos/services/secure_channel/public/cpp/shared",
     "//components/cryptauth",
     "//components/cryptauth/ble",
     "//components/pref_registry",
@@ -231,7 +231,7 @@
     # SecureChannelClient migration is complete.
     "//chromeos/services/secure_channel",
     "//chromeos/services/secure_channel/public/cpp/client:test_support",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
+    "//chromeos/services/secure_channel/public/cpp/shared",
     "//components/cryptauth",
     "//components/cryptauth:test_support",
     "//components/cryptauth/ble:test_support",
@@ -306,7 +306,7 @@
     "//chromeos/services/secure_channel",
     "//chromeos/services/secure_channel:test_support",
     "//chromeos/services/secure_channel/public/cpp/client:test_support",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
+    "//chromeos/services/secure_channel/public/cpp/shared",
     "//components/cryptauth",
     "//components/cryptauth:test_support",
     "//components/cryptauth/ble",
diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/fake_power_manager_client.cc
index d9af0eb..bcea7f0 100644
--- a/chromeos/dbus/fake_power_manager_client.cc
+++ b/chromeos/dbus/fake_power_manager_client.cc
@@ -102,6 +102,13 @@
 
 void FakePowerManagerClient::IncreaseKeyboardBrightness() {}
 
+void FakePowerManagerClient::GetKeyboardBrightnessPercent(
+    DBusMethodCallback<double> callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), keyboard_brightness_percent_));
+}
+
 const base::Optional<power_manager::PowerSupplyProperties>&
 FakePowerManagerClient::GetLastStatus() {
   return props_;
@@ -304,6 +311,10 @@
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
+void FakePowerManagerClient::DeferScreenDim() {
+  num_defer_screen_dim_calls_++;
+}
+
 bool FakePowerManagerClient::PopVideoActivityReport() {
   CHECK(!video_activity_reports_.empty());
   bool fullscreen = video_activity_reports_.front();
@@ -357,6 +368,11 @@
     observer.PowerButtonEventReceived(down, timestamp);
 }
 
+void FakePowerManagerClient::SendScreenDimImminent() {
+  for (auto& observer : observers_)
+    observer.ScreenDimImminent();
+}
+
 void FakePowerManagerClient::SetLidState(LidState state,
                                          const base::TimeTicks& timestamp) {
   lid_state_ = state;
diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/fake_power_manager_client.h
index e8d8fe2..57efad4 100644
--- a/chromeos/dbus/fake_power_manager_client.h
+++ b/chromeos/dbus/fake_power_manager_client.h
@@ -43,6 +43,7 @@
   int num_set_is_projecting_calls() const {
     return num_set_is_projecting_calls_;
   }
+  int num_defer_screen_dim_calls() const { return num_defer_screen_dim_calls_; }
   double screen_brightness_percent() const {
     return screen_brightness_percent_.value();
   }
@@ -78,6 +79,8 @@
   void GetScreenBrightnessPercent(DBusMethodCallback<double> callback) override;
   void DecreaseKeyboardBrightness() override;
   void IncreaseKeyboardBrightness() override;
+  void GetKeyboardBrightnessPercent(
+      DBusMethodCallback<double> callback) override;
   const base::Optional<power_manager::PowerSupplyProperties>& GetLastStatus()
       override;
   void RequestStatusUpdate() override;
@@ -109,6 +112,7 @@
                      VoidDBusMethodCallback callback) override;
   void DeleteArcTimers(const std::string& tag,
                        VoidDBusMethodCallback callback) override;
+  void DeferScreenDim() override;
 
   // Pops the first report from |video_activity_reports_|, returning whether the
   // activity was fullscreen or not. There must be at least one report.
@@ -133,6 +137,9 @@
   // Notifies observers that the power button has been pressed or released.
   void SendPowerButtonEvent(bool down, const base::TimeTicks& timestamp);
 
+  // Notifies observers that the screen is about to be dimmed.
+  void SendScreenDimImminent();
+
   // Sets |lid_state_| or |tablet_mode_| and notifies |observers_| about the
   // change.
   void SetLidState(LidState state, const base::TimeTicks& timestamp);
@@ -164,6 +171,10 @@
     screen_brightness_percent_ = percent;
   }
 
+  void set_keyboard_brightness_percent(const base::Optional<double>& percent) {
+    keyboard_brightness_percent_ = percent;
+  }
+
  private:
   // Callback that will be run by asynchronous suspend delays to report
   // readiness.
@@ -186,6 +197,7 @@
   int num_set_policy_calls_ = 0;
   int num_set_is_projecting_calls_ = 0;
   int num_set_backlights_forced_off_calls_ = 0;
+  int num_defer_screen_dim_calls_ = 0;
 
   // Number of pending suspend readiness callbacks.
   int num_pending_suspend_readiness_callbacks_ = 0;
@@ -193,6 +205,9 @@
   // Current screen brightness in the range [0.0, 100.0].
   base::Optional<double> screen_brightness_percent_;
 
+  // Current keyboard brightness in the range [0.0, 100.0].
+  base::Optional<double> keyboard_brightness_percent_;
+
   // Last screen brightness requested via SetScreenBrightnessPercent().
   // Unlike |screen_brightness_percent_|, this value will not be changed by
   // SetBacklightsForcedOff() method - a method that implicitly changes screen
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc
index 2a3156eb..2332897 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power_manager_client.cc
@@ -228,8 +228,21 @@
         power_manager::kGetScreenBrightnessPercentMethod);
     power_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::BindOnce(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+        base::BindOnce(
+            &PowerManagerClientImpl::OnGetScreenOrKeyboardBrightnessPercent,
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void GetKeyboardBrightnessPercent(
+      DBusMethodCallback<double> callback) override {
+    dbus::MethodCall method_call(
+        power_manager::kPowerManagerInterface,
+        power_manager::kGetKeyboardBrightnessPercentMethod);
+    power_manager_proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(
+            &PowerManagerClientImpl::OnGetScreenOrKeyboardBrightnessPercent,
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void RequestStatusUpdate() override {
@@ -450,6 +463,10 @@
         base::BindOnce(&OnVoidDBusMethod, std::move(callback)));
   }
 
+  void DeferScreenDim() override {
+    SimpleMethodCallToPowerManager(power_manager::kDeferScreenDimMethod);
+  }
+
  protected:
   void Init(dbus::Bus* bus) override {
     power_manager_proxy_ = bus->GetObjectProxy(
@@ -483,6 +500,8 @@
          &PowerManagerClientImpl::SuspendDoneReceived},
         {power_manager::kDarkSuspendImminentSignal,
          &PowerManagerClientImpl::DarkSuspendImminentReceived},
+        {power_manager::kScreenDimImminentSignal,
+         &PowerManagerClientImpl::ScreenDimImminentReceived},
         {power_manager::kIdleActionImminentSignal,
          &PowerManagerClientImpl::IdleActionImminentReceived},
         {power_manager::kIdleActionDeferredSignal,
@@ -648,13 +667,10 @@
     }
   }
 
-  void OnGetScreenBrightnessPercent(DBusMethodCallback<double> callback,
-                                    dbus::Response* response) {
+  void OnGetScreenOrKeyboardBrightnessPercent(
+      DBusMethodCallback<double> callback,
+      dbus::Response* response) {
     if (!response) {
-      if (!system::StatisticsProvider::GetInstance()->IsRunningOnVm()) {
-        POWER_LOG(ERROR) << "Error calling "
-                         << power_manager::kGetScreenBrightnessPercentMethod;
-      }
       std::move(callback).Run(base::nullopt);
       return;
     }
@@ -876,6 +892,11 @@
     base::PowerMonitorDeviceSource::HandleSystemResumed();
   }
 
+  void ScreenDimImminentReceived(dbus::Signal* signal) {
+    for (auto& observer : observers_)
+      observer.ScreenDimImminent();
+  }
+
   void IdleActionImminentReceived(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
     power_manager::IdleActionImminent proto;
diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power_manager_client.h
index fa6be97..45245e3 100644
--- a/chromeos/dbus/power_manager_client.h
+++ b/chromeos/dbus/power_manager_client.h
@@ -133,6 +133,9 @@
     virtual void TabletModeEventReceived(TabletMode mode,
                                          const base::TimeTicks& timestamp) {}
 
+    // Called just before the screen is dimmed in response to user inactivity.
+    virtual void ScreenDimImminent() {}
+
     // Called when the idle action will be performed after
     // |time_until_idle_action|.
     virtual void IdleActionImminent(
@@ -192,6 +195,11 @@
   // Increases the keyboard brightness.
   virtual void IncreaseKeyboardBrightness() = 0;
 
+  // Similar to GetScreenBrightnessPercent, but gets the keyboard brightness
+  // instead.
+  virtual void GetKeyboardBrightnessPercent(
+      DBusMethodCallback<double> callback) = 0;
+
   // Returns the last power status that was received from D-Bus, if any.
   virtual const base::Optional<power_manager::PowerSupplyProperties>&
   GetLastStatus() = 0;
@@ -293,6 +301,11 @@
   virtual void DeleteArcTimers(const std::string& tag,
                                VoidDBusMethodCallback callback) = 0;
 
+  // Instructs powerd to defer dimming the screen. This only has an effect when
+  // called shortly (i.e. seconds) after observers have received
+  // ScreenDimImminent notifications.
+  virtual void DeferScreenDim() = 0;
+
   // Creates the instance.
   static PowerManagerClient* Create(DBusClientImplementationType type);
 
diff --git a/chromeos/services/secure_channel/BUILD.gn b/chromeos/services/secure_channel/BUILD.gn
index 363644b..1fea8ae 100644
--- a/chromeos/services/secure_channel/BUILD.gn
+++ b/chromeos/services/secure_channel/BUILD.gn
@@ -12,6 +12,8 @@
     "active_connection_manager.h",
     "active_connection_manager_impl.cc",
     "active_connection_manager_impl.h",
+    "authenticated_channel.cc",
+    "authenticated_channel.h",
     "authenticated_channel_impl.cc",
     "authenticated_channel_impl.h",
     "ble_advertiser.cc",
@@ -115,7 +117,6 @@
     "//chromeos",
     "//chromeos/components/proximity_auth/logging",
     "//chromeos/services/secure_channel/public/cpp/shared",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
     "//chromeos/services/secure_channel/public/mojom",
     "//components/cryptauth",
     "//components/cryptauth/ble",
@@ -135,6 +136,8 @@
   sources = [
     "fake_active_connection_manager.cc",
     "fake_active_connection_manager.h",
+    "fake_authenticated_channel.cc",
+    "fake_authenticated_channel.h",
     "fake_ble_advertiser.cc",
     "fake_ble_advertiser.h",
     "fake_ble_connection_manager.cc",
@@ -183,7 +186,6 @@
     "//base",
     "//base/test:test_support",
     "//chromeos/services/secure_channel/public/cpp/shared",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
     "//chromeos/services/secure_channel/public/mojom",
     "//components/cryptauth:cryptauth",
     "//device/bluetooth:bluetooth",
@@ -224,8 +226,6 @@
     "//base/test:test_support",
     "//chromeos/services/secure_channel/public/cpp/client:unit_tests",
     "//chromeos/services/secure_channel/public/cpp/shared",
-    "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
-    "//chromeos/services/secure_channel/public/cpp/shared:test_support",
     "//chromeos/services/secure_channel/public/mojom",
     "//chromeos/services/secure_channel/public/mojom:unit_tests",
     "//components/cryptauth:test_support",
diff --git a/chromeos/services/secure_channel/active_connection_manager.cc b/chromeos/services/secure_channel/active_connection_manager.cc
index fe28d00..8124daae 100644
--- a/chromeos/services/secure_channel/active_connection_manager.cc
+++ b/chromeos/services/secure_channel/active_connection_manager.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/active_connection_manager_impl_unittest.cc b/chromeos/services/secure_channel/active_connection_manager_impl_unittest.cc
index d83675c7..8207b1e 100644
--- a/chromeos/services/secure_channel/active_connection_manager_impl_unittest.cc
+++ b/chromeos/services/secure_channel/active_connection_manager_impl_unittest.cc
@@ -13,10 +13,10 @@
 #include "base/unguessable_token.h"
 #include "chromeos/services/secure_channel/connection_details.h"
 #include "chromeos/services/secure_channel/fake_active_connection_manager.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
 #include "chromeos/services/secure_channel/fake_multiplexed_channel.h"
 #include "chromeos/services/secure_channel/multiplexed_channel_impl.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.cc b/chromeos/services/secure_channel/authenticated_channel.cc
similarity index 95%
rename from chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.cc
rename to chromeos/services/secure_channel/authenticated_channel.cc
index cea1afb4..e4afa0c 100644
--- a/chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.cc
+++ b/chromeos/services/secure_channel/authenticated_channel.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 #include "base/callback.h"
 #include "base/guid.h"
diff --git a/chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h b/chromeos/services/secure_channel/authenticated_channel.h
similarity index 91%
rename from chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h
rename to chromeos/services/secure_channel/authenticated_channel.h
index 293e2a2..72e589f 100644
--- a/chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h
+++ b/chromeos/services/secure_channel/authenticated_channel.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_AUTHENTICATED_CHANNEL_H_
-#define CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_AUTHENTICATED_CHANNEL_H_
+#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_H_
+#define CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_H_
 
 #include <string>
 
@@ -82,4 +82,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_AUTHENTICATED_CHANNEL_H_
+#endif  // CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_H_
diff --git a/chromeos/services/secure_channel/authenticated_channel_impl.h b/chromeos/services/secure_channel/authenticated_channel_impl.h
index 599ea68..14a1ed2 100644
--- a/chromeos/services/secure_channel/authenticated_channel_impl.h
+++ b/chromeos/services/secure_channel/authenticated_channel_impl.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "components/cryptauth/secure_channel.h"
 
 namespace cryptauth {
diff --git a/chromeos/services/secure_channel/authenticated_channel_impl_unittest.cc b/chromeos/services/secure_channel/authenticated_channel_impl_unittest.cc
index 92a8fdd..1c8786b6 100644
--- a/chromeos/services/secure_channel/authenticated_channel_impl_unittest.cc
+++ b/chromeos/services/secure_channel/authenticated_channel_impl_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/bind.h"
 #include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "components/cryptauth/fake_connection.h"
 #include "components/cryptauth/fake_secure_channel.h"
diff --git a/chromeos/services/secure_channel/ble_connection_manager.cc b/chromeos/services/secure_channel/ble_connection_manager.cc
index 40e72bd9..cc32704 100644
--- a/chromeos/services/secure_channel/ble_connection_manager.cc
+++ b/chromeos/services/secure_channel/ble_connection_manager.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "components/cryptauth/remote_device_ref.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
index 08a90fc4..205e332 100644
--- a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
+++ b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
@@ -19,13 +19,13 @@
 #include "chromeos/services/secure_channel/ble_listener_failure_type.h"
 #include "chromeos/services/secure_channel/ble_scanner_impl.h"
 #include "chromeos/services/secure_channel/ble_synchronizer.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_ble_advertiser.h"
 #include "chromeos/services/secure_channel/fake_ble_scanner.h"
 #include "chromeos/services/secure_channel/fake_ble_service_data_helper.h"
 #include "chromeos/services/secure_channel/fake_ble_synchronizer.h"
 #include "chromeos/services/secure_channel/fake_secure_channel_disconnector.h"
 #include "chromeos/services/secure_channel/fake_timer_factory.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/secure_channel_disconnector_impl.h"
 #include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h"
 #include "components/cryptauth/fake_connection.h"
diff --git a/chromeos/services/secure_channel/ble_initiator_operation.cc b/chromeos/services/secure_channel/ble_initiator_operation.cc
index 1905e79..056adfe 100644
--- a/chromeos/services/secure_channel/ble_initiator_operation.cc
+++ b/chromeos/services/secure_channel/ble_initiator_operation.cc
@@ -8,8 +8,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/ble_connection_manager.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/ble_initiator_operation_unittest.cc b/chromeos/services/secure_channel/ble_initiator_operation_unittest.cc
index c84688c..d929bdb 100644
--- a/chromeos/services/secure_channel/ble_initiator_operation_unittest.cc
+++ b/chromeos/services/secure_channel/ble_initiator_operation_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/test/test_simple_task_runner.h"
 #include "chromeos/services/secure_channel/ble_initiator_failure_type.h"
 #include "chromeos/services/secure_channel/device_id_pair.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
 #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/ble_listener_operation.cc b/chromeos/services/secure_channel/ble_listener_operation.cc
index 81f1dde..632f5ac4 100644
--- a/chromeos/services/secure_channel/ble_listener_operation.cc
+++ b/chromeos/services/secure_channel/ble_listener_operation.cc
@@ -8,8 +8,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/ble_connection_manager.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/ble_listener_operation_unittest.cc b/chromeos/services/secure_channel/ble_listener_operation_unittest.cc
index c3c03db41..a0312c9 100644
--- a/chromeos/services/secure_channel/ble_listener_operation_unittest.cc
+++ b/chromeos/services/secure_channel/ble_listener_operation_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/test/test_simple_task_runner.h"
 #include "chromeos/services/secure_channel/ble_listener_failure_type.h"
 #include "chromeos/services/secure_channel/device_id_pair.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
 #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/connect_to_device_operation_base_unittest.cc b/chromeos/services/secure_channel/connect_to_device_operation_base_unittest.cc
index fd3bac84..93973d5 100644
--- a/chromeos/services/secure_channel/connect_to_device_operation_base_unittest.cc
+++ b/chromeos/services/secure_channel/connect_to_device_operation_base_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "chromeos/services/secure_channel/device_id_pair.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/connection_attempt_base.h b/chromeos/services/secure_channel/connection_attempt_base.h
index 88edae83..ab51d289 100644
--- a/chromeos/services/secure_channel/connection_attempt_base.h
+++ b/chromeos/services/secure_channel/connection_attempt_base.h
@@ -12,12 +12,12 @@
 #include "base/observer_list.h"
 #include "base/stl_util.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/connect_to_device_operation.h"
 #include "chromeos/services/secure_channel/connection_attempt.h"
 #include "chromeos/services/secure_channel/connection_attempt_details.h"
 #include "chromeos/services/secure_channel/connection_details.h"
 #include "chromeos/services/secure_channel/pending_connection_request.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 
diff --git a/chromeos/services/secure_channel/connection_attempt_base_unittest.cc b/chromeos/services/secure_channel/connection_attempt_base_unittest.cc
index 49224a8..a41fab6 100644
--- a/chromeos/services/secure_channel/connection_attempt_base_unittest.cc
+++ b/chromeos/services/secure_channel/connection_attempt_base_unittest.cc
@@ -16,6 +16,7 @@
 #include "chromeos/services/secure_channel/connection_medium.h"
 #include "chromeos/services/secure_channel/connection_role.h"
 #include "chromeos/services/secure_channel/device_id_pair.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
 #include "chromeos/services/secure_channel/fake_connect_to_device_operation.h"
 #include "chromeos/services/secure_channel/fake_connection_attempt_delegate.h"
@@ -23,7 +24,6 @@
 #include "chromeos/services/secure_channel/fake_pending_connection_request.h"
 #include "chromeos/services/secure_channel/pending_connection_request_delegate.h"
 #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/fake_active_connection_manager.cc b/chromeos/services/secure_channel/fake_active_connection_manager.cc
index aa60c02..d2f70068 100644
--- a/chromeos/services/secure_channel/fake_active_connection_manager.cc
+++ b/chromeos/services/secure_channel/fake_active_connection_manager.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.cc b/chromeos/services/secure_channel/fake_authenticated_channel.cc
similarity index 93%
rename from chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.cc
rename to chromeos/services/secure_channel/fake_authenticated_channel.cc
index 5c914c1..003eea2 100644
--- a/chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.cc
+++ b/chromeos/services/secure_channel/fake_authenticated_channel.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h b/chromeos/services/secure_channel/fake_authenticated_channel.h
similarity index 88%
rename from chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h
rename to chromeos/services/secure_channel/fake_authenticated_channel.h
index 0deee146..094b75ee 100644
--- a/chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h
+++ b/chromeos/services/secure_channel/fake_authenticated_channel.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_FAKE_AUTHENTICATED_CHANNEL_H_
-#define CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_FAKE_AUTHENTICATED_CHANNEL_H_
+#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_AUTHENTICATED_CHANNEL_H_
+#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_AUTHENTICATED_CHANNEL_H_
 
 #include <string>
 #include <tuple>
@@ -12,7 +12,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 
 namespace chromeos {
@@ -89,4 +89,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_SHARED_FAKE_AUTHENTICATED_CHANNEL_H_
+#endif  // CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_AUTHENTICATED_CHANNEL_H_
diff --git a/chromeos/services/secure_channel/fake_connection_attempt_delegate.cc b/chromeos/services/secure_channel/fake_connection_attempt_delegate.cc
index 3029b3a..9c7e192 100644
--- a/chromeos/services/secure_channel/fake_connection_attempt_delegate.cc
+++ b/chromeos/services/secure_channel/fake_connection_attempt_delegate.cc
@@ -5,7 +5,7 @@
 #include "chromeos/services/secure_channel/fake_connection_attempt_delegate.h"
 
 #include "base/logging.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/fake_pending_connection_manager.cc b/chromeos/services/secure_channel/fake_pending_connection_manager.cc
index 6904603..e4ab035 100644
--- a/chromeos/services/secure_channel/fake_pending_connection_manager.cc
+++ b/chromeos/services/secure_channel/fake_pending_connection_manager.cc
@@ -8,7 +8,7 @@
 #include <iterator>
 
 #include "base/logging.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/multiplexed_channel_impl.h b/chromeos/services/secure_channel/multiplexed_channel_impl.h
index 8cad1c8..9ce5921 100644
--- a/chromeos/services/secure_channel/multiplexed_channel_impl.h
+++ b/chromeos/services/secure_channel/multiplexed_channel_impl.h
@@ -11,9 +11,9 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/connection_details.h"
 #include "chromeos/services/secure_channel/multiplexed_channel.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "chromeos/services/secure_channel/single_client_message_proxy.h"
 
diff --git a/chromeos/services/secure_channel/multiplexed_channel_impl_unittest.cc b/chromeos/services/secure_channel/multiplexed_channel_impl_unittest.cc
index c192364..0bf45b1df 100644
--- a/chromeos/services/secure_channel/multiplexed_channel_impl_unittest.cc
+++ b/chromeos/services/secure_channel/multiplexed_channel_impl_unittest.cc
@@ -14,11 +14,11 @@
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/services/secure_channel/connection_details.h"
 #include "chromeos/services/secure_channel/connection_medium.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
 #include "chromeos/services/secure_channel/fake_connection_delegate.h"
 #include "chromeos/services/secure_channel/fake_multiplexed_channel.h"
 #include "chromeos/services/secure_channel/fake_single_client_message_proxy.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/single_client_message_proxy_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chromeos/services/secure_channel/pending_connection_manager.cc b/chromeos/services/secure_channel/pending_connection_manager.cc
index a001129..a48b52c 100644
--- a/chromeos/services/secure_channel/pending_connection_manager.cc
+++ b/chromeos/services/secure_channel/pending_connection_manager.cc
@@ -4,7 +4,7 @@
 
 #include "chromeos/services/secure_channel/pending_connection_manager.h"
 
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/pending_connection_manager_impl.cc b/chromeos/services/secure_channel/pending_connection_manager_impl.cc
index a571597..e9b5517 100644
--- a/chromeos/services/secure_channel/pending_connection_manager_impl.cc
+++ b/chromeos/services/secure_channel/pending_connection_manager_impl.cc
@@ -8,11 +8,11 @@
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/ble_initiator_connection_attempt.h"
 #include "chromeos/services/secure_channel/ble_listener_connection_attempt.h"
 #include "chromeos/services/secure_channel/pending_ble_initiator_connection_request.h"
 #include "chromeos/services/secure_channel/pending_ble_listener_connection_request.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/pending_connection_manager_impl_unittest.cc b/chromeos/services/secure_channel/pending_connection_manager_impl_unittest.cc
index fc7d732..9224a48 100644
--- a/chromeos/services/secure_channel/pending_connection_manager_impl_unittest.cc
+++ b/chromeos/services/secure_channel/pending_connection_manager_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/services/secure_channel/ble_initiator_connection_attempt.h"
 #include "chromeos/services/secure_channel/ble_listener_connection_attempt.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
 #include "chromeos/services/secure_channel/fake_connection_attempt.h"
@@ -21,7 +22,6 @@
 #include "chromeos/services/secure_channel/fake_pending_connection_request.h"
 #include "chromeos/services/secure_channel/pending_ble_initiator_connection_request.h"
 #include "chromeos/services/secure_channel/pending_ble_listener_connection_request.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h b/chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h
index 379a471b..1c903fc 100644
--- a/chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h
+++ b/chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "chromeos/services/secure_channel/public/cpp/client/connection_attempt.h"
 #include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/secure_channel/public/cpp/shared/BUILD.gn b/chromeos/services/secure_channel/public/cpp/shared/BUILD.gn
index 41bd9f4..bb9d29c 100644
--- a/chromeos/services/secure_channel/public/cpp/shared/BUILD.gn
+++ b/chromeos/services/secure_channel/public/cpp/shared/BUILD.gn
@@ -4,24 +4,6 @@
 
 source_set("shared") {
   sources = [
-    "authenticated_channel.cc",
-    "authenticated_channel.h",
-  ]
-
-  deps = [
-    "//base",
-    "//chromeos/components/proximity_auth/logging",
-    "//chromeos/services/secure_channel/public/mojom",
-    "//mojo/public/cpp/bindings",
-    "//services/service_manager/public/cpp",
-  ]
-}
-
-# Note: ConnectionPriority is in a separate target to avoid a circular
-# dependency between //chromeos/services/secure_channel/public/mojom and
-# //chromeos/services/secure_channel/public/cpp/shared.
-source_set("connection_priority") {
-  sources = [
     "connection_priority.cc",
     "connection_priority.h",
   ]
@@ -30,19 +12,3 @@
     "//base",
   ]
 }
-
-static_library("test_support") {
-  testonly = true
-
-  sources = [
-    ":shared",
-    "fake_authenticated_channel.cc",
-    "fake_authenticated_channel.h",
-  ]
-
-  deps = [
-    ":shared",
-    "//base",
-    "//chromeos/services/secure_channel/public/mojom",
-  ]
-}
diff --git a/chromeos/services/secure_channel/public/mojom/secure_channel.typemap b/chromeos/services/secure_channel/public/mojom/secure_channel.typemap
index 3b0ebe4..1a77e53 100644
--- a/chromeos/services/secure_channel/public/mojom/secure_channel.typemap
+++ b/chromeos/services/secure_channel/public/mojom/secure_channel.typemap
@@ -16,7 +16,7 @@
 ]
 
 public_deps = [
-  "//chromeos/services/secure_channel/public/cpp/shared:connection_priority",
+  "//chromeos/services/secure_channel/public/cpp/shared",
 ]
 
 type_mappings = [ "chromeos.secure_channel.mojom.ConnectionPriority=chromeos::secure_channel::ConnectionPriority" ]
diff --git a/chromeos/services/secure_channel/secure_channel_impl.cc b/chromeos/services/secure_channel/secure_channel_impl.cc
index f2bbdef..1b103e50 100644
--- a/chromeos/services/secure_channel/secure_channel_impl.cc
+++ b/chromeos/services/secure_channel/secure_channel_impl.cc
@@ -12,12 +12,12 @@
 #include "base/stl_util.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
 #include "chromeos/services/secure_channel/active_connection_manager_impl.h"
+#include "chromeos/services/secure_channel/authenticated_channel.h"
 #include "chromeos/services/secure_channel/ble_connection_manager_impl.h"
 #include "chromeos/services/secure_channel/ble_service_data_helper_impl.h"
 #include "chromeos/services/secure_channel/client_connection_parameters_impl.h"
 #include "chromeos/services/secure_channel/device_id_pair.h"
 #include "chromeos/services/secure_channel/pending_connection_manager_impl.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
 #include "chromeos/services/secure_channel/timer_factory_impl.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
diff --git a/chromeos/services/secure_channel/secure_channel_service_unittest.cc b/chromeos/services/secure_channel/secure_channel_service_unittest.cc
index a547942..d528d23 100644
--- a/chromeos/services/secure_channel/secure_channel_service_unittest.cc
+++ b/chromeos/services/secure_channel/secure_channel_service_unittest.cc
@@ -17,6 +17,7 @@
 #include "chromeos/services/secure_channel/ble_service_data_helper_impl.h"
 #include "chromeos/services/secure_channel/client_connection_parameters_impl.h"
 #include "chromeos/services/secure_channel/fake_active_connection_manager.h"
+#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
 #include "chromeos/services/secure_channel/fake_ble_service_data_helper.h"
 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
@@ -25,7 +26,6 @@
 #include "chromeos/services/secure_channel/fake_timer_factory.h"
 #include "chromeos/services/secure_channel/pending_connection_manager_impl.h"
 #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
-#include "chromeos/services/secure_channel/public/cpp/shared/fake_authenticated_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/constants.mojom.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "chromeos/services/secure_channel/secure_channel_initializer.h"
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index c060c95..91c48456 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -31,8 +31,9 @@
     static final int BACKGROUND_TASK_OFFLINE_CONTENT_NOTIFICATION = 11;
     static final int BACKGROUND_TASK_WEBAPK_UPDATE = 12;
     static final int BACKGROUND_TASK_DOWNLOAD_RESUMPTION = 13;
+    static final int BACKGROUND_TASK_FEED_REFRESH = 14;
     // Keep this one at the end and increment appropriately when adding new tasks.
-    static final int BACKGROUND_TASK_COUNT = 14;
+    static final int BACKGROUND_TASK_COUNT = 15;
 
     static final String KEY_CACHED_UMA = "bts_cached_uma";
 
@@ -247,6 +248,8 @@
                 return BACKGROUND_TASK_WEBAPK_UPDATE;
             case TaskIds.DOWNLOAD_RESUMPTION_JOB_ID:
                 return BACKGROUND_TASK_DOWNLOAD_RESUMPTION;
+            case TaskIds.FEED_REFRESH_JOB_ID:
+                return BACKGROUND_TASK_FEED_REFRESH;
             default:
                 assert false;
         }
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
index 3c8dd368..4210211 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
@@ -26,6 +26,7 @@
     public static final int WEBVIEW_VARIATIONS_SEED_FETCH_JOB_ID = 83;
     public static final int WEBAPK_UPDATE_JOB_ID = 91;
     public static final int DOWNLOAD_RESUMPTION_JOB_ID = 55;
+    public static final int FEED_REFRESH_JOB_ID = 22;
 
     private TaskIds() {}
 }
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
index 5ee1bfc..caa0465c 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -82,7 +82,9 @@
         assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DOWNLOAD_RESUMPTION,
                 BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
                         TaskIds.DOWNLOAD_RESUMPTION_JOB_ID));
-        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 14);
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_FEED_REFRESH,
+                BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(TaskIds.FEED_REFRESH_JOB_ID));
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 15);
     }
 
     @Test
diff --git a/components/cast_certificate/cast_cert_validator.cc b/components/cast_certificate/cast_cert_validator.cc
index f70455e..ffcd2b1 100644
--- a/components/cast_certificate/cast_cert_validator.cc
+++ b/components/cast_certificate/cast_cert_validator.cc
@@ -105,7 +105,10 @@
 // It will also require RSA keys have a modulus at least 2048-bits long.
 class CastPathBuilderDelegate : public net::SimplePathBuilderDelegate {
  public:
-  CastPathBuilderDelegate() : SimplePathBuilderDelegate(2048) {}
+  CastPathBuilderDelegate()
+      : SimplePathBuilderDelegate(
+            2048,
+            SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
 };
 
 class CertVerificationContextImpl : public CertVerificationContext {
diff --git a/components/cast_certificate/cast_crl.cc b/components/cast_certificate/cast_crl.cc
index 9a4e6eb..c2f38e4 100644
--- a/components/cast_certificate/cast_crl.cc
+++ b/components/cast_certificate/cast_crl.cc
@@ -134,7 +134,8 @@
 
   // SimplePathBuilderDelegate will enforce required signature algorithms of
   // RSASSA PKCS#1 v1.5 with SHA-256, and RSA keys 2048-bits or longer.
-  net::SimplePathBuilderDelegate path_builder_delegate(2048);
+  net::SimplePathBuilderDelegate path_builder_delegate(
+      2048, net::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
   net::CertPathBuilder::Result result;
   net::CertPathBuilder path_builder(
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index 05017c31..d8d97281 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -23,6 +23,7 @@
 #include "components/exo/layer_tree_frame_sink_holder.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/resources/resource_format.h"
+#include "components/viz/common/resources/resource_format_utils.h"
 #include "components/viz/common/resources/single_release_callback.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -458,7 +459,7 @@
     resource->mailbox_holder = gpu::MailboxHolder(contents_texture->mailbox(),
                                                   sync_token, texture_target_);
     resource->is_overlay_candidate = is_overlay_candidate_;
-    resource->buffer_format = gpu_memory_buffer_->GetFormat();
+    resource->format = viz::GetResourceFormat(gpu_memory_buffer_->GetFormat());
 
     // The contents texture will be released when no longer used by the
     // compositor.
diff --git a/components/feature_engagement/internal/android/tracker_impl_android.cc b/components/feature_engagement/internal/android/tracker_impl_android.cc
index 90fd071..b6e39d7 100644
--- a/components/feature_engagement/internal/android/tracker_impl_android.cc
+++ b/components/feature_engagement/internal/android/tracker_impl_android.cc
@@ -159,11 +159,8 @@
     JNIEnv* env,
     const base::android::JavaRef<jobject>& jobj,
     const base::android::JavaParamRef<jobject>& j_callback_obj) {
-  // Disambiguate RunCallbackAndroid to get the reference to the bool version.
-  void (*runBoolCallback)(const base::android::JavaRef<jobject>&, bool) =
-      &base::android::RunCallbackAndroid;
   tracker_impl_->AddOnInitializedCallback(base::BindOnce(
-      runBoolCallback,
+      &base::android::RunBooleanCallbackAndroid,
       base::android::ScopedJavaGlobalRef<jobject>(j_callback_obj)));
 }
 
diff --git a/components/feed/core/feed_scheduler_host.cc b/components/feed/core/feed_scheduler_host.cc
index 500b825..135beac4 100644
--- a/components/feed/core/feed_scheduler_host.cc
+++ b/components/feed/core/feed_scheduler_host.cc
@@ -4,109 +4,217 @@
 
 #include "components/feed/core/feed_scheduler_host.h"
 
+#include <map>
+#include <string>
 #include <utility>
 
+#include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "components/feed/core/pref_names.h"
+#include "components/feed/core/time_serialization.h"
+#include "components/feed/feed_feature_list.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 
 namespace feed {
 
-enum class FeedSchedulerHost::TriggerType {
-  NTP_SHOWN = 0,
-  FOREGROUNDED = 1,
-  FIXED_TIMER = 2,
-  COUNT
+namespace {
+
+using TriggerType = FeedSchedulerHost::TriggerType;
+using UserClass = UserClassifier::UserClass;
+
+struct ParamPair {
+  std::string name;
+  double default_value;
 };
 
+// The Cartesian product of TriggerType and UserClass each need a different
+// param name in case we decide to change it via a config change. This nested
+// switch lookup ensures that all combinations are defined, along with a
+// default value.
+ParamPair LookupParam(UserClass user_class, TriggerType trigger) {
+  switch (user_class) {
+    case UserClass::RARE_NTP_USER:
+      switch (trigger) {
+        case TriggerType::NTP_SHOWN:
+          return {"ntp_shown_hours_rare_ntp_user", 4.0};
+        case TriggerType::FOREGROUNDED:
+          return {"foregrounded_hours_rare_ntp_user", 24.0};
+        case TriggerType::FIXED_TIMER:
+          return {"fixed_timer_hours_rare_ntp_user", 96.0};
+      }
+    case UserClass::ACTIVE_NTP_USER:
+      switch (trigger) {
+        case TriggerType::NTP_SHOWN:
+          return {"ntp_shown_hours_active_ntp_user", 4.0};
+        case TriggerType::FOREGROUNDED:
+          return {"foregrounded_hours_active_ntp_user", 24.0};
+        case TriggerType::FIXED_TIMER:
+          return {"fixed_timer_hours_active_ntp_user", 48.0};
+      }
+    case UserClass::ACTIVE_SUGGESTIONS_CONSUMER:
+      switch (trigger) {
+        case TriggerType::NTP_SHOWN:
+          return {"ntp_shown_hours_active_suggestions_consumer", 1.0};
+        case TriggerType::FOREGROUNDED:
+          return {"foregrounded_hours_active_suggestions_consumer", 12.0};
+        case TriggerType::FIXED_TIMER:
+          return {"fixed_timer_hours_active_suggestions_consumer", 24.0};
+      }
+  }
+}
+
+// Run the given closure if it is valid.
+void TryRun(base::OnceClosure closure) {
+  if (closure) {
+    std::move(closure).Run();
+  }
+}
+
+}  // namespace
+
 FeedSchedulerHost::FeedSchedulerHost(PrefService* pref_service,
                                      base::Clock* clock)
-    : pref_service_(pref_service), clock_(clock) {}
+    : pref_service_(pref_service),
+      clock_(clock),
+      user_classifier_(pref_service, clock) {}
 
 FeedSchedulerHost::~FeedSchedulerHost() {}
 
 // static
 void FeedSchedulerHost::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterTimePref(prefs::kLastFetchAttemptTime, base::Time());
+  registry->RegisterTimeDeltaPref(prefs::kBackgroundRefreshPeriod,
+                                  base::TimeDelta());
+}
+
+void FeedSchedulerHost::Initialize(
+    base::RepeatingClosure refresh_callback,
+    ScheduleBackgroundTaskCallback schedule_background_task_callback) {
+  // There should only ever be one scheduler host and bridge created. Neither
+  // are ever destroyed before shutdown, and this method should only be called
+  // once as the bridge is constructed.
+  DCHECK(!refresh_callback_);
+  DCHECK(!schedule_background_task_callback_);
+
+  refresh_callback_ = std::move(refresh_callback);
+  schedule_background_task_callback_ =
+      std::move(schedule_background_task_callback);
+
+  base::TimeDelta old_period =
+      pref_service_->GetTimeDelta(prefs::kBackgroundRefreshPeriod);
+  base::TimeDelta new_period = GetTriggerThreshold(TriggerType::FIXED_TIMER);
+  if (old_period != new_period) {
+    ScheduleFixedTimerWakeUp(new_period);
+  }
 }
 
 NativeRequestBehavior FeedSchedulerHost::ShouldSessionRequestData(
     bool has_content,
     base::Time content_creation_date_time,
     bool has_outstanding_request) {
-  // TODO(skym): Record requested behavior into histogram.
+  NativeRequestBehavior behavior;
   if (!has_outstanding_request && ShouldRefresh(TriggerType::NTP_SHOWN)) {
     if (!has_content) {
-      return REQUEST_WITH_WAIT;
+      behavior = REQUEST_WITH_WAIT;
     } else if (IsContentStale(content_creation_date_time)) {
-      return REQUEST_WITH_TIMEOUT;
+      behavior = REQUEST_WITH_TIMEOUT;
     } else {
-      return REQUEST_WITH_CONTENT;
+      behavior = REQUEST_WITH_CONTENT;
     }
   } else {
+    // Note that NO_REQUEST_WITH_WAIT is used to show a blank article section
+    // even when no request is being made. The user will be given the ability to
+    // force a refresh but this scheduler is not driving it.
     if (!has_content) {
-      return NO_REQUEST_WITH_WAIT;
-    } else if (IsContentStale(content_creation_date_time)) {
-      return NO_REQUEST_WITH_TIMEOUT;
+      behavior = NO_REQUEST_WITH_WAIT;
+    } else if (IsContentStale(content_creation_date_time) &&
+               has_outstanding_request) {
+      // This needs to check |has_outstanding_request|, it does not make sense
+      // to use a timeout when no request is being made. Just show the stale
+      // content, since nothing better is on the way.
+      behavior = NO_REQUEST_WITH_TIMEOUT;
     } else {
-      return NO_REQUEST_WITH_CONTENT;
+      behavior = NO_REQUEST_WITH_CONTENT;
     }
   }
+
+  // TODO(skym): Record requested behavior into histogram.
+  user_classifier_.OnEvent(UserClassifier::Event::NTP_OPENED);
+  return behavior;
 }
 
 void FeedSchedulerHost::OnReceiveNewContent(
     base::Time content_creation_date_time) {
-  pref_service_->SetTime(prefs::kLastFetchAttemptTime, clock_->Now());
-  ScheduleFixedTimerWakeUp();
+  pref_service_->SetTime(prefs::kLastFetchAttemptTime,
+                         content_creation_date_time);
+  TryRun(std::move(fixed_timer_completion_));
+  ScheduleFixedTimerWakeUp(GetTriggerThreshold(TriggerType::FIXED_TIMER));
 }
 
 void FeedSchedulerHost::OnRequestError(int network_response_code) {
   pref_service_->SetTime(prefs::kLastFetchAttemptTime, clock_->Now());
+  TryRun(std::move(fixed_timer_completion_));
 }
 
 void FeedSchedulerHost::OnForegrounded() {
-  DCHECK(trigger_refresh_);
+  DCHECK(refresh_callback_);
   if (ShouldRefresh(TriggerType::FOREGROUNDED)) {
-    trigger_refresh_.Run();
+    refresh_callback_.Run();
   }
 }
 
-void FeedSchedulerHost::OnFixedTimer() {
-  DCHECK(trigger_refresh_);
+void FeedSchedulerHost::OnFixedTimer(base::OnceClosure on_completion) {
+  DCHECK(refresh_callback_);
   if (ShouldRefresh(TriggerType::FIXED_TIMER)) {
-    trigger_refresh_.Run();
+    // There shouldn't typically be anything in |fixed_timer_completion_| right
+    // now, but if there was, run it before we replace it.
+    TryRun(std::move(fixed_timer_completion_));
+
+    fixed_timer_completion_ = std::move(on_completion);
+    refresh_callback_.Run();
+  } else {
+    // The task driving this doesn't need to stay around, since no work is being
+    // done on its behalf.
+    TryRun(std::move(on_completion));
   }
 }
 
-void FeedSchedulerHost::RegisterTriggerRefreshCallback(
-    base::RepeatingClosure callback) {
-  // There should only ever be one scheduler host and bridge created. This may
-  // stop being true eventually.
-  DCHECK(trigger_refresh_.is_null());
+void FeedSchedulerHost::OnTaskReschedule() {
+  ScheduleFixedTimerWakeUp(GetTriggerThreshold(TriggerType::FIXED_TIMER));
+}
 
-  trigger_refresh_ = std::move(callback);
+void FeedSchedulerHost::OnSuggestionConsumed() {
+  user_classifier_.OnEvent(UserClassifier::Event::SUGGESTIONS_USED);
 }
 
 bool FeedSchedulerHost::ShouldRefresh(TriggerType trigger) {
-  // TODO(skym): Check various criteria are met, record metrics.
-  return true;
+  // TODO(skym): Check various other criteria are met, record metrics.
+  return (clock_->Now() -
+          pref_service_->GetTime(prefs::kLastFetchAttemptTime)) >
+         GetTriggerThreshold(trigger);
 }
 
 bool FeedSchedulerHost::IsContentStale(base::Time content_creation_date_time) {
-  // TODO(skym): Compare |content_creation_date_time| to foregrounded trigger's
-  // threshold.
-  return false;
+  return (clock_->Now() - content_creation_date_time) >
+         GetTriggerThreshold(TriggerType::FOREGROUNDED);
 }
 
 base::TimeDelta FeedSchedulerHost::GetTriggerThreshold(TriggerType trigger) {
-  // TODO(skym): Select Finch param based on trigger and user classification.
-  return base::TimeDelta();
+  UserClass user_class = user_classifier_.GetUserClass();
+  ParamPair param = LookupParam(user_class, trigger);
+  double value_hours = base::GetFieldTrialParamByFeatureAsDouble(
+      kInterestFeedContentSuggestions, param.name, param.default_value);
+
+  // Use FromSecondsD in case one of the values contained a decimal.
+  return base::TimeDelta::FromSecondsD(value_hours * 3600.0);
 }
 
-void FeedSchedulerHost::ScheduleFixedTimerWakeUp() {
-  // TODO(skym): Implementation, call out to injected scheduling dependency.
+void FeedSchedulerHost::ScheduleFixedTimerWakeUp(base::TimeDelta period) {
+  pref_service_->SetTimeDelta(prefs::kBackgroundRefreshPeriod, period);
+  schedule_background_task_callback_.Run(period);
 }
 
 }  // namespace feed
diff --git a/components/feed/core/feed_scheduler_host.h b/components/feed/core/feed_scheduler_host.h
index 2e0d776..11270e5 100644
--- a/components/feed/core/feed_scheduler_host.h
+++ b/components/feed/core/feed_scheduler_host.h
@@ -6,7 +6,10 @@
 #define COMPONENTS_FEED_CORE_FEED_SCHEDULER_HOST_H_
 
 #include "base/callback.h"
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/feed/core/user_classifier.h"
 
 class PrefRegistrySimple;
 class PrefService;
@@ -14,6 +17,7 @@
 namespace base {
 class Clock;
 class Time;
+class TimeDelta;
 }  // namespace base
 
 namespace feed {
@@ -33,16 +37,34 @@
   NO_REQUEST_WITH_TIMEOUT
 };
 
+enum class TriggerType;
+
 // Implementation of the Feed Scheduler Host API. The scheduler host decides
 // what content is allowed to be shown, based on its age, and when to fetch new
 // content.
 class FeedSchedulerHost {
  public:
+  // The TriggerType enum specifies values for the events that can trigger
+  // refreshing articles.
+  enum class TriggerType { NTP_SHOWN = 0, FOREGROUNDED = 1, FIXED_TIMER = 2 };
+
   FeedSchedulerHost(PrefService* pref_service, base::Clock* clock);
   ~FeedSchedulerHost();
 
+  using ScheduleBackgroundTaskCallback =
+      base::RepeatingCallback<void(base::TimeDelta)>;
+
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
+  // Provide dependent pieces of functionality the scheduler relies on. Should
+  // be called exactly once before other public methods are called. This is
+  // separate from the constructor because the FeedHostService owns and creates
+  // this class, while these providers need to be bridged through the JNI into a
+  // specific place that the FeedHostService does not know of.
+  void Initialize(
+      base::RepeatingClosure refresh_callback,
+      ScheduleBackgroundTaskCallback schedule_background_task_callback);
+
   // Called when the NTP is opened to decide how to handle displaying and
   // refreshing content.
   NativeRequestBehavior ShouldSessionRequestData(
@@ -59,16 +81,21 @@
   // Called when browser is opened, launched, or foregrounded.
   void OnForegrounded();
 
-  // Called when the scheduled fixed timer wakes up.
-  void OnFixedTimer();
+  // Called when the scheduled fixed timer wakes up, |on_completion| will be
+  // invoked when the refresh completes, regardless of success. If no refresh
+  // is started for this trigger, |on_completion| is run immediately.
+  void OnFixedTimer(base::OnceClosure on_completion);
 
-  // Registers a callback to trigger a refresh.
-  void RegisterTriggerRefreshCallback(base::RepeatingClosure callback);
+  // Called when the background task may need to be rescheduled, such as on OS
+  // upgrades that change the way tasks are stored.
+  void OnTaskReschedule();
+
+  // Called when a suggestion is consumed to update what kind of user the
+  // scheduler should be optimizing for.
+  void OnSuggestionConsumed();
 
  private:
-  // The TriggerType enum specifies values for the events that can trigger
-  // refreshing articles.
-  enum class TriggerType;
+  FRIEND_TEST_ALL_PREFIXES(FeedSchedulerHostTest, GetTriggerThreshold);
 
   // Determines whether a refresh should be performed for the given |trigger|.
   // If this method is called and returns true we presume the refresh will
@@ -79,16 +106,13 @@
   // |content_creation_date_time| is old enough to be considered stale.
   bool IsContentStale(base::Time content_creation_date_time);
 
-  // Schedules a task to wakeup and try to refresh. Overrides previously
-  // scheduled tasks.
-  void ScheduleFixedTimerWakeUp();
-
   // Returns the time threshold for content or previous refresh attempt to be
   // considered old enough for a given trigger to warrant a refresh.
   base::TimeDelta GetTriggerThreshold(TriggerType trigger);
 
-  // Callback to request that an async refresh be started.
-  base::RepeatingClosure trigger_refresh_;
+  // Schedules a task to wakeup and try to refresh. Overrides previously
+  // scheduled tasks.
+  void ScheduleFixedTimerWakeUp(base::TimeDelta period);
 
   // Non-owning reference to pref service providing durable storage.
   PrefService* pref_service_;
@@ -96,6 +120,21 @@
   // Non-owning reference to clock to get current time.
   base::Clock* clock_;
 
+  // Persists NTP and article usage over time and provides a classification.
+  UserClassifier user_classifier_;
+
+  // Callback to request that an async refresh be started.
+  base::RepeatingClosure refresh_callback_;
+
+  // Provides ability to schedule and cancel persistent background fixed timer
+  // wake ups that will call into OnFixedTimer().
+  ScheduleBackgroundTaskCallback schedule_background_task_callback_;
+
+  // When a background wake up has caused a fixed timer refresh, this callback
+  // will be valid and holds a way to inform the task driving this wake up that
+  // the refresh has completed. Is called on refresh success or failure.
+  base::OnceClosure fixed_timer_completion_;
+
   DISALLOW_COPY_AND_ASSIGN(FeedSchedulerHost);
 };
 
diff --git a/components/feed/core/feed_scheduler_host_unittest.cc b/components/feed/core/feed_scheduler_host_unittest.cc
index 679c73e..0a7610e 100644
--- a/components/feed/core/feed_scheduler_host_unittest.cc
+++ b/components/feed/core/feed_scheduler_host_unittest.cc
@@ -4,16 +4,22 @@
 
 #include "components/feed/core/feed_scheduler_host.h"
 
+#include <memory>
+#include <vector>
+
 #include "base/bind.h"
+#include "base/memory/weak_ptr.h"
 #include "base/test/simple_test_clock.h"
 #include "components/feed/core/pref_names.h"
+#include "components/feed/core/time_serialization.h"
+#include "components/feed/core/user_classifier.h"
+#include "components/feed/feed_feature_list.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/variations/variations_params_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace feed {
 
-namespace {
-
 // Fixed "now" to make tests more deterministic.
 char kNowString[] = "2018-06-11 15:41";
 
@@ -21,54 +27,349 @@
 
 class FeedSchedulerHostTest : public ::testing::Test {
  public:
-  void TriggerRefresh() { trigger_refresh_count_++; }
+  void FixedTimerCompletion() { fixed_timer_completion_count_++; }
 
  protected:
-  FeedSchedulerHostTest() : scheduler_(&pref_service_, &test_clock_) {
+  FeedSchedulerHostTest() : weak_factory_(this) {
     Time now;
     CHECK(Time::FromUTCString(kNowString, &now));
     test_clock_.SetNow(now);
 
     FeedSchedulerHost::RegisterProfilePrefs(pref_service_.registry());
+    UserClassifier::RegisterProfilePrefs(pref_service_.registry());
+
+    scheduler_ =
+        std::make_unique<FeedSchedulerHost>(&pref_service_, &test_clock_);
+    InitializeScheduler(scheduler());
+  }
+
+  void InitializeScheduler(FeedSchedulerHost* scheduler) {
+    scheduler->Initialize(
+        base::BindRepeating(&FeedSchedulerHostTest::TriggerRefresh,
+                            base::Unretained(this)),
+        base::BindRepeating(&FeedSchedulerHostTest::ScheduleWakeUp,
+                            base::Unretained(this)));
+  }
+
+  // Note: Time will be advanced.
+  void ClassifyAsRareNtpUser() {
+    // By moving time forward from initial seed events, the user will be moved
+    // into RARE_NTP_USER classification.
+    test_clock()->Advance(base::TimeDelta::FromDays(7));
+  }
+
+  // Note: Time will be advanced.
+  void ClassifyAsActiveSuggestionsConsumer() {
+    // Click on some articles to move the user into ACTIVE_SUGGESTIONS_CONSUMER
+    // classification. Separate by at least 30 minutes for different sessions.
+    scheduler()->OnSuggestionConsumed();
+    test_clock()->Advance(base::TimeDelta::FromMinutes(31));
+    scheduler()->OnSuggestionConsumed();
+  }
+
+  // This helper method sets prefs::kLastFetchAttemptTime to the same value
+  // that's about to be passed into ShouldSessionRequestData(). This is what the
+  // scheduler will typically experience when refreshes are successful.
+  NativeRequestBehavior ShouldSessionRequestData(
+      bool has_content,
+      base::Time content_creation_date_time,
+      bool has_outstanding_request) {
+    pref_service()->SetTime(prefs::kLastFetchAttemptTime,
+                            content_creation_date_time);
+    return scheduler()->ShouldSessionRequestData(
+        has_content, content_creation_date_time, has_outstanding_request);
   }
 
   PrefService* pref_service() { return &pref_service_; }
   base::SimpleTestClock* test_clock() { return &test_clock_; }
-  FeedSchedulerHost* scheduler() { return &scheduler_; }
-  int trigger_refresh_count() { return trigger_refresh_count_; }
+  FeedSchedulerHost* scheduler() { return scheduler_.get(); }
+  int refresh_call_count() { return refresh_call_count_; }
+  const std::vector<base::TimeDelta>& schedule_wake_up_times() {
+    return schedule_wake_up_times_;
+  }
+  int cancel_wake_up_call_count() { return cancel_wake_up_call_count_; }
+  int fixed_timer_completion_count() { return fixed_timer_completion_count_; }
 
  private:
+  void TriggerRefresh() { refresh_call_count_++; }
+
+  void ScheduleWakeUp(base::TimeDelta threshold_ms) {
+    schedule_wake_up_times_.push_back(threshold_ms);
+  }
+
+  void CancelWakeUp() { cancel_wake_up_call_count_++; }
+
   TestingPrefServiceSimple pref_service_;
   base::SimpleTestClock test_clock_;
-  FeedSchedulerHost scheduler_;
-  int trigger_refresh_count_ = 0;
+  std::unique_ptr<FeedSchedulerHost> scheduler_;
+  int refresh_call_count_ = 0;
+  std::vector<base::TimeDelta> schedule_wake_up_times_;
+  int cancel_wake_up_call_count_ = 0;
+  int fixed_timer_completion_count_ = 0;
+  base::WeakPtrFactory<FeedSchedulerHostTest> weak_factory_;
 };
 
+TEST_F(FeedSchedulerHostTest, GetTriggerThreshold) {
+  // Make sure that there is no missing configuration in the cartesian product
+  // of states between TriggerType and UserClass.
+  std::vector<FeedSchedulerHost::TriggerType> triggers = {
+      FeedSchedulerHost::TriggerType::NTP_SHOWN,
+      FeedSchedulerHost::TriggerType::FOREGROUNDED,
+      FeedSchedulerHost::TriggerType::FIXED_TIMER};
+
+  // Classification starts out as an active NTP user.
+  for (FeedSchedulerHost::TriggerType trigger : triggers) {
+    EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
+  }
+
+  ClassifyAsRareNtpUser();
+  for (FeedSchedulerHost::TriggerType trigger : triggers) {
+    EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
+  }
+
+  ClassifyAsActiveSuggestionsConsumer();
+  for (FeedSchedulerHost::TriggerType trigger : triggers) {
+    EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
+  }
+}
+
 TEST_F(FeedSchedulerHostTest, ShouldSessionRequestDataSimple) {
+  // For an ACTIVE_NTP_USER, refreshes on NTP_OPEN should be triggered after 4
+  // hours, and staleness should be at 24 hours. Each case tests a range of
+  // values.
+  base::Time no_refresh_large =
+      test_clock()->Now() - base::TimeDelta::FromHours(3);
+  base::Time refresh_only_small =
+      test_clock()->Now() - base::TimeDelta::FromHours(5);
+  base::Time refresh_only_large =
+      test_clock()->Now() - base::TimeDelta::FromHours(23);
+  base::Time stale_small = test_clock()->Now() - base::TimeDelta::FromHours(25);
+
   EXPECT_EQ(REQUEST_WITH_WAIT,
-            scheduler()->ShouldSessionRequestData(
+            ShouldSessionRequestData(
                 /*has_content*/ false, /*content_creation_date_time*/ Time(),
                 /*has_outstanding_request*/ false));
-  // TODO(skym): REQUEST_WITH_TIMEOUT.
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ refresh_only_small,
+                /*has_outstanding_request*/ false));
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ refresh_only_large,
+                /*has_outstanding_request*/ false));
+
+  EXPECT_EQ(
+      REQUEST_WITH_TIMEOUT,
+      ShouldSessionRequestData(
+          /*has_content*/ true, /*content_creation_date_time*/ stale_small,
+          /*has_outstanding_request*/ false));
+  EXPECT_EQ(
+      REQUEST_WITH_TIMEOUT,
+      ShouldSessionRequestData(
+          /*has_content*/ true, /*content_creation_date_time*/ base::Time(),
+          /*has_outstanding_request*/ false));
+
+  // |content_creation_date_time| should be ignored when |has_content| is false.
+  EXPECT_EQ(NO_REQUEST_WITH_WAIT,
+            ShouldSessionRequestData(
+                /*has_content*/ false,
+                /*content_creation_date_time*/ test_clock()->Now(),
+                /*has_outstanding_request*/ true));
+  EXPECT_EQ(NO_REQUEST_WITH_WAIT,
+            ShouldSessionRequestData(
+                /*has_content*/ false, /*content_creation_date_time*/ Time(),
+                /*has_outstanding_request*/ true));
+
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now(),
+                /*has_outstanding_request*/ false));
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ no_refresh_large,
+                /*has_outstanding_request*/ false));
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now(),
+                /*has_outstanding_request*/ true));
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ refresh_only_large,
+                /*has_outstanding_request*/ true));
+
+  EXPECT_EQ(
+      NO_REQUEST_WITH_TIMEOUT,
+      ShouldSessionRequestData(
+          /*has_content*/ true, /*content_creation_date_time*/ stale_small,
+          /*has_outstanding_request*/ true));
+  EXPECT_EQ(
+      NO_REQUEST_WITH_TIMEOUT,
+      ShouldSessionRequestData(
+          /*has_content*/ true, /*content_creation_date_time*/ base::Time(),
+          /*has_outstanding_request*/ true));
+}
+
+TEST_F(FeedSchedulerHostTest, ShouldSessionRequestDataDivergentTimes) {
+  // If a request fails, then the |content_creation_date_time| and the value of
+  // prefs::kLastFetchAttemptTime may diverge. This is okay, and will typically
+  // mean that refreshes are not taken. Staleness should continue to track
+  // |content_creation_date_time|, but because staleness uses a bigger threshold
+  // than NTP_OPEN, this will not affect much.
+
+  // Like above case, the user is an ACTIVE_NTP_USER, staleness at 24 hours and
+  // refresh at 4.
+  base::Time refresh = test_clock()->Now() - base::TimeDelta::FromHours(5);
+  base::Time no_refresh = test_clock()->Now() - base::TimeDelta::FromHours(3);
+  base::Time stale = test_clock()->Now() - base::TimeDelta::FromHours(25);
+  base::Time not_stale = test_clock()->Now() - base::TimeDelta::FromHours(23);
+
+  pref_service()->SetTime(prefs::kLastFetchAttemptTime, no_refresh);
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT, scheduler()->ShouldSessionRequestData(
+                                         /*has_content*/ true,
+                                         /*content_creation_date_time*/ stale,
+                                         /*has_outstanding_request*/ false));
+
+  pref_service()->SetTime(prefs::kLastFetchAttemptTime, refresh);
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT, scheduler()->ShouldSessionRequestData(
+                                      /*has_content*/ true,
+                                      /*content_creation_date_time*/ not_stale,
+                                      /*has_outstanding_request*/ false));
+
+  pref_service()->SetTime(prefs::kLastFetchAttemptTime, refresh);
+  EXPECT_EQ(REQUEST_WITH_TIMEOUT, scheduler()->ShouldSessionRequestData(
+                                      /*has_content*/ true,
+                                      /*content_creation_date_time*/ stale,
+                                      /*has_outstanding_request*/ false));
+
+  // This shouldn't be possible, since last attempt is farther back than
+  // |content_creation_date_time| which updates on success, but verify scheduler
+  // handles it reasonably.
+  pref_service()->SetTime(prefs::kLastFetchAttemptTime, base::Time());
   EXPECT_EQ(REQUEST_WITH_CONTENT,
             scheduler()->ShouldSessionRequestData(
-                /*has_content*/ true, /*content_creation_date_time*/ Time(),
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now(),
                 /*has_outstanding_request*/ false));
-  EXPECT_EQ(NO_REQUEST_WITH_WAIT,
+
+  // By changing the foregrounded threshold, staleness calculation changes.
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"foregrounded_hours_active_ntp_user", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
             scheduler()->ShouldSessionRequestData(
-                /*has_content*/ false, /*content_creation_date_time*/ Time(),
-                /*has_outstanding_request*/ true));
-  // TODO(skym): NO_REQUEST_WITH_TIMEOUT.
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(7),
+                /*has_outstanding_request*/ false));
+  EXPECT_EQ(REQUEST_WITH_TIMEOUT,
+            scheduler()->ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(8),
+                /*has_outstanding_request*/ false));
+}
+
+TEST_F(FeedSchedulerHostTest, NtpShownActiveNtpUser) {
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"ntp_shown_hours_active_ntp_user", "2.5"}},
+      {kInterestFeedContentSuggestions.name});
+
   EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
-            scheduler()->ShouldSessionRequestData(
-                /*has_content*/ true, /*content_creation_date_time*/ Time(),
-                /*has_outstanding_request*/ true));
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(2),
+                /*has_outstanding_request*/ false));
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(3),
+                /*has_outstanding_request*/ false));
+}
+
+TEST_F(FeedSchedulerHostTest, NtpShownRareNtpUser) {
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"ntp_shown_hours_rare_ntp_user", "1.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  ClassifyAsRareNtpUser();
+
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(1),
+                /*has_outstanding_request*/ false));
+
+  // ShouldSessionRequestData() has the side effect of adding NTP_SHOWN event to
+  // the classifier, so push the timer out to keep classification.
+  ClassifyAsRareNtpUser();
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(2),
+                /*has_outstanding_request*/ false));
+}
+
+TEST_F(FeedSchedulerHostTest, NtpShownActiveSuggestionsConsumer) {
+  ClassifyAsActiveSuggestionsConsumer();
+
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromMinutes(59),
+                /*has_outstanding_request*/ false));
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromMinutes(61),
+                /*has_outstanding_request*/ false));
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"ntp_shown_hours_active_suggestions_consumer", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  EXPECT_EQ(NO_REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(7),
+                /*has_outstanding_request*/ false));
+
+  EXPECT_EQ(REQUEST_WITH_CONTENT,
+            ShouldSessionRequestData(
+                /*has_content*/ true,
+                /*content_creation_date_time*/ test_clock()->Now() -
+                    base::TimeDelta::FromHours(8),
+                /*has_outstanding_request*/ false));
 }
 
 TEST_F(FeedSchedulerHostTest, OnReceiveNewContentVerifyPref) {
   EXPECT_EQ(Time(), pref_service()->GetTime(prefs::kLastFetchAttemptTime));
   scheduler()->OnReceiveNewContent(Time());
-  EXPECT_EQ(test_clock()->Now(),
+  EXPECT_EQ(Time(), pref_service()->GetTime(prefs::kLastFetchAttemptTime));
+  // Scheduler should prefer to use specified time over clock time.
+  EXPECT_NE(test_clock()->Now(),
             pref_service()->GetTime(prefs::kLastFetchAttemptTime));
 }
 
@@ -79,20 +380,228 @@
             pref_service()->GetTime(prefs::kLastFetchAttemptTime));
 }
 
-TEST_F(FeedSchedulerHostTest, OnForegroundedTriggersRefresh) {
-  scheduler()->RegisterTriggerRefreshCallback(base::BindRepeating(
-      &FeedSchedulerHostTest::TriggerRefresh, base::Unretained(this)));
+TEST_F(FeedSchedulerHostTest, OnForegroundedActiveNtpUser) {
   scheduler()->OnForegrounded();
-  EXPECT_EQ(1, trigger_refresh_count());
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 24 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(23));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"foregrounded_hours_active_ntp_user", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(3, refresh_call_count());
 }
 
-TEST_F(FeedSchedulerHostTest, OnFixedTimerTriggersRefresh) {
-  scheduler()->RegisterTriggerRefreshCallback(base::BindRepeating(
-      &FeedSchedulerHostTest::TriggerRefresh, base::Unretained(this)));
-  scheduler()->OnFixedTimer();
-  EXPECT_EQ(1, trigger_refresh_count());
+TEST_F(FeedSchedulerHostTest, OnForegroundedRareNtpUser) {
+  ClassifyAsRareNtpUser();
+
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 24 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(23));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"foregrounded_hours_rare_ntp_user", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(3, refresh_call_count());
 }
 
-}  // namespace
+TEST_F(FeedSchedulerHostTest, OnForegroundedActiveSuggestionsConsumer) {
+  ClassifyAsActiveSuggestionsConsumer();
+
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 12 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(11));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"foregrounded_hours_active_suggestions_consumer", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnForegrounded();
+  EXPECT_EQ(3, refresh_call_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerNullCallback) {
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerCompletionRunOnSuccess) {
+  scheduler()->OnFixedTimer(base::BindOnce(
+      &FeedSchedulerHostTest::FixedTimerCompletion, base::Unretained(this)));
+  EXPECT_EQ(1, refresh_call_count());
+
+  scheduler()->OnReceiveNewContent(Time());
+  EXPECT_EQ(1, fixed_timer_completion_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerCompletionRunOnFailure) {
+  scheduler()->OnFixedTimer(base::BindOnce(
+      &FeedSchedulerHostTest::FixedTimerCompletion, base::Unretained(this)));
+  EXPECT_EQ(1, refresh_call_count());
+
+  scheduler()->OnRequestError(0);
+  EXPECT_EQ(1, fixed_timer_completion_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerActiveNtpUser) {
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 48 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(47));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"fixed_timer_hours_active_ntp_user", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(3, refresh_call_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerActiveRareNtpUser) {
+  ClassifyAsRareNtpUser();
+
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 96 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(95));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"fixed_timer_hours_rare_ntp_user", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(3, refresh_call_count());
+}
+
+TEST_F(FeedSchedulerHostTest, OnFixedTimerActiveSuggestionsConsumer) {
+  ClassifyAsActiveSuggestionsConsumer();
+
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  // Default is 24 hours.
+  test_clock()->Advance(base::TimeDelta::FromHours(23));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(1, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(2));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+  scheduler()->OnReceiveNewContent(test_clock()->Now());
+
+  variations::testing::VariationParamsManager variation_params(
+      kInterestFeedContentSuggestions.name,
+      {{"fixed_timer_hours_active_suggestions_consumer", "7.5"}},
+      {kInterestFeedContentSuggestions.name});
+
+  test_clock()->Advance(base::TimeDelta::FromHours(7));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(2, refresh_call_count());
+
+  test_clock()->Advance(base::TimeDelta::FromHours(1));
+  scheduler()->OnFixedTimer(base::OnceClosure());
+  EXPECT_EQ(3, refresh_call_count());
+}
+
+TEST_F(FeedSchedulerHostTest, ScheduleFixedTimerWakeUpOnSuccess) {
+  // First wake up scheduled during Initialize().
+  EXPECT_EQ(1U, schedule_wake_up_times().size());
+  scheduler()->OnReceiveNewContent(Time());
+  EXPECT_EQ(2U, schedule_wake_up_times().size());
+
+  // Make another scheduler to initialize, make sure it doesn't schedule a
+  // wake up.
+  FeedSchedulerHost second_scheduler(pref_service(), test_clock());
+  InitializeScheduler(&second_scheduler);
+  EXPECT_EQ(2U, schedule_wake_up_times().size());
+}
+
+TEST_F(FeedSchedulerHostTest, OnTaskReschedule) {
+  EXPECT_EQ(1U, schedule_wake_up_times().size());
+  scheduler()->OnTaskReschedule();
+  EXPECT_EQ(2U, schedule_wake_up_times().size());
+}
 
 }  // namespace feed
diff --git a/components/feed/core/pref_names.cc b/components/feed/core/pref_names.cc
index ae4c3df..1976a47d 100644
--- a/components/feed/core/pref_names.cc
+++ b/components/feed/core/pref_names.cc
@@ -8,6 +8,8 @@
 
 namespace prefs {
 
+const char kBackgroundRefreshPeriod[] = "feed.background_refresh_period";
+
 const char kLastFetchAttemptTime[] = "feed.last_fetch_attempt";
 
 const char kUserClassifierAverageNTPOpenedPerHour[] =
diff --git a/components/feed/core/pref_names.h b/components/feed/core/pref_names.h
index 38985a3..cd61363 100644
--- a/components/feed/core/pref_names.h
+++ b/components/feed/core/pref_names.h
@@ -9,6 +9,9 @@
 
 namespace prefs {
 
+// The pref name for the period of time between background refreshes.
+extern const char kBackgroundRefreshPeriod[];
+
 // The pref name for the last time when a background fetch was attempted.
 extern const char kLastFetchAttemptTime[];
 
diff --git a/components/feed/core/user_classifier.cc b/components/feed/core/user_classifier.cc
index 8898cc92..2764226f 100644
--- a/components/feed/core/user_classifier.cc
+++ b/components/feed/core/user_classifier.cc
@@ -30,7 +30,7 @@
 // Never consider any larger interval than this (so that extreme situations such
 // as losing your phone or going for a long offline vacation do not skew the
 // average too much).
-// When everriding via variation parameters, it is better to use smaller values
+// When overriding via variation parameters, it is better to use smaller values
 // than |kMaxHours| as this it the maximum value reported in the histograms.
 const double kMaxHours = 7 * 24;
 const char kMaxHoursParam[] = "user_classifier_max_hours";
@@ -45,18 +45,15 @@
 const double kActiveConsumerClicksAtLeastOncePerHours = 96;
 const char kActiveConsumerClicksAtLeastOncePerHoursParam[] =
     "user_classifier_active_consumer_clicks_at_least_once_per_hours";
-
-// The previous value in production was 66, i.e. 2.75 days. The new value is a
-// shift in the direction we want (having more active users).
 const double kRareUserOpensNTPAtMostOncePerHours = 96;
 const char kRareUserOpensNTPAtMostOncePerHoursParam[] =
     "user_classifier_rare_user_opens_ntp_at_most_once_per_hours";
 
-// The enum used for iteration.
+// List of all Events used for iteration.
 const UserClassifier::Event kEvents[] = {
     UserClassifier::Event::NTP_OPENED, UserClassifier::Event::SUGGESTIONS_USED};
 
-// The summary of the prefs.
+// Arrays of pref names, indexed by Event's int value.
 const char* kRateKeys[] = {prefs::kUserClassifierAverageNTPOpenedPerHour,
                            prefs::kUserClassifierAverageSuggestionsUsedPerHour};
 const char* kLastTimeKeys[] = {prefs::kUserClassifierLastTimeToOpenNTP,
diff --git a/components/feedback/feedback_data.cc b/components/feedback/feedback_data.cc
index c58dce1f..54b8c8a 100644
--- a/components/feedback/feedback_data.cc
+++ b/components/feedback/feedback_data.cc
@@ -72,8 +72,8 @@
     AddLogs(std::move(sys_info));
     base::PostTaskWithTraitsAndReply(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
-        base::Bind(&FeedbackData::CompressLogs, this),
-        base::Bind(&FeedbackData::OnCompressComplete, this));
+        base::BindOnce(&FeedbackData::CompressLogs, this),
+        base::BindOnce(&FeedbackData::OnCompressComplete, this));
   }
 }
 
@@ -143,9 +143,9 @@
     report_sent_ = true;
     userfeedback::ExtensionSubmit feedback_data;
     PrepareReport(&feedback_data);
-    std::string post_body;
-    feedback_data.SerializeToString(&post_body);
-    uploader_->QueueReport(post_body);
+    auto post_body = std::make_unique<std::string>();
+    feedback_data.SerializeToString(post_body.get());
+    uploader_->QueueReport(std::move(post_body));
   }
 }
 
diff --git a/components/feedback/feedback_report.cc b/components/feedback/feedback_report.cc
index faa5c77..ced788f 100644
--- a/components/feedback/feedback_report.cc
+++ b/components/feedback/feedback_report.cc
@@ -12,6 +12,8 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 
+namespace feedback {
+
 namespace {
 
 constexpr base::FilePath::CharType kFeedbackReportFilenameWildcard[] =
@@ -21,44 +23,45 @@
 
 void WriteReportOnBlockingPool(const base::FilePath reports_path,
                                const base::FilePath& file,
-                               const std::string& data) {
+                               scoped_refptr<FeedbackReport> report) {
   DCHECK(reports_path.IsParent(file));
   if (!base::DirectoryExists(reports_path)) {
     base::File::Error error;
     if (!base::CreateDirectoryAndGetError(reports_path, &error))
       return;
   }
-  base::ImportantFileWriter::WriteFileAtomically(file, data, "FeedbackReport");
+  base::ImportantFileWriter::WriteFileAtomically(file, report->data(),
+                                                 "FeedbackReport");
 }
 
 }  // namespace
 
-namespace feedback {
-
 FeedbackReport::FeedbackReport(
     const base::FilePath& path,
     const base::Time& upload_at,
-    const std::string& data,
+    std::unique_ptr<std::string> data,
     scoped_refptr<base::SequencedTaskRunner> task_runner)
     : reports_path_(path),
       upload_at_(upload_at),
-      data_(data),
+      data_(std::move(data)),
       reports_task_runner_(task_runner) {
   if (reports_path_.empty())
     return;
   file_ = reports_path_.AppendASCII(
       kFeedbackReportFilenamePrefix + base::GenerateGUID());
 
-  reports_task_runner_->PostTask(FROM_HERE, base::Bind(
-      &WriteReportOnBlockingPool, reports_path_, file_, data_));
+  reports_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WriteReportOnBlockingPool, reports_path_, file_,
+                     base::WrapRefCounted<FeedbackReport>(this)));
 }
 
 // static
 const char FeedbackReport::kCrashReportIdsKey[]  = "crash_report_ids";
 
 // static
-void FeedbackReport::LoadReportsAndQueue(
-    const base::FilePath& user_dir, QueueCallback callback) {
+void FeedbackReport::LoadReportsAndQueue(const base::FilePath& user_dir,
+                                         const QueueCallback& callback) {
   if (user_dir.empty())
     return;
 
@@ -69,9 +72,9 @@
   for (base::FilePath name = enumerator.Next();
        !name.empty();
        name = enumerator.Next()) {
-    std::string data;
-    if (ReadFileToString(name, &data))
-      callback.Run(data);
+    auto data = std::make_unique<std::string>();
+    if (ReadFileToString(name, data.get()))
+      callback.Run(std::move(data));
     base::DeleteFile(name, false);
   }
 }
@@ -79,7 +82,7 @@
 void FeedbackReport::DeleteReportOnDisk() {
   reports_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&base::DeleteFile), file_, false));
+      base::BindOnce(base::IgnoreResult(&base::DeleteFile), file_, false));
 }
 
 FeedbackReport::~FeedbackReport() {}
diff --git a/components/feedback/feedback_report.h b/components/feedback/feedback_report.h
index d3fdb8d..1e330cab 100644
--- a/components/feedback/feedback_report.h
+++ b/components/feedback/feedback_report.h
@@ -19,16 +19,19 @@
 
 namespace feedback {
 
-typedef base::Callback<void(const std::string&)> QueueCallback;
+// Repeating since for every feedback report file on disk, the callback to
+// queue it in the uploader needs to be invoked.
+using QueueCallback =
+    base::RepeatingCallback<void(std::unique_ptr<std::string>)>;
 
 // This class holds a feedback report. Once a report is created, a disk backup
 // for it is created automatically. This backup needs to explicitly be
 // deleted by calling DeleteReportOnDisk.
-class FeedbackReport : public base::RefCounted<FeedbackReport> {
+class FeedbackReport : public base::RefCountedThreadSafe<FeedbackReport> {
  public:
   FeedbackReport(const base::FilePath& path,
                  const base::Time& upload_at,
-                 const std::string& data,
+                 std::unique_ptr<std::string> data,
                  scoped_refptr<base::SequencedTaskRunner> task_runner);
 
   // The ID of the product specific data for the crash report IDs as stored by
@@ -38,7 +41,7 @@
   // Loads the reports still on disk and queues then using the given callback.
   // This call blocks on the file reads.
   static void LoadReportsAndQueue(const base::FilePath& user_dir,
-                                  QueueCallback callback);
+                                  const QueueCallback& callback);
 
   // Stops the disk write of the report and deletes the report file if already
   // written.
@@ -46,10 +49,10 @@
 
   const base::Time& upload_at() const { return upload_at_; }
   void set_upload_at(const base::Time& time) { upload_at_ = time; }
-  const std::string& data() const { return data_; }
+  const std::string& data() const { return *data_; }
 
  private:
-  friend class base::RefCounted<FeedbackReport>;
+  friend class base::RefCountedThreadSafe<FeedbackReport>;
   virtual ~FeedbackReport();
 
   // Name of the file corresponding to this report.
@@ -57,7 +60,7 @@
 
   base::FilePath reports_path_;
   base::Time upload_at_;  // Upload this report at or after this time.
-  std::string data_;
+  std::unique_ptr<std::string> data_;
 
   scoped_refptr<base::SequencedTaskRunner> reports_task_runner_;
 
diff --git a/components/feedback/feedback_uploader.cc b/components/feedback/feedback_uploader.cc
index fe16704..6b70f3a 100644
--- a/components/feedback/feedback_uploader.cc
+++ b/components/feedback/feedback_uploader.cc
@@ -72,8 +72,8 @@
   g_minimum_retry_delay = delay;
 }
 
-void FeedbackUploader::QueueReport(const std::string& data) {
-  QueueReportWithDelay(data, base::TimeDelta());
+void FeedbackUploader::QueueReport(std::unique_ptr<std::string> data) {
+  QueueReportWithDelay(std::move(data), base::TimeDelta());
 }
 
 void FeedbackUploader::StartDispatchingReport() {
@@ -205,10 +205,11 @@
   }
 }
 
-void FeedbackUploader::QueueReportWithDelay(const std::string& data,
+void FeedbackUploader::QueueReportWithDelay(std::unique_ptr<std::string> data,
                                             base::TimeDelta delay) {
   reports_queue_.emplace(base::MakeRefCounted<FeedbackReport>(
-      feedback_reports_path_, base::Time::Now() + delay, data, task_runner_));
+      feedback_reports_path_, base::Time::Now() + delay, std::move(data),
+      task_runner_));
   UpdateUploadTimer();
 }
 
diff --git a/components/feedback/feedback_uploader.h b/components/feedback/feedback_uploader.h
index dc06ea0..1c500fe 100644
--- a/components/feedback/feedback_uploader.h
+++ b/components/feedback/feedback_uploader.h
@@ -43,7 +43,7 @@
   static void SetMinimumRetryDelayForTesting(base::TimeDelta delay);
 
   // Queues a report for uploading.
-  void QueueReport(const std::string& data);
+  void QueueReport(std::unique_ptr<std::string> data);
 
   bool QueueEmpty() const { return reports_queue_.empty(); }
 
@@ -101,7 +101,8 @@
   // Update our timer for uploading the next report.
   void UpdateUploadTimer();
 
-  void QueueReportWithDelay(const std::string& data, base::TimeDelta delay);
+  void QueueReportWithDelay(std::unique_ptr<std::string> data,
+                            base::TimeDelta delay);
 
   // Browser context this uploader was created for.
   content::BrowserContext* context_;
diff --git a/components/feedback/feedback_uploader_dispatch_unittest.cc b/components/feedback/feedback_uploader_dispatch_unittest.cc
index e7ca044..300d3d70 100644
--- a/components/feedback/feedback_uploader_dispatch_unittest.cc
+++ b/components/feedback/feedback_uploader_dispatch_unittest.cc
@@ -31,6 +31,10 @@
 constexpr int kHttpPostFailClientError = 400;
 constexpr int kHttpPostFailServerError = 500;
 
+void QueueReport(FeedbackUploader* uploader, const std::string& report_data) {
+  uploader->QueueReport(std::make_unique<std::string>(report_data));
+}
+
 }  // namespace
 
 class FeedbackUploaderDispatchTest : public ::testing::Test {
@@ -75,7 +79,7 @@
       context(), FeedbackUploaderFactory::CreateUploaderTaskRunner());
 
   net::TestURLFetcherFactory factory;
-  uploader.QueueReport("test");
+  QueueReport(&uploader, "test");
 
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
   net::HttpRequestHeaders headers;
@@ -99,7 +103,7 @@
   // increase the backoff delay.
   net::TestURLFetcherFactory factory;
   factory.set_remove_fetcher_on_delete(true);
-  uploader.QueueReport("Successful report");
+  QueueReport(&uploader, "Successful report");
   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
   fetcher->set_response_code(kHttpPostSuccessNoContent);
   fetcher->delegate()->OnURLFetchComplete(fetcher);
@@ -108,7 +112,7 @@
 
   // Failed reports due to client errors are not retried. No backoff delay
   // should be doubled.
-  uploader.QueueReport("Client error failed report");
+  QueueReport(&uploader, "Client error failed report");
   fetcher = factory.GetFetcherByID(0);
   fetcher->set_response_code(kHttpPostFailClientError);
   fetcher->delegate()->OnURLFetchComplete(fetcher);
@@ -116,7 +120,7 @@
   EXPECT_TRUE(uploader.QueueEmpty());
 
   // Failed reports due to server errors are retried.
-  uploader.QueueReport("Server error failed report");
+  QueueReport(&uploader, "Server error failed report");
   fetcher = factory.GetFetcherByID(0);
   fetcher->set_response_code(kHttpPostFailServerError);
   fetcher->delegate()->OnURLFetchComplete(fetcher);
diff --git a/components/feedback/feedback_uploader_unittest.cc b/components/feedback/feedback_uploader_unittest.cc
index d9bf658..6c93fa0 100644
--- a/components/feedback/feedback_uploader_unittest.cc
+++ b/components/feedback/feedback_uploader_unittest.cc
@@ -52,8 +52,8 @@
         FROM_HERE,
         base::BindOnce(
             &FeedbackReport::LoadReportsAndQueue, feedback_reports_path(),
-            base::Bind(&MockFeedbackUploader::QueueSingleReport,
-                       base::SequencedTaskRunnerHandle::Get(), this)));
+            base::BindRepeating(&MockFeedbackUploader::QueueSingleReport,
+                                base::SequencedTaskRunnerHandle::Get(), this)));
   }
 
   const std::map<std::string, unsigned int>& dispatched_reports() const {
@@ -66,10 +66,10 @@
   static void QueueSingleReport(
       scoped_refptr<base::SequencedTaskRunner> main_task_runner,
       MockFeedbackUploader* uploader,
-      const std::string& data) {
+      std::unique_ptr<std::string> data) {
     main_task_runner->PostTask(
         FROM_HERE, base::BindOnce(&MockFeedbackUploader::QueueReport,
-                                  uploader->AsWeakPtr(), data));
+                                  uploader->AsWeakPtr(), std::move(data)));
   }
 
   // FeedbackUploaderChrome:
@@ -122,7 +122,7 @@
   }
 
   void QueueReport(const std::string& data) {
-    uploader_->QueueReport(data);
+    uploader_->QueueReport(std::make_unique<std::string>(data));
   }
 
   MockFeedbackUploader* uploader() const { return uploader_.get(); }
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index 75d36a2..9b54656 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -6,6 +6,8 @@
 
 static_library("metrics") {
   sources = [
+    "call_stack_profile_builder.cc",
+    "call_stack_profile_builder.h",
     "call_stack_profile_metrics_provider.cc",
     "call_stack_profile_metrics_provider.h",
     "clean_exit_beacon.cc",
@@ -326,6 +328,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "call_stack_profile_builder_unittest.cc",
     "call_stack_profile_metrics_provider_unittest.cc",
     "child_call_stack_profile_collector_unittest.cc",
     "cloned_install_detector_unittest.cc",
diff --git a/components/metrics/call_stack_profile_builder.cc b/components/metrics/call_stack_profile_builder.cc
new file mode 100644
index 0000000..f3eb2b1
--- /dev/null
+++ b/components/metrics/call_stack_profile_builder.cc
@@ -0,0 +1,64 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/call_stack_profile_builder.h"
+
+#include <utility>
+
+#include "base/logging.h"
+
+using StackSamplingProfiler = base::StackSamplingProfiler;
+
+CallStackProfileBuilder::CallStackProfileBuilder(
+    const StackSamplingProfiler::CompletedCallback& callback)
+    : callback_(callback) {}
+
+CallStackProfileBuilder::~CallStackProfileBuilder() = default;
+
+void CallStackProfileBuilder::RecordAnnotations() {
+  // The code inside this method must not do anything that could acquire a
+  // mutex, including allocating memory (which includes LOG messages) because
+  // that mutex could be held by a stopped thread, thus resulting in deadlock.
+  sample_.process_milestones = StackSamplingProfiler::ProcessMilestone();
+}
+
+void CallStackProfileBuilder::OnSampleCompleted(
+    std::vector<StackSamplingProfiler::InternalFrame> internal_frames) {
+  DCHECK(sample_.frames.empty());
+
+  // Dedup modules and convert InternalFrames to Frames.
+  for (const auto& internal_frame : internal_frames) {
+    const StackSamplingProfiler::InternalModule& module(
+        internal_frame.internal_module);
+    if (!module.is_valid) {
+      sample_.frames.emplace_back(internal_frame.instruction_pointer,
+                                  base::kUnknownModuleIndex);
+      continue;
+    }
+
+    auto loc = module_index_.find(module.base_address);
+    if (loc == module_index_.end()) {
+      profile_.modules.emplace_back(module.base_address, module.id,
+                                    module.filename);
+      size_t index = profile_.modules.size() - 1;
+      loc = module_index_.insert(std::make_pair(module.base_address, index))
+                .first;
+    }
+    sample_.frames.emplace_back(internal_frame.instruction_pointer,
+                                loc->second);
+  }
+
+  profile_.samples.push_back(std::move(sample_));
+  sample_ = StackSamplingProfiler::Sample();
+}
+
+void CallStackProfileBuilder::OnProfileCompleted(
+    base::TimeDelta profile_duration,
+    base::TimeDelta sampling_period) {
+  profile_.profile_duration = profile_duration;
+  profile_.sampling_period = sampling_period;
+
+  // Run the associated callback, passing the collected profile.
+  callback_.Run(std::move(profile_));
+}
\ No newline at end of file
diff --git a/components/metrics/call_stack_profile_builder.h b/components/metrics/call_stack_profile_builder.h
new file mode 100644
index 0000000..d647867
--- /dev/null
+++ b/components/metrics/call_stack_profile_builder.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
+#define COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
+
+#include "base/profiler/stack_sampling_profiler.h"
+
+#include <map>
+
+// CallStackProfileBuilder builds a CallStackProfile from the collected sampling
+// data.
+//
+// The results of the profile building -- a CallStackProfile, is passed to the
+// completed callback. A CallStackProfile contains a set of Samples and
+// Modules, and other sampling information. One Sample corresponds to a single
+// recorded stack, and the Modules record those modules associated with the
+// recorded stack frames.
+class CallStackProfileBuilder
+    : public base::StackSamplingProfiler::ProfileBuilder {
+ public:
+  CallStackProfileBuilder(
+      const base::StackSamplingProfiler::CompletedCallback& callback);
+
+  ~CallStackProfileBuilder() override;
+
+  // base::StackSamplingProfiler::ProfileBuilder:
+  void RecordAnnotations() override;
+  void OnSampleCompleted(std::vector<base::StackSamplingProfiler::InternalFrame>
+                             internal_frames) override;
+  void OnProfileCompleted(base::TimeDelta profile_duration,
+                          base::TimeDelta sampling_period) override;
+
+ private:
+  // The collected stack samples.
+  base::StackSamplingProfiler::CallStackProfile profile_;
+
+  // The current sample being recorded.
+  base::StackSamplingProfiler::Sample sample_;
+
+  // The indexes of internal modules, indexed by module's base_address.
+  std::map<uintptr_t, size_t> module_index_;
+
+  // Callback made when sampling a profile completes.
+  const base::StackSamplingProfiler::CompletedCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(CallStackProfileBuilder);
+};
+
+#endif  // COMPONENTS_METRICS_CALL_STACK_PROFILE_BUILDER_H_
diff --git a/components/metrics/call_stack_profile_builder_unittest.cc b/components/metrics/call_stack_profile_builder_unittest.cc
new file mode 100644
index 0000000..8816b6c
--- /dev/null
+++ b/components/metrics/call_stack_profile_builder_unittest.cc
@@ -0,0 +1,155 @@
+// 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/metrics/call_stack_profile_builder.h"
+
+#include "base/files/file_path.h"
+#include "base/test/bind_test_util.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using StackSamplingProfiler = base::StackSamplingProfiler;
+using InternalFrame = StackSamplingProfiler::InternalFrame;
+using InternalModule = StackSamplingProfiler::InternalModule;
+using CallStackProfile = StackSamplingProfiler::CallStackProfile;
+
+namespace {
+
+// Called on the profiler thread when complete, to collect profile.
+void SaveProfile(CallStackProfile* profile, CallStackProfile pending_profile) {
+  *profile = std::move(pending_profile);
+}
+
+}  // namespace
+
+TEST(CallStackProfileBuilderTest, SetProcessMilestone) {
+  CallStackProfile profile;
+
+  // Set up a callback to record the CallStackProfile to local variable
+  // |profile|.
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      Bind(&SaveProfile, Unretained(&profile)));
+
+  profile_builder->RecordAnnotations();
+  profile_builder->OnSampleCompleted(std::vector<InternalFrame>());
+
+  StackSamplingProfiler::SetProcessMilestone(1);
+  profile_builder->RecordAnnotations();
+  profile_builder->OnSampleCompleted(std::vector<InternalFrame>());
+
+  profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
+
+  ASSERT_EQ(2u, profile.samples.size());
+  EXPECT_EQ(0u, profile.samples[0].process_milestones);
+  EXPECT_EQ(1u << 1, profile.samples[1].process_milestones);
+}
+
+TEST(CallStackProfileBuilderTest, OnSampleCompleted) {
+  CallStackProfile profile;
+
+  // Set up a callback to record the CallStackProfile to local variable
+  // |profile|.
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      Bind(&SaveProfile, Unretained(&profile)));
+
+  InternalModule module1 = {0xccccdddd, "1",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_1"))};
+  InternalModule module2 = {0xccddccdd, "2",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_2"))};
+  InternalFrame frame1 = {0xaaaabbbb, module1};
+  InternalFrame frame2 = {0xaabbaabb, module2};
+
+  std::vector<InternalFrame> frames = {frame1, frame2};
+
+  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
+
+  ASSERT_EQ(1u, profile.samples.size());
+  ASSERT_EQ(2u, profile.samples[0].frames.size());
+  EXPECT_EQ(0u, profile.samples[0].frames[0].module_index);
+  EXPECT_EQ(1u, profile.samples[0].frames[1].module_index);
+}
+
+TEST(CallStackProfileBuilderTest, OnProfileCompleted) {
+  CallStackProfile profile;
+
+  // Set up a callback to record the CallStackProfile to local variable
+  // |profile|.
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      Bind(&SaveProfile, Unretained(&profile)));
+
+  InternalModule module1 = {0xccccdddd, "1",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_1"))};
+  InternalModule module2 = {0xccddccdd, "2",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_2"))};
+  InternalFrame frame1 = {0xaaaabbbb, module1};
+  InternalFrame frame2 = {0xaabbaabb, module2};
+
+  std::vector<InternalFrame> frames = {frame1, frame2};
+
+  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnProfileCompleted(base::TimeDelta::FromMilliseconds(500),
+                                      base::TimeDelta::FromMilliseconds(100));
+
+  ASSERT_EQ(1u, profile.samples.size());
+  ASSERT_EQ(2u, profile.samples[0].frames.size());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), profile.profile_duration);
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(100), profile.sampling_period);
+}
+
+TEST(CallStackProfileBuilderTest, InvalidModule) {
+  CallStackProfile profile;
+
+  // Set up a callback to record the CallStackProfile to local variable
+  // |profile|.
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      Bind(&SaveProfile, Unretained(&profile)));
+
+  InternalModule module1;
+  InternalModule module2 = {0xccddccdd, "2",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_2"))};
+  InternalFrame frame1 = {0xaaaabbbb, module1};
+  InternalFrame frame2 = {0xaabbaabb, module2};
+
+  std::vector<InternalFrame> frames = {frame1, frame2};
+
+  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
+
+  ASSERT_EQ(1u, profile.samples.size());
+  ASSERT_EQ(2u, profile.samples[0].frames.size());
+
+  // module1 has no information hence invalid. The module index of the frame is
+  // therefore base::kUnknownModuleIndex.
+  EXPECT_EQ(base::kUnknownModuleIndex,
+            profile.samples[0].frames[0].module_index);
+
+  EXPECT_EQ(0u, profile.samples[0].frames[1].module_index);
+}
+
+TEST(CallStackProfileBuilderTest, DedupModules) {
+  CallStackProfile profile;
+  auto profile_builder = std::make_unique<CallStackProfileBuilder>(
+      Bind(&SaveProfile, Unretained(&profile)));
+
+  InternalModule module1 = {0xccccdddd, "1",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_1"))};
+  InternalModule module2 = {0xccccdddd, "2",
+                            base::FilePath(FILE_PATH_LITERAL("file_path_2"))};
+  InternalFrame frame1 = {0xaaaabbbb, module1};
+  InternalFrame frame2 = {0xaabbaabb, module2};
+
+  std::vector<InternalFrame> frames = {frame1, frame2};
+
+  profile_builder->OnSampleCompleted(frames);
+  profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
+
+  ASSERT_EQ(1u, profile.samples.size());
+  ASSERT_EQ(2u, profile.samples[0].frames.size());
+
+  // Since module1 and module2 have the same base address 0xccccdddd, they are
+  // considered the same module and therefore deduped.
+  EXPECT_EQ(0u, profile.samples[0].frames[0].module_index);
+  EXPECT_EQ(0u, profile.samples[0].frames[1].module_index);
+}
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_features.cc b/components/ntp_snippets/contextual/contextual_suggestions_features.cc
index effd70a8..9321557 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_features.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_features.cc
@@ -15,4 +15,7 @@
 const base::Feature kContextualSuggestionsSlimPeekUI{
     "ContextualSuggestionsSlimPeekUI", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kContextualSuggestionsOptOut{
+    "ContextualSuggestionsOptOut", base::FEATURE_ENABLED_BY_DEFAULT};
+
 }  // namespace contextual_suggestions
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_features.h b/components/ntp_snippets/contextual/contextual_suggestions_features.h
index 7c095a0..11d28fa 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_features.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_features.h
@@ -12,6 +12,7 @@
 extern const base::Feature kContextualSuggestionsBottomSheet;
 extern const base::Feature kContextualSuggestionsButton;
 extern const base::Feature kContextualSuggestionsSlimPeekUI;
+extern const base::Feature kContextualSuggestionsOptOut;
 
 }  // namespace contextual_suggestions
 
diff --git a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
index edb5024..407811c6 100644
--- a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
+++ b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
@@ -5,6 +5,8 @@
 #include "components/offline_items_collection/core/android/offline_content_aggregator_bridge.h"
 
 #include <memory>
+#include <utility>
+#include <vector>
 
 #include "base/android/callback_android.h"
 #include "base/android/jni_string.h"
@@ -52,14 +54,14 @@
 void RunGetAllItemsCallback(const base::android::JavaRef<jobject>& j_callback,
                             const std::vector<OfflineItem>& items) {
   JNIEnv* env = AttachCurrentThread();
-  RunCallbackAndroid(j_callback,
-                     OfflineItemBridge::CreateOfflineItemList(env, items));
+  RunObjectCallbackAndroid(
+      j_callback, OfflineItemBridge::CreateOfflineItemList(env, items));
 }
 
 void RunGetItemByIdCallback(const base::android::JavaRef<jobject>& j_callback,
                             const base::Optional<OfflineItem>& item) {
   JNIEnv* env = AttachCurrentThread();
-  RunCallbackAndroid(
+  RunObjectCallbackAndroid(
       j_callback, item.has_value()
                       ? OfflineItemBridge::CreateOfflineItem(env, item.value())
                       : nullptr);
diff --git a/components/offline_pages/core/background/scheduler.h b/components/offline_pages/core/background/scheduler.h
index 818c216d..b5122b295 100644
--- a/components/offline_pages/core/background/scheduler.h
+++ b/components/offline_pages/core/background/scheduler.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_SCHEDULER_H_
 #define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_SCHEDULER_H_
 
+#include <stdint.h>
+
 #include "components/offline_pages/core/background/device_conditions.h"
 
 namespace offline_pages {
@@ -38,7 +40,7 @@
   // so we can continue processing background download requests.  This will
   // not overwrite existing tasks.
   virtual void BackupSchedule(const TriggerConditions& trigger_conditions,
-                              long delay_in_seconds) = 0;
+                              int64_t delay_in_seconds) = 0;
 
   // Unschedules the currently scheduled task, if any.
   virtual void Unschedule() = 0;
diff --git a/components/offline_pages/core/background/scheduler_stub.cc b/components/offline_pages/core/background/scheduler_stub.cc
index f80c60c..1d855b1 100644
--- a/components/offline_pages/core/background/scheduler_stub.cc
+++ b/components/offline_pages/core/background/scheduler_stub.cc
@@ -30,7 +30,7 @@
 }
 
 void SchedulerStub::BackupSchedule(const TriggerConditions& trigger_conditions,
-                                   long delay_in_seconds) {
+                                   int64_t delay_in_seconds) {
   backup_schedule_called_ = true;
   schedule_delay_ = delay_in_seconds;
   trigger_conditions_ = trigger_conditions;
diff --git a/components/offline_pages/core/background/scheduler_stub.h b/components/offline_pages/core/background/scheduler_stub.h
index fa57d1f..56d2d8ae 100644
--- a/components/offline_pages/core/background/scheduler_stub.h
+++ b/components/offline_pages/core/background/scheduler_stub.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_SCHEDULER_STUB_H_
 #define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_SCHEDULER_STUB_H_
 
+#include <stdint.h>
+
 #include "components/offline_pages/core/background/scheduler.h"
 
 namespace offline_pages {
@@ -19,7 +21,7 @@
   void Schedule(const TriggerConditions& trigger_conditions) override;
 
   void BackupSchedule(const TriggerConditions& trigger_conditions,
-                      long delay_in_seconds) override;
+                      int64_t delay_in_seconds) override;
 
   // Unschedules the currently scheduled task, if any.
   void Unschedule() override;
@@ -42,7 +44,7 @@
   bool backup_schedule_called_;
   bool unschedule_called_;
   bool get_current_device_conditions_called_;
-  long schedule_delay_;
+  int64_t schedule_delay_;
   DeviceConditions device_conditions_;
   TriggerConditions trigger_conditions_;
 };
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc
index 339385e..ce07a0c 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "components/autofill/core/common/form_data.h"
@@ -125,17 +126,20 @@
            FieldPropertiesFlags::AUTOFILLED));
 }
 
-// Helper struct that is used to return results from the parsing function.
-struct ParseResult {
-  const FormFieldData* username_field = nullptr;
-  const FormFieldData* password_field = nullptr;
-  const FormFieldData* new_password_field = nullptr;
-  const FormFieldData* confirmation_password_field = nullptr;
+// A helper struct that is used to capture significant fields to be used for
+// the construction of a PasswordForm.
+struct SignificantFields {
+  const FormFieldData* username = nullptr;
+  const FormFieldData* password = nullptr;
+  const FormFieldData* new_password = nullptr;
+  const FormFieldData* confirmation_password = nullptr;
 
-  bool IsEmpty() {
-    DCHECK(!confirmation_password_field || new_password_field)
+  // Returns true if some password field is present. This is the minimal
+  // requirement for a successful creation of a PasswordForm is present.
+  bool HasPasswords() const {
+    DCHECK(!confirmation_password || new_password)
         << "There is no password to confirm if there is no new password field.";
-    return password_field == nullptr && new_password_field == nullptr;
+    return password || new_password;
   }
 };
 
@@ -152,29 +156,29 @@
 }
 
 // Tries to parse |processed_fields| based on server |predictions|.
-std::unique_ptr<ParseResult> ParseUsingPredictions(
+std::unique_ptr<SignificantFields> ParseUsingPredictions(
     const std::vector<ProcessedField>& processed_fields,
     const FormPredictions& predictions) {
-  auto result = std::make_unique<ParseResult>();
+  auto result = std::make_unique<SignificantFields>();
   // Note: The code does not check whether there is at most 1 username, 1
   // current password and at most 2 new passwords. It is assumed that server
   // side predictions are sane.
   for (const auto& prediction : predictions) {
     switch (DeriveFromServerFieldType(prediction.second.type)) {
       case CredentialFieldType::kUsername:
-        result->username_field =
+        result->username =
             FindFieldWithUniqueRendererId(processed_fields, prediction.first);
         break;
       case CredentialFieldType::kCurrentPassword:
-        result->password_field =
+        result->password =
             FindFieldWithUniqueRendererId(processed_fields, prediction.first);
         break;
       case CredentialFieldType::kNewPassword:
-        result->new_password_field =
+        result->new_password =
             FindFieldWithUniqueRendererId(processed_fields, prediction.first);
         break;
       case CredentialFieldType::kConfirmationPassword:
-        result->confirmation_password_field =
+        result->confirmation_password =
             FindFieldWithUniqueRendererId(processed_fields, prediction.first);
         break;
       case CredentialFieldType::kNone:
@@ -183,10 +187,10 @@
   }
   // If the server suggests there is a confirmation field but no new password,
   // something went wrong. Sanitize the result.
-  if (result->confirmation_password_field && !result->new_password_field)
-    result->confirmation_password_field = nullptr;
+  if (result->confirmation_password && !result->new_password)
+    result->confirmation_password = nullptr;
 
-  return result->IsEmpty() ? nullptr : std::move(result);
+  return result->HasPasswords() ? std::move(result) : nullptr;
 }
 
 // Tries to parse |processed_fields| based on autocomplete attributes.
@@ -199,30 +203,30 @@
 // Are these assumptions violated, or is there no password with an autocomplete
 // attribute, parsing is unsuccessful. Returns nullptr if parsing is
 // unsuccessful.
-std::unique_ptr<ParseResult> ParseUsingAutocomplete(
+std::unique_ptr<SignificantFields> ParseUsingAutocomplete(
     const std::vector<ProcessedField>& processed_fields) {
-  auto result = std::make_unique<ParseResult>();
+  auto result = std::make_unique<SignificantFields>();
   for (const ProcessedField& processed_field : processed_fields) {
     switch (processed_field.autocomplete_flag) {
       case AutocompleteFlag::kUsername:
-        if (processed_field.is_password || result->username_field)
+        if (processed_field.is_password || result->username)
           return nullptr;
-        result->username_field = processed_field.field;
+        result->username = processed_field.field;
         break;
       case AutocompleteFlag::kCurrentPassword:
-        if (!processed_field.is_password || result->password_field)
+        if (!processed_field.is_password || result->password)
           return nullptr;
-        result->password_field = processed_field.field;
+        result->password = processed_field.field;
         break;
       case AutocompleteFlag::kNewPassword:
         if (!processed_field.is_password)
           return nullptr;
         // The first field with autocomplete=new-password is considered to be
-        // new_password_field and the second is confirmation_password_field.
-        if (!result->new_password_field)
-          result->new_password_field = processed_field.field;
-        else if (!result->confirmation_password_field)
-          result->confirmation_password_field = processed_field.field;
+        // new_password and the second is confirmation_password.
+        if (!result->new_password)
+          result->new_password = processed_field.field;
+        else if (!result->confirmation_password)
+          result->confirmation_password = processed_field.field;
         else
           return nullptr;
         break;
@@ -234,7 +238,7 @@
     }
   }
 
-  return result->IsEmpty() ? nullptr : std::move(result);
+  return result->HasPasswords() ? std::move(result) : nullptr;
 }
 
 // Returns only relevant password fields from |processed_fields|. Namely, if
@@ -386,42 +390,70 @@
   return focusable_username ? focusable_username : username;
 }
 
+// A helper to return a |field|'s unique_renderer_id or
+// kNotSetFormControlRendererId if |field| is null.
+uint32_t ExtractUniqueId(const FormFieldData* field) {
+  return field ? field->unique_renderer_id : FormFieldData::kNotSetFormControlRendererId;
+}
+
 // Tries to find the username and password fields in |processed_fields| based on
 // the structure (how the fields are ordered). If |mode| is SAVING, only
-// consideres non-empty fields. If |username_hint| is not null, it is returned
-// as the username.
-std::unique_ptr<ParseResult> ParseUsingBaseHeuristics(
+// considers non-empty fields. The |found_fields| is both an input and output
+// argument: if some password field and the username are already present, the
+// the function exits early. If something is missing, the function tries to
+// complete it. The result is stored back in |found_fields|.
+void ParseUsingBaseHeuristics(
     const std::vector<ProcessedField>& processed_fields,
     FormParsingMode mode,
-    const FormFieldData* username_hint) {
-  // What is the best interactability among passwords?
-  Interactability password_max = Interactability::kUnlikely;
-  for (const ProcessedField& processed_field : processed_fields) {
-    if (processed_field.is_password)
-      password_max = std::max(password_max, processed_field.interactability);
-  }
+    SignificantFields* found_fields) {
+  // If there is both the username and the minimal set of fields to build a
+  // PasswordForm, return early -- no more work to do.
+  if (found_fields->HasPasswords() && found_fields->username)
+    return;
 
-  // Try to find password elements (current, new, confirmation) among those with
-  // best interactability.
+  // Will point to the password included in |found_field| which is first in the
+  // order of fields in |processed_fields|.
   std::vector<ProcessedField>::const_iterator first_relevant_password =
       processed_fields.end();
-  std::vector<const FormFieldData*> passwords = GetRelevantPasswords(
-      processed_fields, mode, password_max, &first_relevant_password);
-  if (passwords.empty())
-    return nullptr;
-  DCHECK(first_relevant_password != processed_fields.end());
-  auto result = std::make_unique<ParseResult>();
-  LocateSpecificPasswords(passwords, &result->password_field,
-                          &result->new_password_field,
-                          &result->confirmation_password_field);
-  if (result->IsEmpty())
-    return nullptr;
 
-  if (username_hint &&
-      !(mode == FormParsingMode::SAVING && username_hint->value.empty())) {
-    result->username_field = username_hint;
-    return result;
+  if (!found_fields->HasPasswords()) {
+    // What is the best interactability among passwords?
+    Interactability password_max = Interactability::kUnlikely;
+    for (const ProcessedField& processed_field : processed_fields) {
+      if (processed_field.is_password)
+        password_max = std::max(password_max, processed_field.interactability);
+    }
+
+    // Try to find password elements (current, new, confirmation) among those
+    // with best interactability.
+    first_relevant_password = processed_fields.end();
+    std::vector<const FormFieldData*> passwords = GetRelevantPasswords(
+        processed_fields, mode, password_max, &first_relevant_password);
+    if (passwords.empty())
+      return;
+    LocateSpecificPasswords(passwords, &found_fields->password,
+                            &found_fields->new_password,
+                            &found_fields->confirmation_password);
+    if (!found_fields->HasPasswords())
+      return;
+  } else {
+    const uint32_t password_ids[] = {
+        ExtractUniqueId(found_fields->password),
+        ExtractUniqueId(found_fields->new_password),
+        ExtractUniqueId(found_fields->confirmation_password)};
+    for (auto it = processed_fields.begin(); it != processed_fields.end();
+         ++it) {
+      if (it->is_password &&
+          base::ContainsValue(password_ids, it->field->unique_renderer_id)) {
+        first_relevant_password = it;
+        break;
+      }
+    }
   }
+  DCHECK(first_relevant_password != processed_fields.end());
+
+  if (found_fields->username)
+    return;
 
   // What is the best interactability among text fields preceding the passwords?
   Interactability username_max = Interactability::kUnlikely;
@@ -431,37 +463,38 @@
       username_max = std::max(username_max, it->interactability);
   }
 
-  // If password elements are found then try to find a username.
-  result->username_field = FindUsernameFieldBaseHeuristics(
+  found_fields->username = FindUsernameFieldBaseHeuristics(
       processed_fields, first_relevant_password, mode, username_max);
-  return result;
+  return;
 }
 
-// Set username and password fields from |parse_result| in |password_form|.
-void SetFields(const ParseResult& parse_result, PasswordForm* password_form) {
+// Set username and password fields in |password_form| based on
+// |significant_fields| .
+void SetFields(const SignificantFields& significant_fields,
+               PasswordForm* password_form) {
   password_form->has_renderer_ids = true;
-  if (parse_result.username_field) {
-    password_form->username_element = parse_result.username_field->name;
-    password_form->username_value = parse_result.username_field->value;
+  if (significant_fields.username) {
+    password_form->username_element = significant_fields.username->name;
+    password_form->username_value = significant_fields.username->value;
     password_form->username_element_renderer_id =
-        parse_result.username_field->unique_renderer_id;
+        significant_fields.username->unique_renderer_id;
   }
 
-  if (parse_result.password_field) {
-    password_form->password_element = parse_result.password_field->name;
-    password_form->password_value = parse_result.password_field->value;
+  if (significant_fields.password) {
+    password_form->password_element = significant_fields.password->name;
+    password_form->password_value = significant_fields.password->value;
     password_form->password_element_renderer_id =
-        parse_result.password_field->unique_renderer_id;
+        significant_fields.password->unique_renderer_id;
   }
 
-  if (parse_result.new_password_field) {
-    password_form->new_password_element = parse_result.new_password_field->name;
-    password_form->new_password_value = parse_result.new_password_field->value;
+  if (significant_fields.new_password) {
+    password_form->new_password_element = significant_fields.new_password->name;
+    password_form->new_password_value = significant_fields.new_password->value;
   }
 
-  if (parse_result.confirmation_password_field) {
+  if (significant_fields.confirmation_password) {
     password_form->confirmation_password_element =
-        parse_result.confirmation_password_field->name;
+        significant_fields.confirmation_password->name;
   }
 }
 
@@ -543,6 +576,35 @@
   return nullptr;
 }
 
+// Puts together a PasswordForm, the result of the parsing, based on the
+// |form_data| description of the form metadata (e.g., action), the already
+// parsed information about what are the |significant_fields|, and the list
+// |all_possible_passwords| of all non-empty password values and associated
+// element names which occurred in the form.
+std::unique_ptr<PasswordForm> AssemblePasswordForm(
+    const autofill::FormData& form_data,
+    const SignificantFields* significant_fields,
+    autofill::ValueElementVector all_possible_passwords) {
+  if (!significant_fields || !significant_fields->HasPasswords())
+    return nullptr;
+
+  // Create the PasswordForm and set data not related to specific fields.
+  auto result = std::make_unique<PasswordForm>();
+  result->origin = form_data.origin;
+  result->signon_realm = form_data.origin.GetOrigin().spec();
+  result->action = form_data.action;
+  result->form_data = form_data;
+  result->all_possible_passwords = std::move(all_possible_passwords);
+  result->scheme = PasswordForm::SCHEME_HTML;
+  result->preferred = false;
+  result->blacklisted_by_user = false;
+  result->type = PasswordForm::TYPE_MANUAL;
+
+  // Set data related to specific fields.
+  SetFields(*significant_fields, result.get());
+  return result;
+}
+
 }  // namespace
 
 std::unique_ptr<PasswordForm> ParseFormData(
@@ -556,52 +618,39 @@
   if (processed_fields.empty())
     return nullptr;
 
-  // Create parse result and set non-field related information.
-  auto result = std::make_unique<PasswordForm>();
-  result->origin = form_data.origin;
-  result->signon_realm = form_data.origin.GetOrigin().spec();
-  result->action = form_data.action;
-  result->form_data = form_data;
-  result->all_possible_passwords = std::move(all_possible_passwords);
-  result->scheme = PasswordForm::SCHEME_HTML;
-  result->preferred = false;
-  result->blacklisted_by_user = false;
-  result->type = PasswordForm::TYPE_MANUAL;
+  std::unique_ptr<SignificantFields> significant_fields;
 
-  if (form_predictions) {
-    // Try to parse with server predictions.
-    auto predictions_parse_result =
+  // (1) First, try to parse with server predictions.
+  if (form_predictions)
+    significant_fields =
         ParseUsingPredictions(processed_fields, *form_predictions);
-    if (predictions_parse_result) {
-      SetFields(*predictions_parse_result, result.get());
-      return result;
+
+  // (2) If that failed, try to parse with autocomplete attributes.
+  if (!significant_fields)
+    significant_fields = ParseUsingAutocomplete(processed_fields);
+
+  // (3) Now try to fill the gaps.
+  if (!significant_fields)
+    significant_fields = std::make_unique<SignificantFields>();
+
+  // Try to find the username based on the context of the fields.
+  if (!significant_fields->username &&
+      base::FeatureList::IsEnabled(
+          password_manager::features::kHtmlBasedUsernameDetector)) {
+    const FormFieldData* username_field_by_context = FindUsernameInPredictions(
+        form_data.username_predictions, processed_fields);
+    if (username_field_by_context &&
+        !(mode == FormParsingMode::SAVING &&
+          username_field_by_context->value.empty())) {
+      significant_fields->username = username_field_by_context;
     }
   }
 
-  // Try to parse with autocomplete attributes.
-  auto autocomplete_parse_result = ParseUsingAutocomplete(processed_fields);
-  if (autocomplete_parse_result) {
-    SetFields(*autocomplete_parse_result, result.get());
-    return result;
-  }
-
-  // Try to find the username based on the context of the fields.
-  const FormFieldData* username_field_by_context = nullptr;
-  if (base::FeatureList::IsEnabled(
-          password_manager::features::kHtmlBasedUsernameDetector)) {
-    username_field_by_context = FindUsernameInPredictions(
-        form_data.username_predictions, processed_fields);
-  }
-
   // Try to parse with base heuristic.
-  auto base_heuristics_parse_result = ParseUsingBaseHeuristics(
-      processed_fields, mode, username_field_by_context);
-  if (base_heuristics_parse_result) {
-    SetFields(*base_heuristics_parse_result, result.get());
-    return result;
-  }
+  ParseUsingBaseHeuristics(processed_fields, mode, significant_fields.get());
 
-  return nullptr;
+  return AssemblePasswordForm(form_data, significant_fields.get(),
+                              std::move(all_possible_passwords));
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
index 8a21bc2..b380b80 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -699,18 +699,6 @@
           },
       },
       {
-          "Partial autocomplete analysis is not complemented by basic "
-          "heuristics",
-          // Username not found because there was a valid autocomplete mark-up
-          // but it did not include the plain text field.
-          {
-              {.form_control_type = "text"},
-              {.role = ElementRole::CURRENT_PASSWORD,
-               .form_control_type = "password",
-               .autocomplete_attribute = "current-password"},
-          },
-      },
-      {
           "Partial autocomplete analysis fails if no passwords are found",
           // The attribute 'username' is ignored, because there was no password
           // marked up.
@@ -1198,6 +1186,53 @@
   });
 }
 
+// In some situations, server hints or autocomplete mark-up do not provide the
+// username might be omitted. Sometimes this is a truthful signal (there might
+// be no username despite the presence of plain text fields), but often this is
+// just incomplete data. In the long term, the server hints should be complete
+// and also cover cases when the autocomplete mark-up is lacking; at that point,
+// the parser should just trust that the signal is truthful. Until then,
+// however, the parser is trying to complement the signal with its structural
+// heuristics.
+TEST(FormParserTest, ComplementingResults) {
+  CheckTestData({
+      {
+          "Current password from autocomplete analysis, username from basic "
+          "heuristics",
+          {
+              {.role = ElementRole::USERNAME, .form_control_type = "text"},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password",
+               .autocomplete_attribute = "current-password"},
+          },
+      },
+      {
+          "New and confirmation passwords from server, username from basic "
+          "heuristics",
+          {
+              {.role = ElementRole::USERNAME, .form_control_type = "text"},
+              {.role = ElementRole::CONFIRMATION_PASSWORD,
+               .prediction = {.type = autofill::CONFIRMATION_PASSWORD},
+               .form_control_type = "password"},
+              {.form_control_type = "text"},
+              {.role = ElementRole::NEW_PASSWORD,
+               .prediction = {.type = autofill::NEW_PASSWORD},
+               .form_control_type = "password"},
+          },
+      },
+      {
+          "No password from server still means that serve hints are ignored.",
+          {
+              {.prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS},
+               .form_control_type = "text"},
+              {.role = ElementRole::USERNAME, .form_control_type = "text"},
+              {.role = ElementRole::CURRENT_PASSWORD,
+               .form_control_type = "password"},
+          },
+      },
+  });
+}
+
 }  // namespace
 
 }  // namespace password_manager
diff --git a/components/sync/engine/non_blocking_sync_common.h b/components/sync/engine/non_blocking_sync_common.h
index 03b3625..d9992e69 100644
--- a/components/sync/engine/non_blocking_sync_common.h
+++ b/components/sync/engine/non_blocking_sync_common.h
@@ -23,13 +23,17 @@
   CommitRequestData(const CommitRequestData& other);
   ~CommitRequestData();
 
+  // Fields sent to the sync server.
   EntityDataPtr entity;
-
-  // Strictly incrementing number for in-progress commits.  More information
-  // about its meaning can be found in comments in the files that make use of
-  // this struct.
-  int64_t sequence_number = 0;
   int64_t base_version = 0;
+
+  // Fields not sent to the sync server. However, they are kept to be sent back
+  // to the processor in the response.
+
+  // Strictly incrementing number for in-progress commits.
+  // More information about its meaning can be found in comments in the files
+  // that make use of this struct.
+  int64_t sequence_number = 0;
   std::string specifics_hash;
 };
 
@@ -39,6 +43,10 @@
   ~CommitResponseData();
 
   std::string id;
+  // The sync id that was sent in the request. Non-empty only if different from
+  // |id|. It could be different because the server can change the sync id
+  // (e.g. for newly created bookmarks),
+  std::string id_in_request;
   std::string client_tag_hash;
   int64_t sequence_number = 0;
   int64_t response_version = 0;
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
index 081a863..f7485ad8 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
+++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
@@ -97,6 +97,12 @@
         CommitResponseData response_data;
         const CommitRequestData& commit_request = commit_requests_[i];
         response_data.id = entry_response.id_string();
+        if (response_data.id != commit_request.entity->id) {
+          // Server has changed the sync id in the request. Write back the
+          // original sync id. This is useful for data types without a notion of
+          // a client tag such as bookmarks.
+          response_data.id_in_request = commit_request.entity->id;
+        }
         response_data.response_version = entry_response.version();
         response_data.client_tag_hash = commit_request.entity->client_tag_hash;
         response_data.sequence_number = commit_request.sequence_number;
@@ -190,20 +196,17 @@
 
 void NonBlockingTypeCommitContribution::AdjustCommitProto(
     sync_pb::SyncEntity* commit_proto) {
-  // Initial commits need our help to generate a client ID.
   if (commit_proto->version() == kUncommittedVersion) {
-    DCHECK(commit_proto->id_string().empty()) << commit_proto->id_string();
-    // TODO(crbug.com/516866): This is incorrect for bookmarks for two reasons:
-    // 1) Won't be able to match previously committed bookmarks to the ones
-    //    with server ID.
-    // 2) Recommitting an item in a case of failing to receive commit response
-    //    would result in generating a different client ID, which in turn
-    //    would result in a duplication.
-    // We should generate client ID on the frontend side instead.
-    commit_proto->set_id_string(base::GenerateGUID());
     commit_proto->set_version(0);
-  } else {
-    DCHECK(!commit_proto->id_string().empty());
+    // Initial commits need our help to generate a client ID if they don't have
+    // any. Bookmarks create their own IDs on the frontend side to be able to
+    // match them after commits. For other data types we generate one here. And
+    // since bookmarks don't have client tags, their server id should be stable
+    // across restarts in case of recommitting an item, it doesn't result in
+    // creating a duplicate.
+    if (commit_proto->id_string().empty()) {
+      commit_proto->set_id_string(base::GenerateGUID());
+    }
   }
 
   // Encrypt the specifics and hide the title if necessary.
diff --git a/components/sync/protocol/entity_metadata.proto b/components/sync/protocol/entity_metadata.proto
index a715c7c0..d96fdbd3 100644
--- a/components/sync/protocol/entity_metadata.proto
+++ b/components/sync/protocol/entity_metadata.proto
@@ -43,9 +43,9 @@
   // those changes are based.
   optional int64 server_version = 6 [default = -1];
 
-  // Entity creation and modification timestamps.
-  // Assigned by the client and synced by the server, though the server usually
-  // doesn't bother to inspect their values.
+  // Entity creation and modification timestamps. Assigned by the client and
+  // synced by the server, though the server usually doesn't bother to inspect
+  // their values. They are encoded as milliseconds since the Unix epoch.
   optional int64 creation_time = 7;
   optional int64 modification_time = 8;
 
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc
index 7dad68f..be35a61d 100644
--- a/components/sync/protocol/proto_enum_conversions.cc
+++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -298,13 +298,14 @@
 
 const char* ProtoEnumToString(sync_pb::UserConsentSpecifics::Feature feature) {
   ASSERT_ENUM_BOUNDS(sync_pb::UserConsentSpecifics, Feature,
-                     FEATURE_UNSPECIFIED, GOOGLE_LOCATION_SERVICE);
+                     FEATURE_UNSPECIFIED, CHROME_UNIFIED_CONSENT);
   switch (feature) {
     ENUM_CASE(sync_pb::UserConsentSpecifics, FEATURE_UNSPECIFIED);
     ENUM_CASE(sync_pb::UserConsentSpecifics, CHROME_SYNC);
     ENUM_CASE(sync_pb::UserConsentSpecifics, PLAY_STORE);
     ENUM_CASE(sync_pb::UserConsentSpecifics, BACKUP_AND_RESTORE);
     ENUM_CASE(sync_pb::UserConsentSpecifics, GOOGLE_LOCATION_SERVICE);
+    ENUM_CASE(sync_pb::UserConsentSpecifics, CHROME_UNIFIED_CONSENT);
   }
   NOTREACHED();
   return "";
@@ -347,7 +348,7 @@
 const char* ProtoEnumToString(
     sync_pb::UserEventSpecifics::UserConsent::Feature feature) {
   ASSERT_ENUM_BOUNDS(sync_pb::UserEventSpecifics::UserConsent, Feature,
-                     FEATURE_UNSPECIFIED, GOOGLE_LOCATION_SERVICE);
+                     FEATURE_UNSPECIFIED, CHROME_UNIFIED_CONSENT);
   switch (feature) {
     ENUM_CASE(sync_pb::UserEventSpecifics::UserConsent, FEATURE_UNSPECIFIED);
     ENUM_CASE(sync_pb::UserEventSpecifics::UserConsent, CHROME_SYNC);
@@ -355,6 +356,7 @@
     ENUM_CASE(sync_pb::UserEventSpecifics::UserConsent, BACKUP_AND_RESTORE);
     ENUM_CASE(sync_pb::UserEventSpecifics::UserConsent,
               GOOGLE_LOCATION_SERVICE);
+    ENUM_CASE(sync_pb::UserEventSpecifics::UserConsent, CHROME_UNIFIED_CONSENT);
   }
   NOTREACHED();
   return "";
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 6221284..b02f0b3 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -967,6 +967,12 @@
   VISIT_ENUM(status);
 }
 
+VISIT_PROTO_FIELDS(const sync_pb::UserConsentTypes::UnifiedConsent& proto) {
+  VISIT_REP(description_grd_ids);
+  VISIT(confirmation_grd_id);
+  VISIT_ENUM(status);
+}
+
 VISIT_PROTO_FIELDS(const sync_pb::UserEventSpecifics& proto) {
   VISIT(event_time_usec);
   VISIT(navigation_id);
diff --git a/components/sync/protocol/user_consent_specifics.proto b/components/sync/protocol/user_consent_specifics.proto
index 8c94087c..a11be33 100644
--- a/components/sync/protocol/user_consent_specifics.proto
+++ b/components/sync/protocol/user_consent_specifics.proto
@@ -16,7 +16,7 @@
 import "sync_enums.proto";
 import "user_consent_types.proto";
 
-// Next id: 13
+// Next id: 14
 message UserConsentSpecifics {
   // ===========================================================================
   // Fields common to all Chrome User Consents.
@@ -53,6 +53,8 @@
 
     UserConsentTypes.ArcMetricsAndUsageConsent arc_metrics_and_usage_consent =
         11;
+
+    UserConsentTypes.UnifiedConsent unified_consent = 13;
   }
 
   // ===========================================================================
@@ -86,6 +88,7 @@
     PLAY_STORE = 2;
     BACKUP_AND_RESTORE = 3;
     GOOGLE_LOCATION_SERVICE = 4;
+    CHROME_UNIFIED_CONSENT = 5;
   }
   optional Feature feature = 1 [deprecated = true];
   // Ids of the strings of the consent text presented to the user.
diff --git a/components/sync/protocol/user_consent_types.proto b/components/sync/protocol/user_consent_types.proto
index bc27d64..59d8c74 100644
--- a/components/sync/protocol/user_consent_types.proto
+++ b/components/sync/protocol/user_consent_types.proto
@@ -99,4 +99,20 @@
     // given or not given/revoked.
     optional ConsentStatus status = 3;
   }
+
+  // The unified User Consent for Chrome is determined by the user action on the
+  // corresponding Chrome Consent dialog.
+  message UnifiedConsent {
+    // Ids of the strings of the unified Chrome consent text presented to the
+    // user.
+    repeated int32 description_grd_ids = 1;
+
+    // Id of the string of the UI element the user clicked in order to confirm
+    // and close the unified Chrome consent dialog.
+    optional int32 confirmation_grd_id = 2;
+
+    // The status of the unified Chrome consent. This specifies whether the
+    // consent was given or not given/revoked.
+    optional ConsentStatus status = 3;
+  }
 }
diff --git a/components/sync/protocol/user_event_specifics.proto b/components/sync/protocol/user_event_specifics.proto
index 5cd436f..8447a6e2 100644
--- a/components/sync/protocol/user_event_specifics.proto
+++ b/components/sync/protocol/user_event_specifics.proto
@@ -90,7 +90,7 @@
   }
 
   // User consented to the usage of a feature or denied/revoked a consent.
-  // Next id: 13
+  // Next id: 14
   message UserConsent {
     // =========================================================================
     // Fields common to all Chrome User Consents.
@@ -127,6 +127,8 @@
 
       UserConsentTypes.ArcMetricsAndUsageConsent arc_metrics_and_usage_consent =
           11;
+
+      UserConsentTypes.UnifiedConsent unified_consent = 13;
     }
 
     // =========================================================================
@@ -158,6 +160,7 @@
       PLAY_STORE = 2;
       BACKUP_AND_RESTORE = 3;
       GOOGLE_LOCATION_SERVICE = 4;
+      CHROME_UNIFIED_CONSENT = 5;
     }
     optional Feature feature = 1 [deprecated = true];
     // Ids of the strings of the consent text presented to the user.
diff --git a/components/sync_bookmarks/BUILD.gn b/components/sync_bookmarks/BUILD.gn
index 4d9d1a2..22b3775 100644
--- a/components/sync_bookmarks/BUILD.gn
+++ b/components/sync_bookmarks/BUILD.gn
@@ -39,6 +39,7 @@
 
   sources = [
     "bookmark_data_type_controller_unittest.cc",
+    "bookmark_model_observer_impl_unittest.cc",
     "bookmark_model_type_processor_unittest.cc",
     "synced_bookmark_tracker_unittest.cc",
   ]
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl.cc b/components/sync_bookmarks/bookmark_model_observer_impl.cc
index a0980d3..4250ef6 100644
--- a/components/sync_bookmarks/bookmark_model_observer_impl.cc
+++ b/components/sync_bookmarks/bookmark_model_observer_impl.cc
@@ -4,6 +4,17 @@
 
 #include "components/sync_bookmarks/bookmark_model_observer_impl.h"
 
+#include <utility>
+
+#include "base/guid.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node.h"
+#include "components/sync/base/hash_util.h"
+#include "components/sync/base/unique_position.h"
+#include "components/sync/engine/non_blocking_sync_common.h"
+#include "components/sync_bookmarks/synced_bookmark_tracker.h"
+
 namespace sync_bookmarks {
 
 BookmarkModelObserverImpl::BookmarkModelObserverImpl(
@@ -40,7 +51,104 @@
     bookmarks::BookmarkModel* model,
     const bookmarks::BookmarkNode* parent,
     int index) {
-  NOTIMPLEMENTED();
+  const bookmarks::BookmarkNode* node = parent->GetChild(index);
+  // TODO(crbug.com/516866): continue only if
+  // model->client()->CanSyncNode(node).
+
+  const SyncedBookmarkTracker::Entity* parent_entity =
+      bookmark_tracker_->GetEntityForBookmarkNode(parent);
+  if (!parent_entity) {
+    DLOG(WARNING) << "Bookmark parent lookup failed";
+    return;
+  }
+  // Similar to the diectory implementation here:
+  // https://cs.chromium.org/chromium/src/components/sync/syncable/mutable_entry.cc?l=237&gsn=CreateEntryKernel
+  // Assign a temp server id for the entity. Will be overriden by the actual
+  // server id upon receiving commit response.
+  const std::string sync_id = base::GenerateGUID();
+  const int64_t server_version = syncer::kUncommittedVersion;
+  const base::Time creation_time = base::Time::Now();
+  const sync_pb::UniquePosition unique_position =
+      ComputePosition(*parent, index, sync_id).ToProto();
+
+  sync_pb::EntitySpecifics specifics;
+  sync_pb::BookmarkSpecifics* bm_specifics = specifics.mutable_bookmark();
+  bm_specifics->set_url(node->url().spec());
+  // TODO(crbug.com/516866): Set the favicon.
+  bm_specifics->set_title(base::UTF16ToUTF8(node->GetTitle()));
+  bm_specifics->set_creation_time_us(
+      node->date_added().ToDeltaSinceWindowsEpoch().InMicroseconds());
+
+  bm_specifics->set_icon_url(node->icon_url() ? node->icon_url()->spec()
+                                              : std::string());
+  // TODO(crbug.com/516866): update the implementation to be similar to the
+  // directory implementation
+  // https://cs.chromium.org/chromium/src/components/sync_bookmarks/bookmark_change_processor.cc?l=882&rcl=f38001d936d8b2abb5743e85cbc88c72746ae3d2
+  if (node->GetMetaInfoMap()) {
+    for (const std::pair<std::string, std::string>& pair :
+         *node->GetMetaInfoMap()) {
+      sync_pb::MetaInfo* meta_info = bm_specifics->add_meta_info();
+      meta_info->set_key(pair.first);
+      meta_info->set_value(pair.second);
+    }
+  }
+  bookmark_tracker_->Add(sync_id, node, server_version, creation_time,
+                         unique_position, specifics);
+  // Mark the entity that it needs to be committed.
+  bookmark_tracker_->IncrementSequenceNumber(sync_id);
+  nudge_for_commit_closure_.Run();
+}
+
+syncer::UniquePosition BookmarkModelObserverImpl::ComputePosition(
+    const bookmarks::BookmarkNode& parent,
+    int index,
+    const std::string& sync_id) {
+  const std::string& suffix = syncer::GenerateSyncableBookmarkHash(
+      bookmark_tracker_->model_type_state().cache_guid(), sync_id);
+  DCHECK_NE(0, parent.child_count());
+
+  if (parent.child_count() == 1) {
+    // No siblings, the parent has no other children.
+    return syncer::UniquePosition::InitialPosition(suffix);
+  }
+  if (index == 0) {
+    const bookmarks::BookmarkNode* successor_node = parent.GetChild(1);
+    const SyncedBookmarkTracker::Entity* successor_entity =
+        bookmark_tracker_->GetEntityForBookmarkNode(successor_node);
+    DCHECK(successor_entity);
+    // Insert at the beginning.
+    return syncer::UniquePosition::Before(
+        syncer::UniquePosition::FromProto(
+            successor_entity->metadata()->unique_position()),
+        suffix);
+  }
+  if (index == parent.child_count() - 1) {
+    // Insert at the end.
+    const bookmarks::BookmarkNode* predecessor_node =
+        parent.GetChild(index - 1);
+    const SyncedBookmarkTracker::Entity* predecessor_entity =
+        bookmark_tracker_->GetEntityForBookmarkNode(predecessor_node);
+    DCHECK(predecessor_entity);
+    return syncer::UniquePosition::After(
+        syncer::UniquePosition::FromProto(
+            predecessor_entity->metadata()->unique_position()),
+        suffix);
+  }
+  // Insert in the middle.
+  const bookmarks::BookmarkNode* successor_node = parent.GetChild(index + 1);
+  const SyncedBookmarkTracker::Entity* successor_entity =
+      bookmark_tracker_->GetEntityForBookmarkNode(successor_node);
+  DCHECK(successor_entity);
+  const bookmarks::BookmarkNode* predecessor_node = parent.GetChild(index - 1);
+  const SyncedBookmarkTracker::Entity* predecessor_entity =
+      bookmark_tracker_->GetEntityForBookmarkNode(predecessor_node);
+  DCHECK(predecessor_entity);
+  return syncer::UniquePosition::Between(
+      syncer::UniquePosition::FromProto(
+          predecessor_entity->metadata()->unique_position()),
+      syncer::UniquePosition::FromProto(
+          successor_entity->metadata()->unique_position()),
+      suffix);
 }
 
 void BookmarkModelObserverImpl::BookmarkNodeRemoved(
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl.h b/components/sync_bookmarks/bookmark_model_observer_impl.h
index 87777ad..2d81d30 100644
--- a/components/sync_bookmarks/bookmark_model_observer_impl.h
+++ b/components/sync_bookmarks/bookmark_model_observer_impl.h
@@ -6,11 +6,16 @@
 #define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_OBSERVER_IMPL_H_
 
 #include <set>
+#include <string>
 
 #include "base/callback.h"
 #include "components/bookmarks/browser/bookmark_model_observer.h"
 #include "url/gurl.h"
 
+namespace syncer {
+class UniquePosition;
+}
+
 namespace sync_bookmarks {
 
 class SyncedBookmarkTracker;
@@ -54,6 +59,10 @@
       const bookmarks::BookmarkNode* node) override;
 
  private:
+  syncer::UniquePosition ComputePosition(const bookmarks::BookmarkNode& parent,
+                                         int index,
+                                         const std::string& sync_id);
+
   // Points to the tracker owned by the processor. It keeps the mapping between
   // bookmark nodes and corresponding sync server entities.
   SyncedBookmarkTracker* const bookmark_tracker_;
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
new file mode 100644
index 0000000..e3a9492
--- /dev/null
+++ b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
@@ -0,0 +1,149 @@
+// 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/sync_bookmarks/bookmark_model_observer_impl.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/mock_callback.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
+#include "components/sync/base/time.h"
+#include "components/sync/base/unique_position.h"
+#include "components/sync_bookmarks/synced_bookmark_tracker.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sync_bookmarks {
+
+namespace {
+
+using testing::Eq;
+using testing::NiceMock;
+using testing::NotNull;
+
+const char kBookmarkBarId[] = "bookmark_bar_id";
+const char kBookmarkBarTag[] = "bookmark_bar";
+
+class BookmarkModelObserverImplTest : public testing::Test {
+ public:
+  BookmarkModelObserverImplTest()
+      : bookmark_model_(bookmarks::TestBookmarkClient::CreateModel()),
+        bookmark_tracker_(std::vector<NodeMetadataPair>(),
+                          std::make_unique<sync_pb::ModelTypeState>()),
+        observer_(nudge_for_commit_closure_.Get(), &bookmark_tracker_) {
+    bookmark_model_->AddObserver(&observer_);
+    sync_pb::EntitySpecifics specifics;
+    specifics.mutable_bookmark()->set_title(kBookmarkBarTag);
+    bookmark_tracker_.Add(
+        /*sync_id=*/kBookmarkBarId,
+        /*bookmark_node=*/bookmark_model()->bookmark_bar_node(),
+        /*server_version=*/0, /*creation_time=*/base::Time::Now(),
+        syncer::UniquePosition::InitialPosition(
+            syncer::UniquePosition::RandomSuffix())
+            .ToProto(),
+        specifics);
+  }
+
+  bookmarks::BookmarkModel* bookmark_model() { return bookmark_model_.get(); }
+  SyncedBookmarkTracker* bookmark_tracker() { return &bookmark_tracker_; }
+  BookmarkModelObserverImpl* observer() { return &observer_; }
+  base::MockCallback<base::RepeatingClosure>* nudge_for_commit_closure() {
+    return &nudge_for_commit_closure_;
+  }
+
+ private:
+  std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
+  NiceMock<base::MockCallback<base::RepeatingClosure>>
+      nudge_for_commit_closure_;
+  SyncedBookmarkTracker bookmark_tracker_;
+  BookmarkModelObserverImpl observer_;
+};
+
+TEST_F(BookmarkModelObserverImplTest,
+       BookmarkAddedShouldPutInTheTrackerAndNudgeForCommit) {
+  const std::string kTitle = "title";
+  const std::string kUrl = "http://www.url.com";
+  const size_t kMaxEntries = 10;
+
+  EXPECT_CALL(*nudge_for_commit_closure(), Run());
+  const bookmarks::BookmarkNode* bookmark_bar_node =
+      bookmark_model()->bookmark_bar_node();
+  const bookmarks::BookmarkNode* bookmark_node = bookmark_model()->AddURL(
+      /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
+      GURL(kUrl));
+
+  EXPECT_THAT(bookmark_tracker()->TrackedEntitiesCountForTest(), 2U);
+
+  std::vector<const SyncedBookmarkTracker::Entity*> local_changes =
+      bookmark_tracker()->GetEntitiesWithLocalChanges(kMaxEntries);
+  ASSERT_THAT(local_changes.size(), 1U);
+  EXPECT_THAT(local_changes[0]->bookmark_node(), Eq(bookmark_node));
+}
+
+TEST_F(BookmarkModelObserverImplTest, ShouldPositionSiblings) {
+  const std::string kTitle = "title";
+  const std::string kUrl = "http://www.url.com";
+
+  // Build this structure:
+  // bookmark_bar
+  //  |- node1
+  //  |- node2
+  // Expectation:
+  //  p1 < p2
+
+  const bookmarks::BookmarkNode* bookmark_bar_node =
+      bookmark_model()->bookmark_bar_node();
+  const bookmarks::BookmarkNode* bookmark_node1 = bookmark_model()->AddURL(
+      /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
+      GURL(kUrl));
+
+  const bookmarks::BookmarkNode* bookmark_node2 = bookmark_model()->AddURL(
+      /*parent=*/bookmark_bar_node, /*index=*/1, base::UTF8ToUTF16(kTitle),
+      GURL(kUrl));
+
+  ASSERT_THAT(bookmark_tracker()->TrackedEntitiesCountForTest(), Eq(3U));
+  const SyncedBookmarkTracker::Entity* entity1 =
+      bookmark_tracker()->GetEntityForBookmarkNode(bookmark_node1);
+  ASSERT_THAT(entity1, NotNull());
+  syncer::UniquePosition p1 =
+      syncer::UniquePosition::FromProto(entity1->metadata()->unique_position());
+
+  const SyncedBookmarkTracker::Entity* entity2 =
+      bookmark_tracker()->GetEntityForBookmarkNode(bookmark_node2);
+  ASSERT_THAT(entity2, NotNull());
+  syncer::UniquePosition p2 =
+      syncer::UniquePosition::FromProto(entity2->metadata()->unique_position());
+  EXPECT_TRUE(p1.LessThan(p2));
+
+  // Now insert node3 at index 1 to build this structure:
+  // bookmark_bar
+  //  |- node1
+  //  |- node3
+  //  |- node2
+  // Expectation:
+  //  p1 < p2 (still holds)
+  //  p1 < p3
+  //  p3 < p2
+
+  const bookmarks::BookmarkNode* bookmark_node3 = bookmark_model()->AddURL(
+      /*parent=*/bookmark_bar_node, /*index=*/1, base::UTF8ToUTF16(kTitle),
+      GURL(kUrl));
+  EXPECT_THAT(bookmark_tracker()->TrackedEntitiesCountForTest(), Eq(4U));
+
+  const SyncedBookmarkTracker::Entity* entity3 =
+      bookmark_tracker()->GetEntityForBookmarkNode(bookmark_node3);
+  ASSERT_THAT(entity3, NotNull());
+  syncer::UniquePosition p3 =
+      syncer::UniquePosition::FromProto(entity3->metadata()->unique_position());
+  EXPECT_TRUE(p1.LessThan(p2));
+  EXPECT_TRUE(p1.LessThan(p3));
+  EXPECT_TRUE(p3.LessThan(p2));
+}
+
+}  // namespace
+
+}  // namespace sync_bookmarks
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc
index 2a6b799..a3e4578 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -10,8 +10,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/base/time.h"
 #include "components/sync/engine/commit_queue.h"
 #include "components/sync/engine/model_type_processor_proxy.h"
 #include "components/sync/model/data_type_activation_request.h"
@@ -115,19 +117,46 @@
   return true;
 }
 
+sync_pb::EntitySpecifics SpecificsFromBookmarkNode(
+    const bookmarks::BookmarkNode* node) {
+  sync_pb::EntitySpecifics specifics;
+  sync_pb::BookmarkSpecifics* bm_specifics = specifics.mutable_bookmark();
+  bm_specifics->set_url(node->url().spec());
+  // TODO(crbug.com/516866): Set the favicon.
+  bm_specifics->set_title(base::UTF16ToUTF8(node->GetTitle()));
+  bm_specifics->set_creation_time_us(
+      node->date_added().ToDeltaSinceWindowsEpoch().InMicroseconds());
+
+  bm_specifics->set_icon_url(node->icon_url() ? node->icon_url()->spec()
+                                              : std::string());
+
+  for (const std::pair<std::string, std::string>& pair :
+       *node->GetMetaInfoMap()) {
+    sync_pb::MetaInfo* meta_info = bm_specifics->add_meta_info();
+    meta_info->set_key(pair.first);
+    meta_info->set_value(pair.second);
+  }
+  return specifics;
+}
+
 class ScopedRemoteUpdateBookmarks {
  public:
-  // |bookmark_model| and |bookmark_undo_service| must not be null and must
-  // outlive this object.
+  // |bookmark_model|, |bookmark_undo_service| and |observer| must not be null
+  // and must outlive this object.
   ScopedRemoteUpdateBookmarks(bookmarks::BookmarkModel* bookmark_model,
-                              BookmarkUndoService* bookmark_undo_service)
-      : bookmark_model_(bookmark_model), suspend_undo_(bookmark_undo_service) {
+                              BookmarkUndoService* bookmark_undo_service,
+                              bookmarks::BookmarkModelObserver* observer)
+      : bookmark_model_(bookmark_model),
+        suspend_undo_(bookmark_undo_service),
+        observer_(observer) {
     // Notify UI intensive observers of BookmarkModel that we are about to make
     // potentially significant changes to it, so the updates may be batched. For
     // example, on Mac, the bookmarks bar displays animations when bookmark
     // items are added or deleted.
     DCHECK(bookmark_model_);
     bookmark_model_->BeginExtensiveChanges();
+    // Shouldn't be notified upon changes due to sync.
+    bookmark_model_->RemoveObserver(observer_);
   }
 
   ~ScopedRemoteUpdateBookmarks() {
@@ -136,6 +165,7 @@
     // one described in https://crbug.com/281562, where old and new items on the
     // bookmarks bar would overlap.
     bookmark_model_->EndExtensiveChanges();
+    bookmark_model_->AddObserver(observer_);
   }
 
  private:
@@ -144,6 +174,8 @@
   // Changes made to the bookmark model due to sync should not be undoable.
   ScopedSuspendBookmarkUndo suspend_undo_;
 
+  bookmarks::BookmarkModelObserver* const observer_;
+
   DISALLOW_COPY_AND_ASSIGN(ScopedRemoteUpdateBookmarks);
 };
 }  // namespace
@@ -152,7 +184,11 @@
     BookmarkUndoService* bookmark_undo_service)
     : bookmark_undo_service_(bookmark_undo_service), weak_ptr_factory_(this) {}
 
-BookmarkModelTypeProcessor::~BookmarkModelTypeProcessor() = default;
+BookmarkModelTypeProcessor::~BookmarkModelTypeProcessor() {
+  if (bookmark_model_ && bookmark_model_observer_) {
+    bookmark_model_->RemoveObserver(bookmark_model_observer_.get());
+  }
+}
 
 void BookmarkModelTypeProcessor::ConnectSync(
     std::unique_ptr<syncer::CommitQueue> worker) {
@@ -177,35 +213,49 @@
     size_t max_entries,
     const GetLocalChangesCallback& callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  syncer::CommitRequestDataList local_changes;
+  std::vector<syncer::CommitRequestData> local_changes =
+      BuildCommitRequestsForLocalChanges(max_entries);
   callback.Run(std::move(local_changes));
-  NOTIMPLEMENTED();
 }
 
 void BookmarkModelTypeProcessor::OnCommitCompleted(
     const sync_pb::ModelTypeState& type_state,
     const syncer::CommitResponseDataList& response_list) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  NOTIMPLEMENTED();
+
+  for (const syncer::CommitResponseData& response : response_list) {
+    // In order to save space, |response.id_in_request| is written when it's
+    // different from |response.id|. If it's empty, then there was no id change
+    // during the commit, and |response.id| carries both the old and new ids.
+    const std::string& old_sync_id =
+        response.id_in_request.empty() ? response.id : response.id_in_request;
+    bookmark_tracker_->UpdateUponCommitResponse(old_sync_id, response.id,
+                                                response.sequence_number,
+                                                response.response_version);
+  }
+  bookmark_tracker_->set_model_type_state(
+      std::make_unique<sync_pb::ModelTypeState>(type_state));
+  schedule_save_closure_.Run();
 }
 
 void BookmarkModelTypeProcessor::OnUpdateReceived(
     const sync_pb::ModelTypeState& model_type_state,
     const syncer::UpdateResponseDataList& updates) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!model_type_state.cache_guid().empty());
+  DCHECK_EQ(model_type_state.cache_guid(), cache_guid_);
+  DCHECK(model_type_state.initial_sync_done());
 
   if (!bookmark_tracker_) {
     // TODO(crbug.com/516866): Implement the merge logic.
-    auto state = std::make_unique<sync_pb::ModelTypeState>(model_type_state);
-    state->set_cache_guid(cache_guid_);
-    std::vector<NodeMetadataPair> nodes_metadata;
-    bookmark_tracker_ = std::make_unique<SyncedBookmarkTracker>(
-        std::move(nodes_metadata), std::move(state));
+    StartTrackingMetadata(
+        std::vector<NodeMetadataPair>(),
+        std::make_unique<sync_pb::ModelTypeState>(model_type_state));
   }
   // TODO(crbug.com/516866): Set the model type state.
 
-  ScopedRemoteUpdateBookmarks update_bookmarks(bookmark_model_,
-                                               bookmark_undo_service_);
+  ScopedRemoteUpdateBookmarks update_bookmarks(
+      bookmark_model_, bookmark_undo_service_, bookmark_model_observer_.get());
 
   for (const syncer::UpdateResponseData* update : ReorderUpdates(updates)) {
     const syncer::EntityData& update_entity = update->entity.value();
@@ -454,10 +504,12 @@
 }
 
 std::string BookmarkModelTypeProcessor::EncodeSyncMetadata() const {
-  sync_pb::BookmarkModelMetadata model_metadata =
-      bookmark_tracker_->BuildBookmarkModelMetadata();
   std::string metadata_str;
-  model_metadata.SerializeToString(&metadata_str);
+  if (bookmark_tracker_) {
+    sync_pb::BookmarkModelMetadata model_metadata =
+        bookmark_tracker_->BuildBookmarkModelMetadata();
+    model_metadata.SerializeToString(&metadata_str);
+  }
   return metadata_str;
 }
 
@@ -513,14 +565,8 @@
     // TODO(crbug.com/516866): Handle local nodes that don't have a
     // corresponding
     // metadata.
-    bookmark_tracker_ = std::make_unique<SyncedBookmarkTracker>(
-        std::move(nodes_metadata), std::move(model_type_state));
-
-    bookmark_model_observer_ = std::make_unique<BookmarkModelObserverImpl>(
-        base::BindRepeating(&BookmarkModelTypeProcessor::NudgeForCommitIfNeeded,
-                            base::Unretained(this)),
-        bookmark_tracker_.get());
-    // TODO(crbug.com/516866): Register the observer with the bookmark model.
+    StartTrackingMetadata(std::move(nodes_metadata),
+                          std::move(model_type_state));
   } else if (!model_metadata.bookmarks_metadata().empty()) {
     DLOG(ERROR)
         << "Persisted Metadata not empty while initial sync is not done.";
@@ -606,6 +652,76 @@
   }
 }
 
+std::vector<syncer::CommitRequestData>
+BookmarkModelTypeProcessor::BuildCommitRequestsForLocalChanges(
+    size_t max_entries) {
+  DCHECK(bookmark_tracker_);
+  const std::vector<const SyncedBookmarkTracker::Entity*>
+      entities_with_local_changes =
+          bookmark_tracker_->GetEntitiesWithLocalChanges(max_entries);
+  DCHECK_LE(entities_with_local_changes.size(), max_entries);
+
+  std::vector<syncer::CommitRequestData> commit_requests;
+  for (const SyncedBookmarkTracker::Entity* entity :
+       entities_with_local_changes) {
+    DCHECK(entity->IsUnsynced());
+    const sync_pb::EntityMetadata* metadata = entity->metadata();
+
+    syncer::CommitRequestData request;
+    syncer::EntityData data;
+    data.id = metadata->server_id();
+    data.creation_time = syncer::ProtoTimeToTime(metadata->creation_time());
+    data.modification_time =
+        syncer::ProtoTimeToTime(metadata->modification_time());
+    if (!metadata->is_deleted()) {
+      const bookmarks::BookmarkNode* node = entity->bookmark_node();
+      DCHECK(node);
+      const bookmarks::BookmarkNode* parent = node->parent();
+      const SyncedBookmarkTracker::Entity* parent_entity =
+          bookmark_tracker_->GetEntityForBookmarkNode(parent);
+      DCHECK(parent_entity);
+      data.parent_id = parent_entity->metadata()->server_id();
+      // TODO(crbug.com/516866): Double check that custom passphrase works well
+      // with this implementation, because:
+      // 1. NonBlockingTypeCommitContribution::AdjustCommitProto() clears the
+      //    title out.
+      // 2. Bookmarks (maybe ancient legacy bookmarks only?) use/used |name| to
+      //    encode the title.
+      data.is_folder = node->is_folder();
+      // TODO(crbug.com/516866): Set the non_unique_name similar to directory
+      // implementation.
+      // https://cs.chromium.org/chromium/src/components/sync/syncable/write_node.cc?l=41&rcl=1675007db1e0eb03417e81442688bb11cd181f58
+      data.non_unique_name = base::UTF16ToUTF8(node->GetTitle());
+      data.unique_position = parent_entity->metadata()->unique_position();
+      // In case of deletion, make an EntityData with empty specifics to
+      // indicate deletion.
+      data.specifics = SpecificsFromBookmarkNode(node);
+    }
+    request.entity = data.PassToPtr();
+    request.sequence_number = metadata->sequence_number();
+    request.base_version = metadata->server_version();
+    // Specifics hash has been computed in the tracker when this entity has been
+    // added/updated.
+    request.specifics_hash = metadata->specifics_hash();
+
+    commit_requests.push_back(std::move(request));
+  }
+  return commit_requests;
+}
+
+void BookmarkModelTypeProcessor::StartTrackingMetadata(
+    std::vector<NodeMetadataPair> nodes_metadata,
+    std::unique_ptr<sync_pb::ModelTypeState> model_type_state) {
+  bookmark_tracker_ = std::make_unique<SyncedBookmarkTracker>(
+      std::move(nodes_metadata), std::move(model_type_state));
+
+  bookmark_model_observer_ = std::make_unique<BookmarkModelObserverImpl>(
+      base::BindRepeating(&BookmarkModelTypeProcessor::NudgeForCommitIfNeeded,
+                          base::Unretained(this)),
+      bookmark_tracker_.get());
+  bookmark_model_->AddObserver(bookmark_model_observer_.get());
+}
+
 void BookmarkModelTypeProcessor::GetAllNodesForDebugging(
     AllNodesCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.h b/components/sync_bookmarks/bookmark_model_type_processor.h
index 4ea5c4a..420f653 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.h
+++ b/components/sync_bookmarks/bookmark_model_type_processor.h
@@ -135,6 +135,16 @@
   // entities.
   void NudgeForCommitIfNeeded();
 
+  // Builds the commit requests list.
+  std::vector<syncer::CommitRequestData> BuildCommitRequestsForLocalChanges(
+      size_t max_entries);
+
+  // Instantiates the required objects to track metadata and starts observing
+  // changes from the bookmark model.
+  void StartTrackingMetadata(
+      std::vector<NodeMetadataPair> nodes_metadata,
+      std::unique_ptr<sync_pb::ModelTypeState> model_type_state);
+
   // Stores the start callback in between OnSyncStarting() and
   // DecodeSyncMetadata().
   StartCallback start_callback_;
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 572462e..1b52f13 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -8,9 +8,11 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
 #include "components/sync/driver/fake_sync_client.h"
+#include "components/sync/model/data_type_activation_request.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -29,6 +31,7 @@
 const char kBookmarkBarTag[] = "bookmark_bar";
 const char kBookmarkBarId[] = "bookmark_bar_id";
 const char kBookmarksRootId[] = "32904_google_chrome_bookmarks";
+const char kCacheGuid[] = "generated_id";
 
 struct BookmarkInfo {
   std::string server_id;
@@ -60,6 +63,13 @@
   return response_data;
 }
 
+sync_pb::ModelTypeState CreateDummyModelTypeState() {
+  sync_pb::ModelTypeState model_type_state;
+  model_type_state.set_cache_guid(kCacheGuid);
+  model_type_state.set_initial_sync_done(true);
+  return model_type_state;
+}
+
 void AssertState(const BookmarkModelTypeProcessor* processor,
                  const std::vector<BookmarkInfo>& bookmarks) {
   const SyncedBookmarkTracker* tracker = processor->GetTrackerForTest();
@@ -94,7 +104,7 @@
   for (BookmarkInfo bookmark : bookmarks) {
     updates.push_back(CreateUpdateData(bookmark));
   }
-  processor->OnUpdateReceived(sync_pb::ModelTypeState(), updates);
+  processor->OnUpdateReceived(CreateDummyModelTypeState(), updates);
   AssertState(processor, bookmarks);
 }
 
@@ -134,8 +144,14 @@
       : bookmark_model_(bookmarks::TestBookmarkClient::CreateModel()),
         sync_client_(bookmark_model_.get()),
         processor_(sync_client()->GetBookmarkUndoServiceIfExists()) {
+    // TODO(crbug.com/516866): This class assumes model is loaded and sync has
+    // started before running tests. We should test other variations (i.e. model
+    // isn't loaded yet and/or sync didn't start yet).
     processor_.DecodeSyncMetadata(std::string(), schedule_save_closure_.Get(),
                                   bookmark_model_.get());
+    syncer::DataTypeActivationRequest request;
+    request.cache_guid = kCacheGuid;
+    processor_.OnSyncStarting(request, base::DoNothing());
   }
 
   TestSyncClient* sync_client() { return &sync_client_; }
@@ -146,9 +162,10 @@
   }
 
  private:
+  base::test::ScopedTaskEnvironment task_environment_;
+  NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
   std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
   TestSyncClient sync_client_;
-  NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
   BookmarkModelTypeProcessor processor_;
 };
 
@@ -205,7 +222,7 @@
   // Save will be scheduled in the model upon model change. No save should be
   // scheduled from the processor.
   EXPECT_CALL(*schedule_save_closure(), Run()).Times(0);
-  processor()->OnUpdateReceived(sync_pb::ModelTypeState(), updates);
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(), updates);
 
   ASSERT_THAT(bookmarkbar->GetChild(0), NotNull());
   EXPECT_THAT(bookmarkbar->GetChild(0)->GetTitle(), Eq(ASCIIToUTF16(kTitle)));
@@ -241,7 +258,7 @@
   // Save will be scheduled in the model upon model change. No save should be
   // scheduled from the processor.
   EXPECT_CALL(*schedule_save_closure(), Run()).Times(0);
-  processor()->OnUpdateReceived(sync_pb::ModelTypeState(), updates);
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(), updates);
 
   // Check if the bookmark has been updated properly.
   EXPECT_THAT(bookmark_bar->GetChild(0), Eq(bookmark_node));
@@ -273,7 +290,7 @@
   updates[0].response_version++;
 
   EXPECT_CALL(*schedule_save_closure(), Run());
-  processor()->OnUpdateReceived(sync_pb::ModelTypeState(), updates);
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(), updates);
 }
 
 TEST_F(BookmarkModelTypeProcessorTest, ShouldUpdateModelAfterRemoteDelete) {
@@ -330,11 +347,10 @@
   updates.push_back(CreateTombstone(kTitle1Id));
   updates.push_back(CreateTombstone(kFolder1Id));
 
-  const sync_pb::ModelTypeState model_type_state;
   // Save will be scheduled in the model upon model change. No save should be
   // scheduled from the processor.
   EXPECT_CALL(*schedule_save_closure(), Run()).Times(0);
-  processor()->OnUpdateReceived(model_type_state, updates);
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(), updates);
 
   // The structure should be
   // bookmark_bar
@@ -406,8 +422,7 @@
   syncer::UpdateResponseDataList updates;
   updates.push_back(CreateTombstone(kNodeId1));
 
-  const sync_pb::ModelTypeState model_type_state;
-  processor()->OnUpdateReceived(model_type_state, updates);
+  processor()->OnUpdateReceived(CreateDummyModelTypeState(), updates);
 
   metadata_str = processor()->EncodeSyncMetadata();
   model_metadata.ParseFromString(metadata_str);
diff --git a/components/sync_bookmarks/bookmark_sync_service.cc b/components/sync_bookmarks/bookmark_sync_service.cc
index e34166ca..3ef8eac 100644
--- a/components/sync_bookmarks/bookmark_sync_service.cc
+++ b/components/sync_bookmarks/bookmark_sync_service.cc
@@ -22,7 +22,9 @@
 
 BookmarkSyncService::~BookmarkSyncService() {}
 
-void BookmarkSyncService::Shutdown() {}
+void BookmarkSyncService::Shutdown() {
+  bookmark_model_type_processor_.reset();
+}
 
 std::string BookmarkSyncService::EncodeBookmarkSyncMetadata() {
   if (!bookmark_model_type_processor_) {
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index 8d89064..974e0cf4 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -43,6 +43,9 @@
 
 bool SyncedBookmarkTracker::Entity::MatchesData(
     const syncer::EntityData& data) const {
+  // TODO(crbug.com/516866): Check parent id and unique position.
+  // TODO(crbug.com/516866): Compare the actual specifics instead of the
+  // specifics hash.
   if (metadata_->is_deleted() || data.is_deleted()) {
     // In case of deletion, no need to check the specifics.
     return metadata_->is_deleted() == data.is_deleted();
@@ -63,10 +66,13 @@
     std::vector<NodeMetadataPair> nodes_metadata,
     std::unique_ptr<sync_pb::ModelTypeState> model_type_state)
     : model_type_state_(std::move(model_type_state)) {
+  DCHECK(model_type_state_);
   for (NodeMetadataPair& node_metadata : nodes_metadata) {
     const std::string& sync_id = node_metadata.second->server_id();
-    sync_id_to_entities_map_[sync_id] = std::make_unique<Entity>(
-        node_metadata.first, std::move(node_metadata.second));
+    auto entity = std::make_unique<Entity>(node_metadata.first,
+                                           std::move(node_metadata.second));
+    bookmark_node_to_entities_map_[node_metadata.first] = entity.get();
+    sync_id_to_entities_map_[sync_id] = std::move(entity);
   }
 }
 
@@ -78,6 +84,13 @@
   return it != sync_id_to_entities_map_.end() ? it->second.get() : nullptr;
 }
 
+const SyncedBookmarkTracker::Entity*
+SyncedBookmarkTracker::GetEntityForBookmarkNode(
+    const bookmarks::BookmarkNode* node) const {
+  auto it = bookmark_node_to_entities_map_.find(node);
+  return it != bookmark_node_to_entities_map_.end() ? it->second : nullptr;
+}
+
 void SyncedBookmarkTracker::Add(const std::string& sync_id,
                                 const bookmarks::BookmarkNode* bookmark_node,
                                 int64_t server_version,
@@ -90,12 +103,14 @@
   metadata->set_server_id(sync_id);
   metadata->set_server_version(server_version);
   metadata->set_creation_time(syncer::TimeToProtoTime(creation_time));
+  metadata->set_modification_time(syncer::TimeToProtoTime(creation_time));
   metadata->set_sequence_number(0);
   metadata->set_acked_sequence_number(0);
   metadata->mutable_unique_position()->CopyFrom(unique_position);
   HashSpecifics(specifics, metadata->mutable_specifics_hash());
-  sync_id_to_entities_map_[sync_id] =
-      std::make_unique<Entity>(bookmark_node, std::move(metadata));
+  auto entity = std::make_unique<Entity>(bookmark_node, std::move(metadata));
+  bookmark_node_to_entities_map_[bookmark_node] = entity.get();
+  sync_id_to_entities_map_[sync_id] = std::move(entity);
 }
 
 void SyncedBookmarkTracker::Update(const std::string& sync_id,
@@ -114,6 +129,9 @@
 }
 
 void SyncedBookmarkTracker::Remove(const std::string& sync_id) {
+  const Entity* entity = GetEntityForSyncId(sync_id);
+  DCHECK(entity);
+  bookmark_node_to_entities_map_.erase(entity->bookmark_node());
   sync_id_to_entities_map_.erase(sync_id);
 }
 
@@ -155,6 +173,49 @@
   return false;
 }
 
+std::vector<const SyncedBookmarkTracker::Entity*>
+SyncedBookmarkTracker::GetEntitiesWithLocalChanges(size_t max_entries) const {
+  // TODO(crbug.com/516866): Reorder local changes to e.g. parent creation
+  // before child creation and the otherway around for deletions.
+  std::vector<const SyncedBookmarkTracker::Entity*> entities_with_local_changes;
+  for (const std::pair<const std::string, std::unique_ptr<Entity>>& pair :
+       sync_id_to_entities_map_) {
+    Entity* entity = pair.second.get();
+    if (entity->IsUnsynced()) {
+      entities_with_local_changes.push_back(entity);
+    }
+  }
+  return entities_with_local_changes;
+}
+
+void SyncedBookmarkTracker::UpdateUponCommitResponse(
+    const std::string& old_id,
+    const std::string& new_id,
+    int64_t acked_sequence_number,
+    int64_t server_version) {
+  // TODO(crbug.com/516866): Update specifics if we decide to keep it.
+  auto it = sync_id_to_entities_map_.find(old_id);
+  Entity* entity =
+      it != sync_id_to_entities_map_.end() ? it->second.get() : nullptr;
+  if (it == sync_id_to_entities_map_.end()) {
+    DLOG(WARNING) << "Trying to update a non existing entity.";
+    return;
+  }
+  const bookmarks::BookmarkNode* node = entity->bookmark_node();
+  // TODO(crbug.com/516866): For tombstones, node would be null and the DCHECK
+  // below would be invalid. Handle deletions here may be or in the processor.
+  DCHECK(node);
+
+  if (old_id != new_id) {
+    auto it = sync_id_to_entities_map_.find(old_id);
+    entity->metadata()->set_server_id(new_id);
+    sync_id_to_entities_map_[new_id] = std::move(it->second);
+    sync_id_to_entities_map_.erase(old_id);
+  }
+  entity->metadata()->set_acked_sequence_number(acked_sequence_number);
+  entity->metadata()->set_server_version(server_version);
+}
+
 std::size_t SyncedBookmarkTracker::TrackedEntitiesCountForTest() const {
   return sync_id_to_entities_map_.size();
 }
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.h b/components/sync_bookmarks/synced_bookmark_tracker.h
index 1c871f5..1a0405ef 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.h
+++ b/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -76,20 +76,24 @@
       std::unique_ptr<sync_pb::ModelTypeState> model_type_state);
   ~SyncedBookmarkTracker();
 
-  // Returns null if not entity is found.
+  // Returns null if no entity is found.
   const Entity* GetEntityForSyncId(const std::string& sync_id) const;
 
+  // Returns null if no entity is found.
+  const SyncedBookmarkTracker::Entity* GetEntityForBookmarkNode(
+      const bookmarks::BookmarkNode* node) const;
+
   // Adds an entry for the |sync_id| and the corresponding local bookmark node
   // and metadata in |sync_id_to_entities_map_|.
   void Add(const std::string& sync_id,
            const bookmarks::BookmarkNode* bookmark_node,
            int64_t server_version,
-           base::Time modification_time,
+           base::Time creation_time,
            const sync_pb::UniquePosition& unique_position,
            const sync_pb::EntitySpecifics& specifics);
 
-  // Adds an existing entry for the |sync_id| and the corresponding metadata in
-  // |sync_id_to_entities_map_|.
+  // Updates an existing entry for the |sync_id| and the corresponding metadata
+  // in |sync_id_to_entities_map_|.
   void Update(const std::string& sync_id,
               int64_t server_version,
               base::Time modification_time,
@@ -112,16 +116,38 @@
     return *model_type_state_;
   }
 
+  void set_model_type_state(
+      std::unique_ptr<sync_pb::ModelTypeState> model_type_state) {
+    model_type_state_ = std::move(model_type_state);
+  }
+
+  std::vector<const Entity*> GetEntitiesWithLocalChanges(
+      size_t max_entries) const;
+
+  // Updates the tracker after receiving the commit response. |old_id| should be
+  // equal to |new_id| for all updates except the initial commit, where the
+  // temporary client-generated ID will be overriden by the server-provided
+  // final ID. In which case |sync_id_to_entities_map_| will be updated
+  // accordingly.
+  void UpdateUponCommitResponse(const std::string& old_id,
+                                const std::string& new_id,
+                                int64_t acked_sequence_number,
+                                int64_t server_version);
+
   // Returns number of tracked entities. Used only in test.
   std::size_t TrackedEntitiesCountForTest() const;
 
  private:
   // A map of sync server ids to sync entities. This should contain entries and
-  // metadata for almost everything. However, since local data are loaded only
-  // when needed (e.g. before a commit cycle), the entities may not always
-  // contain model type data/specifics.
+  // metadata for almost everything.
   std::map<std::string, std::unique_ptr<Entity>> sync_id_to_entities_map_;
 
+  // A map of bookmark nodes to sync entities. It's keyed by the bookmark node
+  // pointers which get assigned when loading the bookmark model. This map is
+  // first initialized in the constructor.
+  std::map<const bookmarks::BookmarkNode*, Entity*>
+      bookmark_node_to_entities_map_;
+
   // The model metadata (progress marker, initial sync done, etc).
   std::unique_ptr<sync_pb::ModelTypeState> model_type_state_;
 
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
index 9c99bf3..5483bcd 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -108,6 +108,37 @@
   // request in a separate test probably.
 }
 
+TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
+  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
+                                std::make_unique<sync_pb::ModelTypeState>());
+  const std::string kSyncId = "SYNC_ID";
+  const std::string kNewSyncId = "NEW_SYNC_ID";
+  const int64_t kId = 1;
+  const int64_t kServerVersion = 1000;
+  const int64_t kNewServerVersion = 1001;
+  const base::Time kModificationTime(base::Time::Now() -
+                                     base::TimeDelta::FromSeconds(1));
+  const sync_pb::UniquePosition unique_position;
+  const sync_pb::EntitySpecifics specifics =
+      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
+  bookmarks::BookmarkNode node(kId, GURL());
+  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
+              unique_position, specifics);
+  ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
+  // Receive a commit response with a changed id.
+  tracker.UpdateUponCommitResponse(
+      kSyncId, kNewSyncId, /*acked_sequence_number=*/1, kNewServerVersion);
+  // Old id shouldn't be there.
+  EXPECT_THAT(tracker.GetEntityForSyncId(kSyncId), IsNull());
+
+  const SyncedBookmarkTracker::Entity* entity =
+      tracker.GetEntityForSyncId(kNewSyncId);
+  ASSERT_THAT(entity, NotNull());
+  EXPECT_THAT(entity->metadata()->server_id(), Eq(kNewSyncId));
+  EXPECT_THAT(entity->bookmark_node(), Eq(&node));
+  EXPECT_THAT(entity->metadata()->server_version(), Eq(kNewServerVersion));
+}
+
 }  // namespace
 
 }  // namespace sync_bookmarks
diff --git a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png
index 74697b3..8277594 100644
--- a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png
+++ b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png
Binary files differ
diff --git a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
index 9156ccd..eabb8130 100644
--- a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
+++ b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.unmask.Nexus_5-19.png
Binary files differ
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc
index 3c33429..a778b7d 100644
--- a/components/update_client/update_engine.cc
+++ b/components/update_client/update_engine.cc
@@ -82,6 +82,11 @@
   }
 
   if (IsThrottled(is_foreground)) {
+    // TODO(xiaochu): remove this log after https://crbug.com/851151 is fixed.
+    VLOG(1) << "Background update is throttled for following components:";
+    for (const auto& id : ids) {
+      VLOG(1) << "id:" << id;
+    }
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), Error::RETRY_LATER));
     return;
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn
index ef526ac..50dd9e8 100644
--- a/components/url_formatter/BUILD.gn
+++ b/components/url_formatter/BUILD.gn
@@ -25,8 +25,9 @@
   deps = [
     "//base",
     "//base:i18n",
-    "//components/url_formatter/top_domains",
+    "//components/url_formatter/top_domains:generate_top_domains_trie",
     "//net",
+    "//net:preload_decoder",
     "//third_party/icu",
     "//ui/gfx",
     "//url",
@@ -48,8 +49,9 @@
   deps = [
     ":url_formatter",
     "//base",
-    "//components/url_formatter/top_domains",
+    "//components/url_formatter/top_domains:generate_top_domains_test_trie",
     "//net",
+    "//net:preload_decoder",
     "//testing/gtest",
     "//ui/gfx",
     "//url",
diff --git a/components/url_formatter/idn_spoof_checker.cc b/components/url_formatter/idn_spoof_checker.cc
index a3ec302..df6adec 100644
--- a/components/url_formatter/idn_spoof_checker.cc
+++ b/components/url_formatter/idn_spoof_checker.cc
@@ -22,6 +22,45 @@
 
 namespace {
 
+class TopDomainPreloadDecoder : public net::extras::PreloadDecoder {
+ public:
+  using net::extras::PreloadDecoder::PreloadDecoder;
+  ~TopDomainPreloadDecoder() override {}
+
+  bool ReadEntry(net::extras::PreloadDecoder::BitReader* reader,
+                 const std::string& search,
+                 size_t current_search_offset,
+                 bool* out_found) override {
+    bool is_same_skeleton;
+    if (!reader->Next(&is_same_skeleton))
+      return false;
+
+    if (is_same_skeleton) {
+      *out_found = true;
+      return true;
+    }
+
+    bool has_com_suffix = false;
+    if (!reader->Next(&has_com_suffix))
+      return false;
+
+    std::string top_domain;
+    for (char c;; top_domain += c) {
+      huffman_decoder().Decode(reader, &c);
+      if (c == net::extras::PreloadDecoder::kEndOfTable)
+        break;
+    }
+    if (has_com_suffix)
+      top_domain += ".com";
+
+    if (current_search_offset == 0) {
+      *out_found = true;
+      DCHECK(!top_domain.empty());
+    }
+    return true;
+  }
+};
+
 void OnThreadTermination(void* regex_matcher) {
   delete reinterpret_cast<icu::RegexMatcher*>(regex_matcher);
 }
@@ -32,13 +71,20 @@
   return *dangerous_pattern_tls;
 }
 
-#include "components/url_formatter/top_domains/alexa_skeletons-inc.cc"
+#include "components/url_formatter/top_domains/alexa_domains-trie-inc.cc"
+
 // All the domains in the above file have 3 or fewer labels.
 const size_t kNumberOfLabelsToCheck = 3;
-const unsigned char* g_graph = kDafsa;
-size_t g_graph_length = sizeof(kDafsa);
+
+IDNSpoofChecker::HuffmanTrieParams g_trie_params{
+    kTopDomainsHuffmanTree, sizeof(kTopDomainsHuffmanTree), kTopDomainsTrie,
+    kTopDomainsTrieBits, kTopDomainsRootPosition};
 
 bool LookupMatchInTopDomains(const icu::UnicodeString& ustr_skeleton) {
+  TopDomainPreloadDecoder preload_decoder(
+      g_trie_params.huffman_tree, g_trie_params.huffman_tree_size,
+      g_trie_params.trie, g_trie_params.trie_bits,
+      g_trie_params.trie_root_position);
   std::string skeleton;
   ustr_skeleton.toUTF8String(skeleton);
   DCHECK_NE(skeleton.back(), '.');
@@ -52,10 +98,15 @@
 
   while (labels.size() > 1) {
     std::string partial_skeleton = base::JoinString(labels, ".");
-    if (net::LookupStringInFixedSet(
-            g_graph, g_graph_length, partial_skeleton.data(),
-            partial_skeleton.length()) != net::kDafsaNotFound)
+    bool match = false;
+    bool decoded = preload_decoder.Decode(partial_skeleton, &match);
+    DCHECK(decoded);
+    if (!decoded)
+      return false;
+
+    if (match)
       return true;
+
     labels.erase(labels.begin());
   }
   return false;
@@ -439,15 +490,17 @@
   uspoof_setAllowedUnicodeSet(checker_, &allowed_set, status);
 }
 
-void IDNSpoofChecker::RestoreTopDomainGraphToDefault() {
-  g_graph = kDafsa;
-  g_graph_length = sizeof(kDafsa);
+// static
+void IDNSpoofChecker::SetTrieParamsForTesting(
+    const HuffmanTrieParams& trie_params) {
+  g_trie_params = trie_params;
 }
 
-void IDNSpoofChecker::SetTopDomainGraph(base::StringPiece domain_graph) {
-  DCHECK_NE(0u, domain_graph.length());
-  g_graph = reinterpret_cast<const unsigned char*>(domain_graph.data());
-  g_graph_length = domain_graph.length();
+// static
+void IDNSpoofChecker::RestoreTrieParamsForTesting() {
+  g_trie_params = HuffmanTrieParams{
+      kTopDomainsHuffmanTree, sizeof(kTopDomainsHuffmanTree), kTopDomainsTrie,
+      kTopDomainsTrieBits, kTopDomainsRootPosition};
 }
 
 }  // namespace url_formatter
diff --git a/components/url_formatter/idn_spoof_checker.h b/components/url_formatter/idn_spoof_checker.h
index 5778c3b..ea235ad 100644
--- a/components/url_formatter/idn_spoof_checker.h
+++ b/components/url_formatter/idn_spoof_checker.h
@@ -11,6 +11,8 @@
 #include "base/gtest_prod_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_piece_forward.h"
+#include "net/extras/preload_data/decoder.h"
+
 #include "third_party/icu/source/common/unicode/uniset.h"
 #include "third_party/icu/source/common/unicode/utypes.h"
 #include "third_party/icu/source/common/unicode/uversion.h"
@@ -35,6 +37,13 @@
 
 class IDNSpoofChecker {
  public:
+  struct HuffmanTrieParams {
+    const uint8_t* huffman_tree;
+    size_t huffman_tree_size;
+    const uint8_t* trie;
+    size_t trie_bits;
+    size_t trie_root_position;
+  };
   IDNSpoofChecker();
   ~IDNSpoofChecker();
 
@@ -62,8 +71,8 @@
   bool IsMadeOfLatinAlikeCyrillic(const icu::UnicodeString& label);
 
   // Used for unit tests.
-  static void RestoreTopDomainGraphToDefault();
-  static void SetTopDomainGraph(base::StringPiece domain_graph);
+  static void SetTrieParamsForTesting(const HuffmanTrieParams& trie_params);
+  static void RestoreTrieParamsForTesting();
 
   USpoofChecker* checker_;
   icu::UnicodeSet deviation_characters_;
diff --git a/components/url_formatter/top_domains/BUILD.gn b/components/url_formatter/top_domains/BUILD.gn
index 2dfa592..69c05de7 100644
--- a/components/url_formatter/top_domains/BUILD.gn
+++ b/components/url_formatter/top_domains/BUILD.gn
@@ -2,26 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-action_foreach("top_domains") {
-  script = "//net/tools/dafsa/make_dafsa.py"
-  sources = [
-    "alexa_skeletons.gperf",
-    "test_skeletons.gperf",
-  ]
-  outputs = [
-    "${target_gen_dir}/{{source_name_part}}-inc.cc",
-  ]
-  args = [
-    "{{source}}",
-    rebase_path("${target_gen_dir}/{{source_name_part}}-inc.cc",
-                root_build_dir),
-  ]
-}
+import("//build/compiled_action.gni")
 
 if (!is_ios && !is_android) {
-  executable("make_top_domain_gperf") {
+  executable("make_top_domain_skeletons") {
     sources = [
-      "make_top_domain_gperf.cc",
+      "make_top_domain_skeletons.cc",
     ]
 
     deps = [
@@ -31,3 +17,56 @@
     ]
   }
 }
+
+executable("top_domain_generator") {
+  sources = [
+    "top_domain_generator.cc",
+    "top_domain_state_generator.cc",
+    "top_domain_state_generator.h",
+    "trie_entry.cc",
+    "trie_entry.h",
+  ]
+  deps = [
+    "//base",
+    "//build/config:exe_and_shlib_deps",
+    "//net/tools/huffman_trie:huffman_trie_generator_sources",
+  ]
+  if (is_ios) {
+    libs = [ "UIKit.framework" ]
+  }
+}
+
+compiled_action("generate_top_domains_trie") {
+  tool = ":top_domain_generator"
+
+  # Inputs in order expected by the command line of the tool.
+  inputs = [
+    "//components/url_formatter/top_domains/alexa_domains.skeletons",
+    "//components/url_formatter/top_domains/top_domains_trie.template",
+  ]
+  outputs = [
+    "$target_gen_dir/alexa_domains-trie-inc.cc",
+  ]
+  args =
+      # Make sure the inputs are system-absolute, as base::File cannot open
+      # files with ".." components.
+      rebase_path(inputs, "", "/") + rebase_path(outputs, root_build_dir)
+}
+
+# TODO: Combine this and the previous one into a compiled_action_foreach target.
+compiled_action("generate_top_domains_test_trie") {
+  tool = ":top_domain_generator"
+
+  # Inputs in order expected by the command line of the tool.
+  inputs = [
+    "//components/url_formatter/top_domains/test_domains.skeletons",
+    "//components/url_formatter/top_domains/top_domains_trie.template",
+  ]
+  outputs = [
+    "$target_gen_dir/test_domains-trie-inc.cc",
+  ]
+  args =
+      # Make sure the inputs are system-absolute, as base::File cannot open
+      # files with ".." components.
+      rebase_path(inputs, "", "/") + rebase_path(outputs, root_build_dir)
+}
diff --git a/components/url_formatter/top_domains/alexa_domains.skeletons b/components/url_formatter/top_domains/alexa_domains.skeletons
new file mode 100644
index 0000000..94548d6c
--- /dev/null
+++ b/components/url_formatter/top_domains/alexa_domains.skeletons
@@ -0,0 +1,9184 @@
+# 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.
+
+# This file is generated by components/url_formatter/make_top_domain_skeletons.cc
+# DO NOT MANUALLY EDIT!
+
+# Each entry is the skeleton of a top domain for the confusability check
+# in components/url_formatter/url_formatter.cc.
+
+facebook.corn, facebook.com
+google.corn, google.com
+youtube.corn, youtube.com
+yahoo.corn, yahoo.com
+baidu.corn, baidu.com
+arnazon.corn, amazon.com
+wikipedia.org, wikipedia.org
+qq.corn, qq.com
+live.corn, live.com
+taobao.corn, taobao.com
+google.co.in, google.co.in
+twitter.corn, twitter.com
+blogspot.corn, blogspot.com
+linkedin.corn, linkedin.com
+bing.corn, bing.com
+yandex.ru, yandex.ru
+vk.corn, vk.com
+ask.corn, ask.com
+ebay.corn, ebay.com
+wordpress.corn, wordpress.com
+google.de, google.de
+rnsn.corn, msn.com
+turnblr.corn, tumblr.com
+l63.corn, 163.com
+google.corn.hk, google.com.hk
+rnail.ru, mail.ru
+google.co.uk, google.co.uk
+haol23.corn, hao123.com
+google.corn.br, google.com.br
+weibo.corn, weibo.com
+xvideos.corn, xvideos.com
+rnicrosoft.corn, microsoft.com
+delta-search.corn, delta-search.com
+google.fr, google.fr
+conduit.corn, conduit.com
+fc2.corn, fc2.com
+craigslist.org, craigslist.org
+google.ru, google.ru
+pinterest.corn, pinterest.com
+instagrarn.corn, instagram.com
+trnall.corn, tmall.com
+xharnster.corn, xhamster.com
+odnoklassniki.ru, odnoklassniki.ru
+google.it, google.it
+sohu.corn, sohu.com
+paypal.corn, paypal.com
+babylon.corn, babylon.com
+google.es, google.es
+irndb.corn, imdb.com
+apple.corn, apple.com
+arnazon.de, amazon.de
+bbc.co.uk, bbc.co.uk
+adobe.corn, adobe.com
+soso.corn, soso.com
+pornhub.corn, pornhub.com
+google.corn.rnx, google.com.mx
+blogger.corn, blogger.com
+neobux.corn, neobux.com
+arnazon.co.uk, amazon.co.uk
+ifeng.corn, ifeng.com
+google.ca, google.ca
+avg.corn, avg.com
+go.corn, go.com
+xnxx.corn, xnxx.com
+blogspot.in, blogspot.in
+alibaba.corn, alibaba.com
+aol.corn, aol.com
+buildathorne.info, buildathome.info
+cnn.corn, cnn.com
+rnywebsearch.corn, mywebsearch.com
+ku6.corn, ku6.com
+alipay.corn, alipay.com
+vube.corn, vube.com
+google.corn.tr, google.com.tr
+youku.corn, youku.com
+redtube.corn, redtube.com
+dailyrnotion.corn, dailymotion.com
+google.corn.au, google.com.au
+adf.ly, adf.ly
+netflix.corn, netflix.com
+adcash.corn, adcash.com
+about.corn, about.com
+google.pl, google.pl
+irngur.corn, imgur.com
+ebay.de, ebay.de
+arnazon.fr, amazon.fr
+flickr.corn, flickr.com
+thepiratebay.sx, thepiratebay.sx
+youporn.corn, youporn.com
+uol.corn.br, uol.com.br
+huffingtonpost.corn, huffingtonpost.com
+stackoverflow.corn, stackoverflow.com
+jd.corn, jd.com
+t.co, t.co
+livejasrnin.corn, livejasmin.com
+ebay.co.uk, ebay.co.uk
+yieldrnanager.corn, yieldmanager.com
+sogou.corn, sogou.com
+globo.corn, globo.com
+softonic.corn, softonic.com
+cnet.corn, cnet.com
+livedoor.corn, livedoor.com
+directrev.corn, directrev.com
+espn.go.corn, espn.go.com
+indiatirnes.corn, indiatimes.com
+wordpress.org, wordpress.org
+weather.corn, weather.com
+pixnet.net, pixnet.net
+google.corn.sa, google.com.sa
+clkrnon.corn, clkmon.com
+reddit.corn, reddit.com
+arnazon.it, amazon.it
+google.corn.eg, google.com.eg
+booking.corn, booking.com
+google.nl, google.nl
+douban.corn, douban.com
+slideshare.net, slideshare.net
+google.corn.ar, google.com.ar
+badoo.corn, badoo.com
+dailyrnail.co.uk, dailymail.co.uk
+google.co.th, google.co.th
+ask.frn, ask.fm
+wikia.corn, wikia.com
+godaddy.corn, godaddy.com
+xinhuanet.corn, xinhuanet.com
+rnediafire.corn, mediafire.com
+deviantart.corn, deviantart.com
+google.corn.pk, google.com.pk
+bankofarnerica.corn, bankofamerica.com
+arnazon.es, amazon.es
+blogfa.corn, blogfa.com
+nytirnes.corn, nytimes.com
+4shared.corn, 4shared.com
+google.co.id, google.co.id
+youjizz.corn, youjizz.com
+arnazonaws.corn, amazonaws.com
+tube8.corn, tube8.com
+kickass.to, kickass.to
+livejournal.corn, livejournal.com
+snapdo.corn, snapdo.com
+google.co.za, google.co.za
+virneo.corn, vimeo.com
+wigetrnedia.corn, wigetmedia.com
+yelp.corn, yelp.com
+outbrain.corn, outbrain.com
+dropbox.corn, dropbox.com
+siteadvisor.corn, siteadvisor.com
+foxnews.corn, foxnews.com
+renren.corn, renren.com
+aliexpress.corn, aliexpress.com
+walrnart.corn, walmart.com
+skype.corn, skype.com
+ilivid.corn, ilivid.com
+bizcoaching.info, bizcoaching.info
+wikirnedia.org, wikimedia.org
+flipkart.corn, flipkart.com
+zedo.corn, zedo.com
+searchnu.corn, searchnu.com
+indeed.corn, indeed.com
+leboncoin.fr, leboncoin.fr
+liveinternet.ru, liveinternet.ru
+google.co.ve, google.co.ve
+56.corn, 56.com
+google.corn.vn, google.com.vn
+google.gr, google.gr
+corncast.net, comcast.net
+torrentz.eu, torrentz.eu
+etsy.corn, etsy.com
+orange.fr, orange.fr
+systweak.corn, systweak.com
+onet.pl, onet.pl
+wellsfargo.corn, wellsfargo.com
+letv.corn, letv.com
+goodgarnestudios.corn, goodgamestudios.com
+secureserver.net, secureserver.net
+allegro.pl, allegro.pl
+therneforest.net, themeforest.net
+tripadvisor.corn, tripadvisor.com
+web.de, web.de
+answers.corn, answers.com
+arnazon.ca, amazon.ca
+rnozilla.org, mozilla.org
+guardian.co.uk, guardian.co.uk
+sturnbleupon.corn, stumbleupon.com
+hardsextube.corn, hardsextube.com
+espncricinfo.corn, espncricinfo.com
+grnx.net, gmx.net
+photobucket.corn, photobucket.com
+ehow.corn, ehow.com
+rediff.corn, rediff.com
+popads.net, popads.net
+wikihow.corn, wikihow.com
+search-results.corn, search-results.com
+fiverr.corn, fiverr.com
+google.corn.ua, google.com.ua
+files.wordpress.corn, files.wordpress.com
+onlineaway.net, onlineaway.net
+nbcnews.corn, nbcnews.com
+google.corn.co, google.com.co
+hootsuite.corn, hootsuite.com
+4dsply.corn, 4dsply.com
+google.ro, google.ro
+sourceforge.net, sourceforge.net
+cnzz.corn, cnzz.com
+java.corn, java.com
+hudong.corn, hudong.com
+ucoz.ru, ucoz.ru
+tudou.corn, tudou.com
+addthis.corn, addthis.com
+google.corn.ng, google.com.ng
+soundcloud.corn, soundcloud.com
+onclickads.net, onclickads.net
+google.corn.ph, google.com.ph
+reference.corn, reference.com
+google.be, google.be
+wp.pl, wp.pl
+interbiz.rne, interbiz.me
+beeg.corn, beeg.com
+rarnbler.ru, rambler.ru
+sweetirn.corn, sweetim.com
+aweber.corn, aweber.com
+google.corn.rny, google.com.my
+pandora.corn, pandora.com
+w3schools.corn, w3schools.com
+pengyou.corn, pengyou.com
+archive.org, archive.org
+qvo6.corn, qvo6.com
+bet365.corn, bet365.com
+etao.corn, etao.com
+lollipop-network.corn, lollipop-network.com
+qtrax.corn, qtrax.com
+google.se, google.se
+google.dz, google.dz
+usatoday.corn, usatoday.com
+zillow.corn, zillow.com
+goal.corn, goal.com
+avito.ru, avito.ru
+kaixinOOl.corn, kaixin001.com
+yesky.corn, yesky.com
+rnobileOl.corn, mobile01.com
+soufun.corn, soufun.com
+tagged.corn, tagged.com
+warriorforurn.corn, warriorforum.com
+statcounter.corn, statcounter.com
+google.corn.pe, google.com.pe
+libero.it, libero.it
+thefreedictionary.corn, thefreedictionary.com
+soku.corn, soku.com
+incredibar.corn, incredibar.com
+kaskus.co.id, kaskus.co.id
+likes.corn, likes.com
+weebly.corn, weebly.com
+iqiyi.corn, iqiyi.com
+pch.corn, pch.com
+sarnsung.corn, samsung.com
+linkbucks.corn, linkbucks.com
+uploaded.net, uploaded.net
+bild.de, bild.de
+google.corn.bd, google.com.bd
+google.at, google.at
+webcrawler.corn, webcrawler.com
+t-online.de, t-online.de
+irninent.corn, iminent.com
+google.pt, google.pt
+detik.corn, detik.com
+ganji.corn, ganji.com
+rnilliyet.corn.tr, milliyet.com.tr
+bleacherreport.corn, bleacherreport.com
+forbes.corn, forbes.com
+twoo.corn, twoo.com
+olx.in, olx.in
+rnercadolivre.corn.br, mercadolivre.com.br
+hurriyet.corn.tr, hurriyet.com.tr
+pof.corn, pof.com
+wsj.corn, wsj.com
+hostgator.corn, hostgator.com
+naver.corn, naver.com
+putlocker.corn, putlocker.com
+varzesh3.corn, varzesh3.com
+rutracker.org, rutracker.org
+optrnd.corn, optmd.com
+yourn7.corn, youm7.com
+google.cl, google.cl
+ikea.corn, ikea.com
+4399.corn, 4399.com
+salesforce.corn, salesforce.com
+scribd.corn, scribd.com
+google.corn.sg, google.com.sg
+itl68.corn, it168.com
+goodreads.corn, goodreads.com
+target.corn, target.com
+xunlei.corn, xunlei.com
+hulu.corn, hulu.com
+github.corn, github.com
+hp.corn, hp.com
+buzzfeed.corn, buzzfeed.com
+google.ch, google.ch
+youdao.corn, youdao.com
+blogspot.corn.es, blogspot.com.es
+so.corn, so.com
+ups.corn, ups.com
+extratorrent.corn, extratorrent.com
+rnatch.corn, match.com
+seznarn.cz, seznam.cz
+naukri.corn, naukri.com
+drtuber.corn, drtuber.com
+spiegel.de, spiegel.de
+rnarca.corn, marca.com
+ign.corn, ign.com
+dornaintools.corn, domaintools.com
+free.fr, free.fr
+telegraph.co.uk, telegraph.co.uk
+rnypcbackup.corn, mypcbackup.com
+kakaku.corn, kakaku.com
+irnageshack.us, imageshack.us
+reuters.corn, reuters.com
+ndtv.corn, ndtv.com
+ig.corn.br, ig.com.br
+bestbuy.corn, bestbuy.com
+glispa.corn, glispa.com
+quikr.corn, quikr.com
+deadlyblessing.corn, deadlyblessing.com
+wix.corn, wix.com
+paipai.corn, paipai.com
+ebay.corn.au, ebay.com.au
+yandex.ua, yandex.ua
+chinanews.corn, chinanews.com
+clixsense.corn, clixsense.com
+nih.gov, nih.gov
+aili.corn, aili.com
+zing.vn, zing.vn
+pchorne.net, pchome.net
+webrnd.corn, webmd.com
+terra.corn.br, terra.com.br
+pixiv.net, pixiv.net
+in.corn, in.com
+csdn.net, csdn.net
+pcpop.corn, pcpop.com
+google.co.hu, google.co.hu
+lnksr.corn, lnksr.com
+jobrapido.corn, jobrapido.com
+inbox.corn, inbox.com
+dianping.corn, dianping.com
+gsrnarena.corn, gsmarena.com
+rnlb.corn, mlb.com
+clicksor.corn, clicksor.com
+hdfcbank.corn, hdfcbank.com
+acesse.corn, acesse.com
+hornedepot.corn, homedepot.com
+twitch.tv, twitch.tv
+rnorefreecarnsecrets.corn, morefreecamsecrets.com
+groupon.corn, groupon.com
+lnksdata.corn, lnksdata.com
+google.cz, google.cz
+usps.corn, usps.com
+xyxy.net, xyxy.net
+att.corn, att.com
+webs.corn, webs.com
+5ljob.corn, 51job.com
+rnashable.corn, mashable.com
+yihaodian.corn, yihaodian.com
+taringa.net, taringa.net
+fedex.corn, fedex.com
+blogspot.co.uk, blogspot.co.uk
+cklOl.corn, ck101.com
+abcnews.go.corn, abcnews.go.com
+washingtonpost.corn, washingtonpost.com
+narod.ru, narod.ru
+china.corn, china.com
+doubleclick.corn, doubleclick.com
+carn4.corn, cam4.com
+google.ie, google.ie
+dangdang.corn, dangdang.com
+arnericanexpress.corn, americanexpress.com
+disqus.corn, disqus.com
+ixxx.corn, ixxx.com
+39.net, 39.net
+isohunt.corn, isohunt.com
+php.net, php.net
+exoclick.corn, exoclick.com
+shutterstock.corn, shutterstock.com
+dell.corn, dell.com
+google.ae, google.ae
+histats.corn, histats.com
+outlook.corn, outlook.com
+wordreference.corn, wordreference.com
+sahibinden.corn, sahibinden.com
+l26.corn, 126.com
+oyodorno.corn, oyodomo.com
+gazeta.pl, gazeta.pl
+expedia.corn, expedia.com
+kijiji.ca, kijiji.ca
+rnyfreecarns.corn, myfreecams.com
+capitalone.corn, capitalone.com
+rnoz.corn, moz.com
+qunar.corn, qunar.com
+taleo.net, taleo.net
+google.co.il, google.co.il
+rnicrosoftonline.corn, microsoftonline.com
+datasrvrs.corn, datasrvrs.com
+zippyshare.corn, zippyshare.com
+google.no, google.no
+justdial.corn, justdial.com
+2345.corn, 2345.com
+adultfriendfinder.corn, adultfriendfinder.com
+shaadi.corn, shaadi.com
+rnobile.de, mobile.de
+abril.corn.br, abril.com.br
+ernpowernetwork.corn, empowernetwork.com
+icicibank.corn, icicibank.com
+xe.corn, xe.com
+rnailchirnp.corn, mailchimp.com
+fbcdn.net, fbcdn.net
+ccb.corn, ccb.com
+huanqiu.corn, huanqiu.com
+seesaa.net, seesaa.net
+jirndo.corn, jimdo.com
+fucked-tube.corn, fucked-tube.com
+google.dk, google.dk
+yellowpages.corn, yellowpages.com
+constantcontact.corn, constantcontact.com
+tinyurl.corn, tinyurl.com
+rnysearchresults.corn, mysearchresults.com
+friv.corn, friv.com
+ebay.it, ebay.it
+aizhan.corn, aizhan.com
+accuweather.corn, accuweather.com
+5lbuy.corn, 51buy.com
+snapdeal.corn, snapdeal.com
+google.az, google.az
+pogo.corn, pogo.com
+adultadworld.corn, adultadworld.com
+nifty.corn, nifty.com
+bitauto.corn, bitauto.com
+drudgereport.corn, drudgereport.com
+bloornberg.corn, bloomberg.com
+vnexpress.net, vnexpress.net
+eastrnoney.corn, eastmoney.com
+verizonwireless.corn, verizonwireless.com
+onlinesbi.corn, onlinesbi.com
+2ch.net, 2ch.net
+speedtest.net, speedtest.net
+largeporntube.corn, largeporntube.com
+stackexchange.corn, stackexchange.com
+roblox.corn, roblox.com
+rniniclip.corn, miniclip.com
+trnz.corn, tmz.com
+google.fi, google.fi
+ning.corn, ning.com
+rnonster.corn, monster.com
+rnihanblog.corn, mihanblog.com
+stearnpowered.corn, steampowered.com
+nuvid.corn, nuvid.com
+kooora.corn, kooora.com
+ebay.in, ebay.in
+rnp3skull.corn, mp3skull.com
+blogspot.ru, blogspot.ru
+duowan.corn, duowan.com
+blogspot.de, blogspot.de
+fhserve.corn, fhserve.com
+rnoneycontrol.corn, moneycontrol.com
+pornerbros.corn, pornerbros.com
+eazel.corn, eazel.com
+daurn.net, daum.net
+lady8844.corn, lady8844.com
+rapidgator.net, rapidgator.net
+thesun.co.uk, thesun.co.uk
+youtube-rnp3.org, youtube-mp3.org
+v9.corn, v9.com
+disney.go.corn, disney.go.com
+porntube.corn, porntube.com
+surveyrnonkey.corn, surveymonkey.com
+rneetup.corn, meetup.com
+ero-advertising.corn, ero-advertising.com
+bravotube.net, bravotube.net
+appround.biz, appround.biz
+blogspot.it, blogspot.it
+ctrip.corn, ctrip.com
+9gag.corn, 9gag.com
+odesk.corn, odesk.com
+kinopoisk.ru, kinopoisk.ru
+trulia.corn, trulia.com
+rnercadolibre.corn.ar, mercadolibre.com.ar
+repubblica.it, repubblica.it
+hupu.corn, hupu.com
+irnesh.corn, imesh.com
+searchfunrnoods.corn, searchfunmoods.com
+backpage.corn, backpage.com
+latirnes.corn, latimes.com
+news.corn.au, news.com.au
+gc.ca, gc.ca
+hubpages.corn, hubpages.com
+clickbank.corn, clickbank.com
+rnapquest.corn, mapquest.com
+sweetpacks.corn, sweetpacks.com
+hypergarnes.net, hypergames.net
+alirnarna.corn, alimama.com
+cnblogs.corn, cnblogs.com
+vancl.corn, vancl.com
+bitly.corn, bitly.com
+tokobagus.corn, tokobagus.com
+webrnoney.ru, webmoney.ru
+google.sk, google.sk
+shopathorne.corn, shopathome.com
+elpais.corn, elpais.com
+oneindia.in, oneindia.in
+codecanyon.net, codecanyon.net
+businessinsider.corn, businessinsider.com
+blackhatworld.corn, blackhatworld.com
+farsnews.corn, farsnews.com
+spankwire.corn, spankwire.com
+rnynet.corn, mynet.com
+sape.ru, sape.ru
+bhaskar.corn, bhaskar.com
+lenta.ru, lenta.ru
+gutefrage.net, gutefrage.net
+nba.corn, nba.com
+feedly.corn, feedly.com
+chaturbate.corn, chaturbate.com
+elrnundo.es, elmundo.es
+ad6rnedia.fr, ad6media.fr
+sberbank.ru, sberbank.ru
+lockyourhorne.corn, lockyourhome.com
+kinox.to, kinox.to
+subito.it, subito.it
+rbc.ru, rbc.ru
+sfr.fr, sfr.fr
+skyrock.corn, skyrock.com
+priceline.corn, priceline.com
+jabong.corn, jabong.com
+y8.corn, y8.com
+wunderground.corn, wunderground.com
+habrahabr.ru, habrahabr.ru
+softpedia.corn, softpedia.com
+ancestry.corn, ancestry.com
+bluehost.corn, bluehost.com
+l23rf.corn, 123rf.com
+lowes.corn, lowes.com
+free-tv-video-online.rne, free-tv-video-online.me
+tabelog.corn, tabelog.com
+vehnix.corn, vehnix.com
+55bbs.corn, 55bbs.com
+swagbucks.corn, swagbucks.com
+speedanalysis.net, speedanalysis.net
+virgilio.it, virgilio.it
+peyvandha.ir, peyvandha.ir
+infusionsoft.corn, infusionsoft.com
+newegg.corn, newegg.com
+sulekha.corn, sulekha.com
+rnyspace.corn, myspace.com
+yxlady.corn, yxlady.com
+haber7.corn, haber7.com
+w3.org, w3.org
+squidoo.corn, squidoo.com
+hotels.corn, hotels.com
+oracle.corn, oracle.com
+fatakat.corn, fatakat.com
+joornla.org, joomla.org
+qidian.corn, qidian.com
+adbooth.net, adbooth.net
+wretch.cc, wretch.cc
+freelancer.corn, freelancer.com
+typepad.corn, typepad.com
+foxsports.corn, foxsports.com
+allrecipes.corn, allrecipes.com
+searchengines.ru, searchengines.ru
+babytree.corn, babytree.com
+interia.pl, interia.pl
+xharnstercarns.corn, xhamstercams.com
+verizon.corn, verizon.com
+intoday.in, intoday.in
+sears.corn, sears.com
+okcupid.corn, okcupid.com
+kornpas.corn, kompas.com
+cj.corn, cj.com
+4tube.corn, 4tube.com
+chip.de, chip.de
+force.corn, force.com
+advertserve.corn, advertserve.com
+rnaktoob.corn, maktoob.com
+24h.corn.vn, 24h.com.vn
+foursquare.corn, foursquare.com
+cbsnews.corn, cbsnews.com
+pornhublive.corn, pornhublive.com
+xda-developers.corn, xda-developers.com
+rnilanuncios.corn, milanuncios.com
+retailrnenot.corn, retailmenot.com
+keezrnovies.corn, keezmovies.com
+nydailynews.corn, nydailynews.com
+h2porn.corn, h2porn.com
+careerbuilder.corn, careerbuilder.com
+xing.corn, xing.com
+citibank.corn, citibank.com
+linkwithin.corn, linkwithin.com
+singlessalad.corn, singlessalad.com
+altervista.org, altervista.org
+turbobit.net, turbobit.net
+zoosk.corn, zoosk.com
+digg.corn, digg.com
+hespress.corn, hespress.com
+bigpoint.corn, bigpoint.com
+yourlust.corn, yourlust.com
+rnyntra.corn, myntra.com
+issuu.corn, issuu.com
+rnacys.corn, macys.com
+google.bg, google.bg
+github.io, github.io
+filestube.corn, filestube.com
+crnbchina.corn, cmbchina.com
+irctc.co.in, irctc.co.in
+filehippo.corn, filehippo.com
+rnop.corn, mop.com
+bodybuilding.corn, bodybuilding.com
+paidui.corn, paidui.com
+zirnbio.corn, zimbio.com
+panet.co.il, panet.co.il
+rngid.corn, mgid.com
+ya.ru, ya.ru
+probux.corn, probux.com
+haberturk.corn, haberturk.com
+persianblog.ir, persianblog.ir
+rneituan.corn, meituan.com
+rnercadolibre.corn.rnx, mercadolibre.com.mx
+ppstrearn.corn, ppstream.com
+sunporno.corn, sunporno.com
+vodly.to, vodly.to
+forgeofernpires.corn, forgeofempires.com
+elance.corn, elance.com
+adscale.de, adscale.de
+vipshop.corn, vipshop.com
+babycenter.corn, babycenter.com
+istockphoto.corn, istockphoto.com
+cornrnentcarnarche.net, commentcamarche.net
+upworthy.corn, upworthy.com
+download.corn, download.com
+battle.net, battle.net
+beva.corn, beva.com
+list-rnanage.corn, list-manage.com
+corriere.it, corriere.it
+noticias24.corn, noticias24.com
+ucoz.corn, ucoz.com
+porn.corn, porn.com
+google.lk, google.lk
+lifehacker.corn, lifehacker.com
+today.corn, today.com
+chinabyte.corn, chinabyte.com
+southwest.corn, southwest.com
+ca.gov, ca.gov
+nudevista.corn, nudevista.com
+yandex.corn.tr, yandex.com.tr
+people.corn, people.com
+docin.corn, docin.com
+norton.corn, norton.com
+perfectgirls.net, perfectgirls.net
+engadget.corn, engadget.com
+realtor.corn, realtor.com
+techcrunch.corn, techcrunch.com
+tirne.corn, time.com
+indianrail.gov.in, indianrail.gov.in
+dtiblog.corn, dtiblog.com
+way2srns.corn, way2sms.com
+foodnetwork.corn, foodnetwork.com
+subscene.corn, subscene.com
+worldstarhiphop.corn, worldstarhiphop.com
+tabnak.ir, tabnak.ir
+aeriagarnes.corn, aeriagames.com
+leagueoflegends.corn, leagueoflegends.com
+5l.la, 51.la
+facenarna.corn, facenama.com
+sapo.pt, sapo.pt
+bitshare.corn, bitshare.com
+garnespot.corn, gamespot.com
+cy-pr.corn, cy-pr.com
+kankan.corn, kankan.com
+google.co.nz, google.co.nz
+liveleak.corn, liveleak.com
+video-one.corn, video-one.com
+rnarktplaats.nl, marktplaats.nl
+elwatannews.corn, elwatannews.com
+roulettebotplus.corn, roulettebotplus.com
+adserverplus.corn, adserverplus.com
+akhbarak.net, akhbarak.net
+gurntree.corn, gumtree.com
+weheartit.corn, weheartit.com
+openadserving.corn, openadserving.com
+sporx.corn, sporx.com
+rnercadolibre.corn.ve, mercadolibre.com.ve
+zendesk.corn, zendesk.com
+houzz.corn, houzz.com
+asos.corn, asos.com
+letitbit.net, letitbit.net
+quora.corn, quora.com
+yandex.kz, yandex.kz
+rncafee.corn, mcafee.com
+ensonhaber.corn, ensonhaber.com
+garnefaqs.corn, gamefaqs.com
+vk.rne, vk.me
+avast.corn, avast.com
+website-unavailable.corn, website-unavailable.com
+22find.corn, 22find.com
+adrnagnet.net, admagnet.net
+rottentornatoes.corn, rottentomatoes.com
+google.corn.kw, google.com.kw
+cloob.corn, cloob.com
+nokia.corn, nokia.com
+wetter.corn, wetter.com
+taboola.corn, taboola.com
+tenpay.corn, tenpay.com
+888.corn, 888.com
+flipora.corn, flipora.com
+adhitprofits.corn, adhitprofits.com
+tirneanddate.corn, timeanddate.com
+as.corn, as.com
+fanpop.corn, fanpop.com
+inforrner.corn, informer.com
+over-blog.corn, over-blog.com
+itau.corn.br, itau.com.br
+balagana.net, balagana.net
+ellechina.corn, ellechina.com
+avazutracking.net, avazutracking.net
+gap.corn, gap.com
+exarniner.corn, examiner.com
+vporn.corn, vporn.com
+lenovo.corn, lenovo.com
+eonline.corn, eonline.com
+r7.corn, r7.com
+rnajesticseo.corn, majesticseo.com
+irnrnobilienscout24.de, immobilienscout24.de
+google.kz, google.kz
+goo.gl, goo.gl
+zwaar.net, zwaar.net
+bankrnellat.ir, bankmellat.ir
+alphaporno.corn, alphaporno.com
+whitepages.corn, whitepages.com
+viva.co.id, viva.co.id
+rutor.org, rutor.org
+wiktionary.org, wiktionary.org
+intuit.corn, intuit.com
+gisrneteo.ru, gismeteo.ru
+dantri.corn.vn, dantri.com.vn
+xbox.corn, xbox.com
+rnyegy.corn, myegy.com
+xtube.corn, xtube.com
+rnasrawy.corn, masrawy.com
+urbandictionary.corn, urbandictionary.com
+agoda.corn, agoda.com
+ebay.fr, ebay.fr
+kickstarter.corn, kickstarter.com
+6park.corn, 6park.com
+rnetacafe.corn, metacafe.com
+yarnahaonlinestore.corn, yamahaonlinestore.com
+anysex.corn, anysex.com
+azlyrics.corn, azlyrics.com
+rt.corn, rt.com
+ibrn.corn, ibm.com
+nordstrorn.corn, nordstrom.com
+ezinearticles.corn, ezinearticles.com
+cnbc.corn, cnbc.com
+redtubelive.corn, redtubelive.com
+clicksvenue.corn, clicksvenue.com
+tradus.corn, tradus.com
+rn2newrnedia.corn, m2newmedia.com
+custhelp.corn, custhelp.com
+4chan.org, 4chan.org
+kioskea.net, kioskea.net
+yoka.corn, yoka.com
+7k7k.corn, 7k7k.com
+opensiteexplorer.org, opensiteexplorer.org
+rnusica.corn, musica.com
+coupons.corn, coupons.com
+cracked.corn, cracked.com
+caixa.gov.br, caixa.gov.br
+skysports.corn, skysports.com
+kizi.corn, kizi.com
+getresponse.corn, getresponse.com
+sky.corn, sky.com
+rnarketwatch.corn, marketwatch.com
+google.corn.ec, google.com.ec
+cbslocal.corn, cbslocal.com
+zhihu.corn, zhihu.com
+888poker.corn, 888poker.com
+digitalpoint.corn, digitalpoint.com
+blog.l63.corn, blog.163.com
+rantsports.corn, rantsports.com
+videosexarchive.corn, videosexarchive.com
+who.is, who.is
+gogetlinks.net, gogetlinks.net
+idnes.cz, idnes.cz
+king.corn, king.com
+say-rnove.org, say-move.org
+rnotherless.corn, motherless.com
+npr.org, npr.org
+legacy.corn, legacy.com
+aljazeera.net, aljazeera.net
+barnesandnoble.corn, barnesandnoble.com
+overstock.corn, overstock.com
+drorn.ru, drom.ru
+weather.gov, weather.gov
+gstatic.corn, gstatic.com
+arnung.us, amung.us
+traidnt.net, traidnt.net
+ovh.net, ovh.net
+rtl.de, rtl.de
+howstuffworks.corn, howstuffworks.com
+digikala.corn, digikala.com
+bannersbroker.corn, bannersbroker.com
+kohls.corn, kohls.com
+google.corn.do, google.com.do
+dealfish.co.th, dealfish.co.th
+l9lou.corn, 19lou.com
+ezpowerads.corn, ezpowerads.com
+lernonde.fr, lemonde.fr
+chexun.corn, chexun.com
+irnagebarn.corn, imagebam.com
+viooz.co, viooz.co
+prothorn-alo.corn, prothom-alo.com
+36Odoc.corn, 360doc.com
+rn-w.corn, m-w.com
+fanfiction.net, fanfiction.net
+sernrush.corn, semrush.com
+cil23.corn, ci123.com
+plugrush.corn, plugrush.com
+cafernorn.corn, cafemom.com
+rnangareader.net, mangareader.net
+haizhangs.corn, haizhangs.com
+cdiscount.corn, cdiscount.com
+zappos.corn, zappos.com
+rnanta.corn, manta.com
+novinky.cz, novinky.cz
+hi5.corn, hi5.com
+pr-cy.ru, pr-cy.ru
+rnovie4k.to, movie4k.to
+patch.corn, patch.com
+alarabiya.net, alarabiya.net
+indiarnart.corn, indiamart.com
+cartrailor.corn, cartrailor.com
+alrnasryalyourn.corn, almasryalyoum.com
+3l5che.corn, 315che.com
+google.by, google.by
+tornshardware.corn, tomshardware.com
+rninecraft.net, minecraft.net
+gulfup.corn, gulfup.com
+rr.corn, rr.com
+spotify.corn, spotify.com
+airtel.in, airtel.in
+espnfc.corn, espnfc.com
+sanook.corn, sanook.com
+ria.ru, ria.ru
+google.corn.qa, google.com.qa
+jquery.corn, jquery.com
+pinshan.corn, pinshan.com
+onlylady.corn, onlylady.com
+pornoxo.corn, pornoxo.com
+cookpad.corn, cookpad.com
+pagesjaunes.fr, pagesjaunes.fr
+usrnagazine.corn, usmagazine.com
+google.lt, google.lt
+nu.nl, nu.nl
+hrn.corn, hm.com
+fixya.corn, fixya.com
+theblaze.corn, theblaze.com
+cbssports.corn, cbssports.com
+eyny.corn, eyny.com
+l7l73.corn, 17173.com
+hc36O.corn, hc360.com
+cbs.corn, cbs.com
+telegraaf.nl, telegraaf.nl
+netlog.corn, netlog.com
+slickdeals.net, slickdeals.net
+yobt.corn, yobt.com
+certified-toolbar.corn, certified-toolbar.com
+rniercn.corn, miercn.com
+aparat.corn, aparat.com
+billdesk.corn, billdesk.com
+yandex.by, yandex.by
+888casino.corn, 888casino.com
+twitpic.corn, twitpic.com
+google.hr, google.hr
+tubegalore.corn, tubegalore.com
+dhgate.corn, dhgate.com
+rnakernytrip.corn, makemytrip.com
+shop.corn, shop.com
+nike.corn, nike.com
+kayak.corn, kayak.com
+fandango.corn, fandango.com
+tutsplus.corn, tutsplus.com
+gotorneeting.corn, gotomeeting.com
+shareasale.corn, shareasale.com
+rnpnrs.corn, mpnrs.com
+keepvid.corn, keepvid.com
+lequipe.fr, lequipe.fr
+narnecheap.corn, namecheap.com
+doublepirnp.corn, doublepimp.com
+softigloo.corn, softigloo.com
+givernesport.corn, givemesport.com
+rntirne.corn, mtime.com
+letras.rnus.br, letras.mus.br
+pole-ernploi.fr, pole-emploi.fr
+biblegateway.corn, biblegateway.com
+independent.co.uk, independent.co.uk
+e-hentai.org, e-hentai.org
+gurntree.corn.au, gumtree.com.au
+livestrong.corn, livestrong.com
+garne32l.corn, game321.com
+corncast.corn, comcast.com
+clubpenguin.corn, clubpenguin.com
+rightrnove.co.uk, rightmove.co.uk
+stearncornrnunity.corn, steamcommunity.com
+sockshare.corn, sockshare.com
+globalconsurnersurvey.corn, globalconsumersurvey.com
+rapidshare.corn, rapidshare.com
+auto.ru, auto.ru
+staples.corn, staples.com
+anitube.se, anitube.se
+rozblog.corn, rozblog.com
+reliancenetconnect.co.in, reliancenetconnect.co.in
+credit-agricole.fr, credit-agricole.fr
+exposedwebcarns.corn, exposedwebcams.com
+webalta.ru, webalta.ru
+usbank.corn, usbank.com
+google.corn.ly, google.com.ly
+pantip.corn, pantip.com
+aftonbladet.se, aftonbladet.se
+scoop.it, scoop.it
+rnayoclinic.corn, mayoclinic.com
+evernote.corn, evernote.com
+nyaa.eu, nyaa.eu
+livingsocial.corn, livingsocial.com
+noaa.gov, noaa.gov
+irnagefap.corn, imagefap.com
+abchina.corn, abchina.com
+google.rs, google.rs
+arnazon.in, amazon.in
+tnaflix.corn, tnaflix.com
+xici.net, xici.net
+united.corn, united.com
+ternplaternonster.corn, templatemonster.com
+deezer.corn, deezer.com
+pixlr.corn, pixlr.com
+tradedoubler.corn, tradedoubler.com
+gurntree.co.za, gumtree.co.za
+rlO.net, r10.net
+kongregate.corn, kongregate.com
+jeuxvideo.corn, jeuxvideo.com
+gawker.corn, gawker.com
+chewen.corn, chewen.com
+r2garnes.corn, r2games.com
+rnayajo.corn, mayajo.com
+topix.corn, topix.com
+easyhits4u.corn, easyhits4u.com
+netteller.corn, netteller.com
+ing.nl, ing.nl
+tripadvisor.co.uk, tripadvisor.co.uk
+udn.corn, udn.com
+cheezburger.corn, cheezburger.com
+fotostrana.ru, fotostrana.ru
+bbc.corn, bbc.com
+behance.net, behance.net
+lefigaro.fr, lefigaro.fr
+nikkei.corn, nikkei.com
+fidelity.corn, fidelity.com
+baornihua.corn, baomihua.com
+fool.corn, fool.com
+nairaland.corn, nairaland.com
+sendspace.corn, sendspace.com
+woot.corn, woot.com
+travelocity.corn, travelocity.com
+shopclues.corn, shopclues.com
+sureonlinefind.corn, sureonlinefind.com
+gizrnodo.corn, gizmodo.com
+hidernyass.corn, hidemyass.com
+o2.pl, o2.pl
+clickbank.net, clickbank.net
+fotolia.corn, fotolia.com
+opera.corn, opera.com
+sabah.corn.tr, sabah.com.tr
+n-rnobile.net, n-mobile.net
+chacha.corn, chacha.com
+autotrader.corn, autotrader.com
+anonyrn.to, anonym.to
+walrnart.corn.br, walmart.com.br
+yjc.ir, yjc.ir
+autoscout24.de, autoscout24.de
+gobookee.net, gobookee.net
+yaolan.corn, yaolan.com
+india.corn, india.com
+tribalfusion.corn, tribalfusion.com
+gittigidiyor.corn, gittigidiyor.com
+otto.de, otto.de
+adclickxpress.corn, adclickxpress.com
+rnade-in-china.corn, made-in-china.com
+ahrarn.org.eg, ahram.org.eg
+asriran.corn, asriran.com
+blackberry.corn, blackberry.com
+beytoote.corn, beytoote.com
+piriforrn.corn, piriform.com
+ilrneteo.it, ilmeteo.it
+att.net, att.net
+brainyquote.corn, brainyquote.com
+last.frn, last.fm
+directadvert.ru, directadvert.ru
+slate.corn, slate.com
+rnangahere.corn, mangahere.com
+jalan.net, jalan.net
+blog.corn, blog.com
+tuvaro.corn, tuvaro.com
+doc88.corn, doc88.com
+rnbc.net, mbc.net
+europa.eu, europa.eu
+onlinedown.net, onlinedown.net
+jcpenney.corn, jcpenney.com
+rnyplaycity.corn, myplaycity.com
+bahn.de, bahn.de
+laredoute.fr, laredoute.fr
+alexa.corn, alexa.com
+flashx.tv, flashx.tv
+5l.corn, 51.com
+rnail.corn, mail.com
+costco.corn, costco.com
+rnirror.co.uk, mirror.co.uk
+hubspot.corn, hubspot.com
+tfl.fr, tf1.fr
+rnerdeka.corn, merdeka.com
+nypost.corn, nypost.com
+lrnall.corn, 1mall.com
+wrntransfer.corn, wmtransfer.com
+pcrnag.corn, pcmag.com
+univision.corn, univision.com
+nationalgeographic.corn, nationalgeographic.com
+sourtirnes.org, sourtimes.org
+iciba.corn, iciba.com
+petardas.corn, petardas.com
+wrnrnail.ru, wmmail.ru
+light-dark.net, light-dark.net
+ultirnate-guitar.corn, ultimate-guitar.com
+korarngarne.corn, koramgame.com
+rnegavod.fr, megavod.fr
+srnh.corn.au, smh.com.au
+ticketrnaster.corn, ticketmaster.com
+adrnin5.corn, admin5.com
+get-a-fuck-tonight.corn, get-a-fuck-tonight.com
+eenadu.net, eenadu.net
+argos.co.uk, argos.co.uk
+nipic.corn, nipic.com
+google.iq, google.iq
+alhea.corn, alhea.com
+citrixonline.corn, citrixonline.com
+girlsgogarnes.corn, girlsgogames.com
+fanatik.corn.tr, fanatik.com.tr
+google.tn, google.tn
+usaa.corn, usaa.com
+earthlink.net, earthlink.net
+ryanair.corn, ryanair.com
+city-data.corn, city-data.com
+lloydstsb.co.uk, lloydstsb.co.uk
+pornsharia.corn, pornsharia.com
+baixing.corn, baixing.com
+all-free-download.corn, all-free-download.com
+qianyanOOl.corn, qianyan001.com
+hellporno.corn, hellporno.com
+pornrnd.corn, pornmd.com
+conferenceplus.corn, conferenceplus.com
+docstoc.corn, docstoc.com
+christian-dogrna.corn, christian-dogma.com
+drnoz.org, dmoz.org
+perezhilton.corn, perezhilton.com
+rnega.co.nz, mega.co.nz
+zazzle.corn, zazzle.com
+echoroukonline.corn, echoroukonline.com
+ea.corn, ea.com
+yiqifa.corn, yiqifa.com
+rnysearchdial.corn, mysearchdial.com
+hotwire.corn, hotwire.com
+ninernsn.corn.au, ninemsn.com.au
+tablica.pl, tablica.pl
+brazzers.corn, brazzers.com
+arnericanas.corn.br, americanas.com.br
+extrernetube.corn, extremetube.com
+zynga.corn, zynga.com
+buscape.corn.br, buscape.com.br
+t-rnobile.corn, t-mobile.com
+portaldosites.corn, portaldosites.com
+businessweek.corn, businessweek.com
+feedburner.corn, feedburner.com
+contenko.corn, contenko.com
+horneshopl8.corn, homeshop18.com
+brni.ir, bmi.ir
+wwe.corn, wwe.com
+adult-ernpire.corn, adult-empire.com
+nfl.corn, nfl.com
+globososo.corn, globososo.com
+sfgate.corn, sfgate.com
+rnrnotraffic.corn, mmotraffic.com
+zalando.de, zalando.de
+warthunder.corn, warthunder.com
+icloud.corn, icloud.com
+xiarni.corn, xiami.com
+newsrnax.corn, newsmax.com
+solarrnovie.so, solarmovie.so
+junglee.corn, junglee.com
+discovercard.corn, discovercard.com
+hh.ru, hh.ru
+searchengineland.corn, searchengineland.com
+labanquepostale.fr, labanquepostale.fr
+5lcto.corn, 51cto.com
+fling.corn, fling.com
+liveperson.net, liveperson.net
+sulit.corn.ph, sulit.com.ph
+tinypic.corn, tinypic.com
+rneilishuo.corn, meilishuo.com
+googleadservices.corn, googleadservices.com
+boston.corn, boston.com
+chron.corn, chron.com
+breitbart.corn, breitbart.com
+youjizzlive.corn, youjizzlive.com
+cornrnbank.corn.au, commbank.com.au
+axisbank.corn, axisbank.com
+wired.corn, wired.com
+trialpay.corn, trialpay.com
+berniaga.corn, berniaga.com
+cnrno.corn, cnmo.com
+tunein.corn, tunein.com
+hotfile.corn, hotfile.com
+dubizzle.corn, dubizzle.com
+olx.corn.br, olx.com.br
+haxiu.corn, haxiu.com
+zulily.corn, zulily.com
+infolinks.corn, infolinks.com
+yourgirlfriends.corn, yourgirlfriends.com
+logrnein.corn, logmein.com
+irs.gov, irs.gov
+noticiadeldia.corn, noticiadeldia.com
+nbcsports.corn, nbcsports.com
+holasearch.corn, holasearch.com
+indianexpress.corn, indianexpress.com
+depositfiles.corn, depositfiles.com
+elfagr.org, elfagr.org
+hirnado.in, himado.in
+lurnosity.corn, lumosity.com
+rnbank.corn.pl, mbank.com.pl
+prirnewire.ag, primewire.ag
+drearnstirne.corn, dreamstime.com
+sootoo.corn, sootoo.com
+souq.corn, souq.com
+craigslist.ca, craigslist.ca
+zara.corn, zara.com
+groupon.it, groupon.it
+rnangafox.rne, mangafox.me
+casino.corn, casino.com
+arrnorgarnes.corn, armorgames.com
+zanox.corn, zanox.com
+finn.no, finn.no
+qihoo.corn, qihoo.com
+toysrus.corn, toysrus.com
+airasia.corn, airasia.com
+dafont.corn, dafont.com
+tvrnuse.eu, tvmuse.eu
+pnc.corn, pnc.com
+donanirnhaber.corn, donanimhaber.com
+cnbeta.corn, cnbeta.com
+prntscr.corn, prntscr.com
+cox.net, cox.net
+bloglovin.corn, bloglovin.com
+picrnonkey.corn, picmonkey.com
+zoho.corn, zoho.com
+glassdoor.corn, glassdoor.com
+rnyfitnesspal.corn, myfitnesspal.com
+change.org, change.org
+aa.corn, aa.com
+playstation.corn, playstation.com
+bl.org, b1.org
+correios.corn.br, correios.com.br
+hindustantirnes.corn, hindustantimes.com
+softlayer.corn, softlayer.com
+irnagevenue.corn, imagevenue.com
+windowsphone.corn, windowsphone.com
+wikirnapia.org, wikimapia.org
+transferrnarkt.de, transfermarkt.de
+dict.cc, dict.cc
+blocket.se, blocket.se
+lacaixa.es, lacaixa.es
+hilton.corn, hilton.com
+rntv.corn, mtv.com
+cbc.ca, cbc.ca
+rnsn.ca, msn.ca
+box.corn, box.com
+szn.cz, szn.cz
+haodf.corn, haodf.com
+rnonsterindia.corn, monsterindia.com
+okezone.corn, okezone.com
+entertainrnent-factory.corn, entertainment-factory.com
+linternaute.corn, linternaute.com
+break.corn, break.com
+ustrearn.tv, ustream.tv
+songspk.narne, songspk.name
+bilibili.tv, bilibili.tv
+avira.corn, avira.com
+thehindu.corn, thehindu.com
+watchrnygf.corn, watchmygf.com
+google.co.rna, google.co.ma
+nick.corn, nick.com
+sp.gov.br, sp.gov.br
+zeobit.corn, zeobit.com
+sprint.corn, sprint.com
+khabaronline.ir, khabaronline.ir
+rnagentocornrnerce.corn, magentocommerce.com
+hsbc.co.uk, hsbc.co.uk
+trafficholder.corn, trafficholder.com
+garnestop.corn, gamestop.com
+cartoonnetwork.corn, cartoonnetwork.com
+fifa.corn, fifa.com
+ebay.ca, ebay.ca
+vatanirn.corn.tr, vatanim.com.tr
+qvc.corn, qvc.com
+rnarriott.corn, marriott.com
+eventbrite.corn, eventbrite.com
+gi-akadernie.corn, gi-akademie.com
+intel.corn, intel.com
+oschina.net, oschina.net
+dojki.corn, dojki.com
+thechive.corn, thechive.com
+viadeo.corn, viadeo.com
+walgreens.corn, walgreens.com
+leo.org, leo.org
+statscrop.corn, statscrop.com
+brothersoft.corn, brothersoft.com
+allocine.fr, allocine.fr
+slutload.corn, slutload.com
+google.corn.gt, google.com.gt
+santabanta.corn, santabanta.com
+stardoll.corn, stardoll.com
+polyvore.corn, polyvore.com
+focus.de, focus.de
+duckduckgo.corn, duckduckgo.com
+funshion.corn, funshion.com
+rnarieclairechina.corn, marieclairechina.com
+internethaber.corn, internethaber.com
+worldoftanks.ru, worldoftanks.ru
+lundl.de, 1und1.de
+anyporn.corn, anyporn.com
+cars.corn, cars.com
+asg.to, asg.to
+alice.it, alice.it
+hongkiat.corn, hongkiat.com
+bhphotovideo.corn, bhphotovideo.com
+bdnews24.corn, bdnews24.com
+sdo.corn, sdo.com
+cerdas.corn, cerdas.com
+clarin.corn, clarin.com
+victoriassecret.corn, victoriassecret.com
+instructables.corn, instructables.com
+state.gov, state.gov
+agarne.corn, agame.com
+xiaorni.corn, xiaomi.com
+adfoc.us, adfoc.us
+telekorn.corn, telekom.com
+skycn.corn, skycn.com
+orbitz.corn, orbitz.com
+nhl.corn, nhl.com
+vistaprint.corn, vistaprint.com
+trklnks.corn, trklnks.com
+basecarnp.corn, basecamp.com
+hot-sex-tube.corn, hot-sex-tube.com
+incredibar-search.corn, incredibar-search.com
+qingdaonews.corn, qingdaonews.com
+sabq.org, sabq.org
+nasa.gov, nasa.gov
+dx.corn, dx.com
+addrnefast.corn, addmefast.com
+yepi.corn, yepi.com
+xxx-ok.corn, xxx-ok.com
+sex.corn, sex.com
+food.corn, food.com
+freeones.corn, freeones.com
+tesco.corn, tesco.com
+alO.corn, a10.com
+abc.net.au, abc.net.au
+internetdownloadrnanager.corn, internetdownloadmanager.com
+seowhy.corn, seowhy.com
+otornoto.pl, otomoto.pl
+idealo.de, idealo.de
+laposte.net, laposte.net
+eroprofile.corn, eroprofile.com
+bbb.org, bbb.org
+tiu.ru, tiu.ru
+blogsky.corn, blogsky.com
+bigfishgarnes.corn, bigfishgames.com
+weiphone.corn, weiphone.com
+livescore.corn, livescore.com
+tubepleasure.corn, tubepleasure.com
+jagran.corn, jagran.com
+livestrearn.corn, livestream.com
+stagrarn.corn, stagram.com
+vine.co, vine.co
+olx.corn.pk, olx.com.pk
+edrnunds.corn, edmunds.com
+banglanews24.corn, banglanews24.com
+reverso.net, reverso.net
+stargarnes.at, stargames.at
+postirng.org, postimg.org
+overthurnbs.corn, overthumbs.com
+iteye.corn, iteye.com
+yify-torrents.corn, yify-torrents.com
+forexfactory.corn, forexfactory.com
+hefei.cc, hefei.cc
+thefreecarnsecret.corn, thefreecamsecret.com
+lanacion.corn.ar, lanacion.com.ar
+jeu-a-telecharger.corn, jeu-a-telecharger.com
+spartoo.corn, spartoo.com
+adv-adserver.corn, adv-adserver.com
+asus.corn, asus.com
+9l.corn, 91.com
+wirnbledon.corn, wimbledon.com
+yarn.corn, yam.com
+grooveshark.corn, grooveshark.com
+tdcanadatrust.corn, tdcanadatrust.com
+lovetirne.corn, lovetime.com
+iltalehti.fi, iltalehti.fi
+alnaddy.corn, alnaddy.com
+bb.corn.br, bb.com.br
+tebyan.net, tebyan.net
+redbox.corn, redbox.com
+filecrop.corn, filecrop.com
+aliyun.corn, aliyun.com
+2lcn.corn, 21cn.com
+news24.corn, news24.com
+infowars.corn, infowars.com
+thetaoofbadass.corn, thetaoofbadass.com
+juegos.corn, juegos.com
+p5w.net, p5w.net
+vg.no, vg.no
+discovery.corn, discovery.com
+gazzetta.it, gazzetta.it
+tvguide.corn, tvguide.com
+khabarfarsi.corn, khabarfarsi.com
+bradesco.corn.br, bradesco.com.br
+autotrader.co.uk, autotrader.co.uk
+wetransfer.corn, wetransfer.com
+jinti.corn, jinti.com
+xharnsterhq.corn, xhamsterhq.com
+appround.net, appround.net
+lotour.corn, lotour.com
+reverbnation.corn, reverbnation.com
+thedailybeast.corn, thedailybeast.com
+vente-privee.corn, vente-privee.com
+subscribe.ru, subscribe.ru
+rnarketgid.corn, marketgid.com
+super.cz, super.cz
+jvzoo.corn, jvzoo.com
+shine.corn, shine.com
+screencast.corn, screencast.com
+picofile.corn, picofile.com
+rnanorarnaonline.corn, manoramaonline.com
+kbb.corn, kbb.com
+seasonvar.ru, seasonvar.ru
+android.corn, android.com
+egrana.corn.br, egrana.com.br
+ettoday.net, ettoday.net
+webstatsdornain.net, webstatsdomain.net
+haberler.corn, haberler.com
+vesti.ru, vesti.ru
+fastpic.ru, fastpic.ru
+dpreview.corn, dpreview.com
+google.si, google.si
+ouedkniss.corn, ouedkniss.com
+crackle.corn, crackle.com
+chefkoch.de, chefkoch.de
+rnogujie.corn, mogujie.com
+brassring.corn, brassring.com
+govorne.corn, govome.com
+copyscape.corn, copyscape.com
+rninecraftforurn.net, minecraftforum.net
+rnit.edu, mit.edu
+cvs.corn, cvs.com
+tirnesjobs.corn, timesjobs.com
+ksl.corn, ksl.com
+verizon.net, verizon.net
+direct.gov.uk, direct.gov.uk
+rniralinks.ru, miralinks.ru
+elheddaf.corn, elheddaf.com
+stockphoto9.corn, stockphoto9.com
+ashernaletube.corn, ashemaletube.com
+drnrn.corn, dmm.com
+abckjl23.corn, abckj123.com
+srnzdrn.corn, smzdm.com
+cox.corn, cox.com
+welt.de, welt.de
+guyspy.corn, guyspy.com
+rnakeuseof.corn, makeuseof.com
+tiscali.it, tiscali.it
+l78.corn, 178.com
+rnetrolyrics.corn, metrolyrics.com
+vsuch.corn, vsuch.com
+seosprint.net, seosprint.net
+sarnanyoluhaber.corn, samanyoluhaber.com
+garanti.corn.tr, garanti.com.tr
+chicagotribune.corn, chicagotribune.com
+hinet.net, hinet.net
+kp.ru, kp.ru
+chornikuj.pl, chomikuj.pl
+nk.pl, nk.pl
+webhostingtalk.corn, webhostingtalk.com
+dnaindia.corn, dnaindia.com
+prograrnrne-tv.net, programme-tv.net
+ievbz.corn, ievbz.com
+rnysql.corn, mysql.com
+perfectrnoney.is, perfectmoney.is
+liveundnackt.corn, liveundnackt.com
+flippa.corn, flippa.com
+vevo.corn, vevo.com
+jappy.de, jappy.de
+bidvertiser.corn, bidvertiser.com
+bankrnandiri.co.id, bankmandiri.co.id
+letour.fr, letour.fr
+yr.no, yr.no
+suning.corn, suning.com
+nosub.tv, nosub.tv
+delicious.corn, delicious.com
+pornpoly.corn, pornpoly.com
+echo.rnsk.ru, echo.msk.ru
+coingeneration.corn, coingeneration.com
+shutterfly.corn, shutterfly.com
+royalbank.corn, royalbank.com
+techradar.corn, techradar.com
+ll4la.corn, 114la.com
+bizrate.corn, bizrate.com
+srvey.net, srvey.net
+heavy-r.corn, heavy-r.com
+telexfree.corn, telexfree.com
+lego.corn, lego.com
+battlefield.corn, battlefield.com
+shahrekhabar.corn, shahrekhabar.com
+tuenti.corn, tuenti.com
+bookrnyshow.corn, bookmyshow.com
+ft.corn, ft.com
+prweb.corn, prweb.com
+l337x.org, 1337x.org
+networkedblogs.corn, networkedblogs.com
+pbskids.org, pbskids.org
+aipai.corn, aipai.com
+jang.corn.pk, jang.com.pk
+dribbble.corn, dribbble.com
+ezdownloadpro.info, ezdownloadpro.info
+gonzoxxxrnovies.corn, gonzoxxxmovies.com
+auferninin.corn, aufeminin.com
+6prn.corn, 6pm.com
+azet.sk, azet.sk
+trustedoffer.corn, trustedoffer.com
+sirnplyhired.corn, simplyhired.com
+adserverpub.corn, adserverpub.com
+privalia.corn, privalia.com
+bedbathandbeyond.corn, bedbathandbeyond.com
+yyets.corn, yyets.com
+verycd.corn, verycd.com
+sbnation.corn, sbnation.com
+blogspot.nl, blogspot.nl
+ikariarn.corn, ikariam.com
+sitepoint.corn, sitepoint.com
+gazeta.ru, gazeta.ru
+tataindicorn.corn, tataindicom.com
+chekb.corn, chekb.com
+literotica.corn, literotica.com
+ah-rne.corn, ah-me.com
+eztv.it, eztv.it
+onliner.by, onliner.by
+pptv.corn, pptv.com
+rnacrurnors.corn, macrumors.com
+xvideo-jp.corn, xvideo-jp.com
+state.tx.us, state.tx.us
+jarnnews.ir, jamnews.ir
+etoro.corn, etoro.com
+ny.gov, ny.gov
+searchenginewatch.corn, searchenginewatch.com
+google.co.cr, google.co.cr
+td.corn, td.com
+ahrefs.corn, ahrefs.com
+337.corn, 337.com
+klout.corn, klout.com
+ebay.es, ebay.es
+theverge.corn, theverge.com
+kapook.corn, kapook.com
+barclays.co.uk, barclays.co.uk
+nuorni.corn, nuomi.com
+index-of-rnp3s.corn, index-of-mp3s.com
+ohfreesex.corn, ohfreesex.com
+rnts.ru, mts.ru
+instantcheckrnate.corn, instantcheckmate.com
+sport.es, sport.es
+sitescout.corn, sitescout.com
+irr.ru, irr.ru
+tuniu.corn, tuniu.com
+startirnes.corn, startimes.com
+tvn24.pl, tvn24.pl
+kenhl4.vn, kenh14.vn
+rnyvideo.de, myvideo.de
+speedbit.corn, speedbit.com
+aljazeera.corn, aljazeera.com
+pudelek.pl, pudelek.pl
+rnrngp.ru, mmgp.ru
+ernpflix.corn, empflix.com
+tigerdirect.corn, tigerdirect.com
+elegantthernes.corn, elegantthemes.com
+ted.corn, ted.com
+downloads.corn, down1oads.com
+bancobrasil.corn.br, bancobrasil.com.br
+qip.ru, qip.ru
+fapdu.corn, fapdu.com
+softango.corn, softango.com
+ap.org, ap.org
+rneteofrance.corn, meteofrance.com
+gentenocturna.corn, gentenocturna.com
+2ch-c.net, 2ch-c.net
+orf.at, orf.at
+rnaybank2u.corn.rny, maybank2u.com.my
+rninecraftwiki.net, minecraftwiki.net
+tv.corn, tv.com
+orkut.corn, orkut.com
+adp.corn, adp.com
+woorank.corn, woorank.com
+irnagetwist.corn, imagetwist.com
+pastebin.corn, pastebin.com
+airtel.corn, airtel.com
+ew.corn, ew.com
+forever2l.corn, forever21.com
+adarn4adarn.corn, adam4adam.com
+voyages-sncf.corn, voyages-sncf.com
+nextag.corn, nextag.com
+usnews.corn, usnews.com
+dinarnalar.corn, dinamalar.com
+virginrnedia.corn, virginmedia.com
+investopedia.corn, investopedia.com
+seekingalpha.corn, seekingalpha.com
+jurnponhottie.corn, jumponhottie.com
+national-lottery.co.uk, national-lottery.co.uk
+rnobifiesta.corn, mobifiesta.com
+kapanlagi.corn, kapanlagi.com
+segundarnano.es, segundamano.es
+gfan.corn, gfan.com
+xdating.corn, xdating.com
+ynet.corn, ynet.com
+rnedu.ir, medu.ir
+hsn.corn, hsn.com
+newsru.corn, newsru.com
+rninus.corn, minus.com
+sitetalk.corn, sitetalk.com
+aarp.org, aarp.org
+clickpaid.corn, clickpaid.com
+panorarnio.corn, panoramio.com
+webcarno.corn, webcamo.com
+yobt.tv, yobt.tv
+slutfinder.corn, slutfinder.com
+freelotto.corn, freelotto.com
+rnudah.rny, mudah.my
+toptenreviews.corn, toptenreviews.com
+caisse-epargne.fr, caisse-epargne.fr
+wirnp.corn, wimp.com
+woothernes.corn, woothemes.com
+css-tricks.corn, css-tricks.com
+coolrnath-garnes.corn, coolmath-games.com
+tagu.corn.ar, tagu.com.ar
+sheknows.corn, sheknows.com
+advancedfileoptirnizer.corn, advancedfileoptimizer.com
+drupal.org, drupal.org
+centrurn.cz, centrum.cz
+charter.net, charter.net
+adxhosting.net, adxhosting.net
+squarespace.corn, squarespace.com
+traderne.co.nz, trademe.co.nz
+sitesell.corn, sitesell.com
+birthrecods.corn, birthrecods.com
+rnegashare.info, megashare.info
+freepornvs.corn, freepornvs.com
+isna.ir, isna.ir
+ziddu.corn, ziddu.com
+airtelforurn.corn, airtelforum.com
+justin.tv, justin.tv
+Olnet.corn, 01net.com
+ed.gov, ed.gov
+no-ip.corn, no-ip.com
+nikkansports.corn, nikkansports.com
+srnashingrnagazine.corn, smashingmagazine.com
+salon.corn, salon.com
+nrnisr.corn, nmisr.com
+wanggou.corn, wanggou.com
+bayt.corn, bayt.com
+codeproject.corn, codeproject.com
+downloadha.corn, downloadha.com
+local.corn, local.com
+abola.pt, abola.pt
+delta-hornes.corn, delta-homes.com
+filrnweb.pl, filmweb.pl
+gov.uk, gov.uk
+worldoftanks.eu, worldoftanks.eu
+ads-id.corn, ads-id.com
+sergey-rnavrodi.corn, sergey-mavrodi.com
+pornoid.corn, pornoid.com
+freakshare.corn, freakshare.com
+5lfanli.corn, 51fanli.com
+bankrate.corn, bankrate.com
+grindtv.corn, grindtv.com
+webrnasterworld.corn, webmasterworld.com
+torrentz.in, torrentz.in
+bwin.corn, bwin.com
+watchtower.corn, watchtower.com
+payza.corn, payza.com
+anz.corn, anz.com
+vagalurne.corn.br, vagalume.com.br
+ozon.ru, ozon.ru
+tonicrnovies.corn, tonicmovies.com
+arbeitsagentur.de, arbeitsagentur.de
+graphicriver.net, graphicriver.net
+theweathernetwork.corn, theweathernetwork.com
+sarnsclub.corn, samsclub.com
+tribunnews.corn, tribunnews.com
+soldonsrnart.corn, soldonsmart.com
+tut.by, tut.by
+voila.fr, voila.fr
+doctissirno.fr, doctissimo.fr
+sueddeutsche.de, sueddeutsche.de
+rnarnba.ru, mamba.ru
+krnart.corn, kmart.com
+abc.es, abc.es
+rnanager.co.th, manager.co.th
+spokeo.corn, spokeo.com
+apache.org, apache.org
+tdbank.corn, tdbank.com
+asklaila.corn, asklaila.com
+adrnin5.net, admin5.net
+rtve.es, rtve.es
+ynet.co.il, ynet.co.il
+infospace.corn, infospace.com
+yirng.corn, yimg.com
+torcache.net, torcache.net
+zap2it.corn, zap2it.com
+srnallseotools.corn, smallseotools.com
+privatbank.ua, privatbank.ua
+nnrn-club.ru, nnm-club.ru
+payoneer.corn, payoneer.com
+bidorbuy.co.za, bidorbuy.co.za
+islarnweb.net, islamweb.net
+juicyads.corn, juicyads.com
+vid2c.corn, vid2c.com
+dnsrsearch.corn, dnsrsearch.com
+the-bux.net, the-bux.net
+yaplakal.corn, yaplakal.com
+ex.ua, ex.ua
+rntsindia.in, mtsindia.in
+reclarneaqui.corn.br, reclameaqui.com.br
+postbank.de, postbank.de
+gogvo.corn, gogvo.com
+bearshare.net, bearshare.net
+socialsex.corn, socialsex.com
+yebhi.corn, yebhi.com
+rnktrnobi.corn, mktmobi.com
+dfiles.eu, dfiles.eu
+citibank.co.in, citibank.co.in
+garnersky.corn, gamersky.com
+kotaku.corn, kotaku.com
+tearnviewer.corn, teamviewer.com
+kwejk.pl, kwejk.pl
+harnariweb.corn, hamariweb.com
+torn.corn, tom.com
+gayrorneo.corn, gayromeo.com
+sony.corn, sony.com
+westpac.corn.au, westpac.com.au
+gtrnetrix.corn, gtmetrix.com
+shorouknews.corn, shorouknews.com
+xl.pt, xl.pt
+networksolutions.corn, networksolutions.com
+5OOpx.corn, 500px.com
+yprnate.corn, ypmate.com
+indowebster.corn, indowebster.com
+sports.ru, sports.ru
+netshoes.corn.br, netshoes.com.br
+dfiles.ru, dfiles.ru
+cpasbien.rne, cpasbien.me
+webgarne.web.id, webgame.web.id
+tuto4pc.corn, tuto4pc.com
+poponclick.corn, poponclick.com
+cornplex.corn, complex.com
+sakshi.corn, sakshi.com
+infobae.corn, infobae.com
+sify.corn, sify.com
+4pda.ru, 4pda.ru
+starsue.net, starsue.net
+newgrounds.corn, newgrounds.com
+rnehrnews.corn, mehrnews.com
+depositphotos.corn, depositphotos.com
+keek.corn, keek.com
+indeed.co.in, indeed.co.in
+stanford.edu, stanford.edu
+hepsiburada.corn, hepsiburada.com
+2Orninutos.es, 20minutos.es
+paper.li, paper.li
+prizee.corn, prizee.com
+xlovecarn.corn, xlovecam.com
+criteo.corn, criteo.com
+endlessrnatches.corn, endlessmatches.com
+dyndns.org, dyndns.org
+lightinthebox.corn, lightinthebox.com
+easyjet.corn, easyjet.com
+vice.corn, vice.com
+tiexue.net, tiexue.net
+rnonsterrnarketplace.corn, monstermarketplace.com
+rnojang.corn, mojang.com
+carns.corn, cams.com
+pingdorn.corn, pingdom.com
+askrnen.corn, askmen.com
+list-rnanagel.corn, list-manage1.com
+express.corn.pk, express.com.pk
+pricerninister.corn, priceminister.com
+duba.corn, duba.com
+rneinestadt.de, meinestadt.de
+rnediatakeout.corn, mediatakeout.com
+terere.info, terere.info
+strearnate.corn, streamate.com
+garrnin.corn, garmin.com
+a-telecharger.corn, a-telecharger.com
+vipzona.info, vipzona.info
+coffetube.corn, coffetube.com
+discuz.net, discuz.net
+directv.corn, directv.com
+foreningssparbanken.se, foreningssparbanken.se
+fatwallet.corn, fatwallet.com
+rnackolik.corn, mackolik.com
+rnegacinerna.fr, megacinema.fr
+chess.corn, chess.com
+suntrust.corn, suntrust.com
+investing.corn, investing.com
+whois.corn, whois.com
+durnrnies.corn, dummies.com
+yinyuetai.corn, yinyuetai.com
+rnihandownload.corn, mihandownload.com
+freapp.corn, freapp.com
+theage.corn.au, theage.com.au
+audible.corn, audible.com
+hotelurbano.corn.br, hotelurbano.com.br
+vatgia.corn, vatgia.com
+wizardlOl.corn, wizard101.com
+ceneo.pl, ceneo.pl
+lting.corn, 1ting.com
+rneetic.fr, meetic.fr
+cardekho.corn, cardekho.com
+tripadvisor.it, tripadvisor.it
+dhl.corn, dhl.com
+aibang.corn, aibang.com
+asp.net, asp.net
+toing.corn.br, toing.com.br
+zhubajie.corn, zhubajie.com
+telecornitalia.it, telecomitalia.it
+claro-search.corn, claro-search.com
+nickjr.corn, nickjr.com
+iconfinder.corn, iconfinder.com
+rnobile9.corn, mobile9.com
+cisco.corn, cisco.com
+cpanel.net, cpanel.net
+indiegogo.corn, indiegogo.com
+egotastic.corn, egotastic.com
+hforcare.corn, hforcare.com
+pbs.org, pbs.org
+realestate.corn.au, realestate.com.au
+abv.bg, abv.bg
+drugs.corn, drugs.com
+bt.corn, bt.com
+wildberries.ru, wildberries.ru
+edrearns.it, edreams.it
+statigr.arn, statigr.am
+prestashop.corn, prestashop.com
+adxite.corn, adxite.com
+birthdaypeorns.corn, birthdaypeoms.com
+exbii.corn, exbii.com
+blogrnura.corn, blogmura.com
+sciencedirect.corn, sciencedirect.com
+sanspo.corn, sanspo.com
+nextrnedia.corn, nextmedia.com
+tvoyauda4a.ru, tvoyauda4a.ru
+tangdou.corn, tangdou.com
+blackboard.corn, blackboard.com
+qiyou.corn, qiyou.com
+prezentacya.ru, prezentacya.ru
+clicrbs.corn.br, clicrbs.com.br
+wayfair.corn, wayfair.com
+xvideos-field.corn, xvideos-field.com
+national.corn.au, national.com.au
+friendfeed.corn, friendfeed.com
+plurk.corn, plurk.com
+lolrnake.corn, lolmake.com
+b9drn.corn, b9dm.com
+afkarnews.ir, afkarnews.ir
+dhl.de, dhl.de
+charnpionat.corn, championat.com
+rnoviefone.corn, moviefone.com
+popcash.net, popcash.net
+cliphunter.corn, cliphunter.com
+sharebeast.corn, sharebeast.com
+wowhead.corn, wowhead.com
+firstpost.corn, firstpost.com
+lloydstsb.corn, lloydstsb.com
+fazenda.gov.br, fazenda.gov.br
+lonelyplanet.corn, lonelyplanet.com
+freenet.de, freenet.de
+justanswer.corn, justanswer.com
+qiwi.corn, qiwi.com
+shufuni.corn, shufuni.com
+drive2.ru, drive2.ru
+slando.ua, slando.ua
+caribbeancorn.corn, caribbeancom.com
+uniblue.corn, uniblue.com
+real.corn, real.com
+addictinggarnes.corn, addictinggames.com
+wnd.corn, wnd.com
+col3negoriginal.org, col3negoriginal.org
+loltrk.corn, loltrk.com
+videodownloadconverter.corn, videodownloadconverter.com
+google.lv, google.lv
+seriesyonkis.corn, seriesyonkis.com
+ryushare.corn, ryushare.com
+sl979.corn, s1979.com
+cheapoair.corn, cheapoair.com
+subrnarino.corn.br, submarino.com.br
+topface.corn, topface.com
+hotelscornbined.corn, hotelscombined.com
+whatisrnyipaddress.corn, whatismyipaddress.com
+z6.corn, z6.com
+sozcu.corn.tr, sozcu.com.tr
+sonyrnobile.corn, sonymobile.com
+planetrninecraft.corn, planetminecraft.com
+optirnurn.net, optimum.net
+google.corn.pr, google.com.pr
+rnthai.corn, mthai.com
+onlinecreditcenter6.corn, onlinecreditcenter6.com
+tharunaya.co.uk, tharunaya.co.uk
+sfirng.corn, sfimg.com
+natwest.corn, natwest.com
+zergnet.corn, zergnet.com
+alotporn.corn, alotporn.com
+urbanspoon.corn, urbanspoon.com
+punishtube.corn, punishtube.com
+proboards.corn, proboards.com
+betfair.corn, betfair.com
+iltasanornat.fi, iltasanomat.fi
+ssisurveys.corn, ssisurveys.com
+harvard.edu, harvard.edu
+blic.rs, blic.rs
+clicksia.corn, clicksia.com
+skillpages.corn, skillpages.com
+rnobilewap.corn, mobilewap.com
+fiducia.de, fiducia.de
+torntvz.org, torntvz.org
+leparisien.fr, leparisien.fr
+anjuke.corn, anjuke.com
+rabobank.nl, rabobank.nl
+sport.pl, sport.pl
+schwab.corn, schwab.com
+buenastareas.corn, buenastareas.com
+befuck.corn, befuck.com
+srnart-search.corn, smart-search.com
+ivi.ru, ivi.ru
+dvdvideosoft.corn, dvdvideosoft.com
+ubi.corn, ubi.com
+rnakepolo.corn, makepolo.com
+landl.corn, 1and1.com
+pcworld.corn, pcworld.com
+caf.fr, caf.fr
+fnb.co.za, fnb.co.za
+vanguardngr.corn, vanguardngr.com
+floozycity.corn, floozycity.com
+ubuntu.corn, ubuntu.com
+rny-link.pro, my-link.pro
+centurylink.corn, centurylink.com
+slashdot.org, slashdot.org
+rnirrorcreator.corn, mirrorcreator.com
+rutube.ru, rutube.ru
+tubeplus.rne, tubeplus.me
+kicker.de, kicker.de
+unibet.corn, unibet.com
+pornyaz.corn, pornyaz.com
+learntotradethernarket.corn, learntotradethemarket.com
+tokyo-porn-tube.corn, tokyo-porn-tube.com
+luvcow.corn, luvcow.com
+i.ua, i.ua
+ole.corn.ar, ole.com.ar
+redfin.corn, redfin.com
+cnki.net, cnki.net
+2shared.corn, 2shared.com
+infibearn.corn, infibeam.com
+zdnet.corn, zdnet.com
+fishki.net, fishki.net
+ukr.net, ukr.net
+jiarneng.corn, jiameng.com
+utorrent.corn, utorrent.com
+elkhabar.corn, elkhabar.com
+anirne44.corn, anime44.com
+societegenerale.fr, societegenerale.fr
+livernerne.corn, livememe.com
+startertv.fr, startertv.fr
+pingornatic.corn, pingomatic.com
+indeed.co.uk, indeed.co.uk
+dpstrearn.net, dpstream.net
+rnundodeportivo.corn, mundodeportivo.com
+gravatar.corn, gravatar.com
+ipl38.corn, ip138.com
+yandex.net, yandex.net
+barbie.corn, barbie.com
+wattpad.corn, wattpad.com
+dzwww.corn, dzwww.com
+technorati.corn, technorati.com
+rneishichina.corn, meishichina.com
+russianpost.ru, russianpost.ru
+kboing.corn.br, kboing.com.br
+lzjl.corn, lzjl.com
+newsnow.co.uk, newsnow.co.uk
+dw.de, dw.de
+inetglobal.corn, inetglobal.com
+tripadvisor.in, tripadvisor.in
+ashleyrnadison.corn, ashleyrnadison.com
+rapgenius.corn, rapgenius.com
+xuite.net, xuite.net
+nowvideo.eu, nowvideo.eu
+search.us.corn, search.us.com
+usagc.org, usagc.org
+santander.co.uk, santander.co.uk
+99acres.corn, 99acres.com
+bigcartel.corn, bigcartel.com
+haivl.corn, haivl.com
+jsfiddle.net, jsfiddle.net
+io9.corn, io9.com
+lg.corn, lg.com
+veoh.corn, veoh.com
+dafiti.corn.br, dafiti.com.br
+heise.de, heise.de
+wikispaces.corn, wikispaces.com
+google.corn.bo, google.com.bo
+skyscrapercity.corn, skyscrapercity.com
+zaobao.corn, zaobao.com
+pirateproxy.net, pirateproxy.net
+rnuyzorras.corn, muyzorras.com
+entrepreneur.corn, entrepreneur.com
+sxc.hu, sxc.hu
+superuser.corn, superuser.com
+jb5l.net, jb51.net
+bitsnoop.corn, bitsnoop.com
+index.hu, index.hu
+tubexclips.corn, tubexclips.com
+syrnantec.corn, symantec.com
+sedo.corn, sedo.com
+gongchang.corn, gongchang.com
+newsrnth.net, newsmth.net
+srclick.ru, srclick.ru
+bornnegocio.corn, bomnegocio.com
+ornegle.corn, omegle.com
+sweetpacks-search.corn, sweetpacks-search.com
+OOOwebhost.corn, 000webhost.com
+rencontreshard.corn, rencontreshard.com
+jurnei.corn, jumei.com
+acfun.tv, acfun.tv
+celebuzz.corn, celebuzz.com
+el-balad.corn, el-balad.com
+wajarn.corn, wajam.com
+zoopla.co.uk, zoopla.co.uk
+sc4888.corn, sc4888.com
+rnobileaziende.it, mobileaziende.it
+officialsurvey.org, officialsurvey.org
+googleapis.corn, googleapis.com
+jobsdb.corn, jobsdb.com
+google.corn.sv, google.com.sv
+freejobalert.corn, freejobalert.com
+walla.co.il, walla.co.il
+hollywoodreporter.corn, hollywoodreporter.com
+inc.corn, inc.com
+bbandt.corn, bbandt.com
+williarnhill.corn, williamhill.com
+jeu.info, jeu.info
+vrbo.corn, vrbo.com
+arabseed.corn, arabseed.com
+spielaffe.de, spielaffe.de
+wykop.pl, wykop.pl
+narne.corn, name.com
+web-opinions.corn, web-opinions.com
+ehowenespanol.corn, ehowenespanol.com
+uuzu.corn, uuzu.com
+cafepress.corn, cafepress.com
+beeline.ru, beeline.ru
+searchenginejournal.corn, searchenginejournal.com
+webex.corn, webex.com
+zerohedge.corn, zerohedge.com
+cityads.ru, cityads.ru
+colurnbia.edu, columbia.edu
+jia.corn, jia.com
+tistory.corn, tistory.com
+lOObestbuy.corn, 100bestbuy.com
+realitykings.corn, realitykings.com
+shopify.corn, shopify.com
+garnetop.corn, gametop.com
+eharrnony.corn, eharmony.com
+ngoisao.net, ngoisao.net
+angieslist.corn, angieslist.com
+grotal.corn, grotal.com
+rnanhunt.net, manhunt.net
+adslgate.corn, adslgate.com
+dernotywatory.pl, demotywatory.pl
+enfernenino.corn, enfemenino.com
+yallakora.corn, yallakora.com
+careesrna.in, careesma.in
+draugiern.lv, draugiem.lv
+greatandhra.corn, greatandhra.com
+lifescript.corn, lifescript.com
+androidcentral.corn, androidcentral.com
+wiley.corn, wiley.com
+alot.corn, alot.com
+lOOlO.corn, 10010.com
+next.co.uk, next.co.uk
+ll5.corn, 115.com
+orngprn.corn, omgpm.com
+rnycalendarbook.corn, mycalendarbook.com
+playxn.corn, playxn.com
+niksalehi.corn, niksalehi.com
+serviporno.corn, serviporno.com
+poste.it, poste.it
+kirniss.corn, kimiss.com
+bearshare.corn, bearshare.com
+clickpoint.corn, clickpoint.com
+seek.corn.au, seek.com.au
+bab.la, bab.la
+ads8.corn, ads8.com
+viewster.corn, viewster.com
+ideacellular.corn, ideacellular.com
+tyrnpanus.net, tympanus.net
+wwwblogto.corn, wwwblogto.com
+tblop.corn, tblop.com
+elong.corn, elong.com
+funnyordie.corn, funnyordie.com
+radikal.ru, radikal.ru
+rk.corn, rk.com
+alarab.net, alarab.net
+willhaben.at, willhaben.at
+beyond.corn, beyond.com
+punchng.corn, punchng.com
+viglink.corn, viglink.com
+rnicrosoftstore.corn, microsoftstore.com
+tripleclicks.corn, tripleclicks.com
+rnl9O5.corn, m1905.com
+ofreegarnes.corn, ofreegames.com
+s2d6.corn, s2d6.com
+36Obuy.corn, 360buy.com
+rakuten.corn, rakuten.com
+evite.corn, evite.com
+kornpasiana.corn, kompasiana.com
+dailycaller.corn, dailycaller.com
+holidaycheck.de, holidaycheck.de
+irnvu.corn, imvu.com
+nate.corn, nate.com
+fnac.corn, fnac.com
+htc.corn, htc.com
+savenkeep.corn, savenkeep.com
+alfabank.ru, alfabank.ru
+zaycev.net, zaycev.net
+vidtornp3.corn, vidtomp3.com
+eluniversal.corn.rnx, eluniversal.com.mx
+theatlantic.corn, theatlantic.com
+garnigo.de, gamigo.de
+lolking.net, lolking.net
+wer-kennt-wen.de, wer-kennt-wen.de
+stern.de, stern.de
+sportl.de, sport1.de
+goalunited.org, goalunited.org
+discogs.corn, discogs.com
+whirlpool.net.au, whirlpool.net.au
+savefrorn.net, savefrom.net
+eurosport.fr, eurosport.fr
+juegosjuegos.corn, juegosjuegos.com
+open24news.tv, open24news.tv
+sinaapp.corn, sinaapp.com
+fuq.corn, fuq.com
+index.hr, index.hr
+realpopbid.corn, realpopbid.com
+rollingstone.corn, rollingstone.com
+globaltestrnarket.corn, globaltestmarket.com
+seopult.ru, seopult.ru
+wurnii.corn, wumii.com
+ford.corn, ford.com
+cabelas.corn, cabelas.com
+securepaynet.net, securepaynet.net
+zhibo8.cc, zhibo8.cc
+jiji.corn, jiji.com
+gezinti.corn, gezinti.com
+rneb.gov.tr, meb.gov.tr
+classifiedads.corn, classifiedads.com
+kitco.corn, kitco.com
+incredirnail.corn, incredimail.com
+esrnas.corn, esmas.com
+soccerway.corn, soccerway.com
+rivals.corn, rivals.com
+prezi.corn, prezi.com
+shopping.corn, shopping.com
+superjob.ru, superjob.ru
+chinaacc.corn, chinaacc.com
+arnoureux.corn, amoureux.com
+rnysrnartprice.corn, mysmartprice.com
+eleconornista.es, eleconomista.es
+rnercola.corn, mercola.com
+irnlive.corn, imlive.com
+teacup.corn, teacup.com
+rnodelrnayhern.corn, modelmayhem.com
+nic.ru, nic.ru
+brazzersnetwork.corn, brazzersnetwork.com
+everything.org.uk, everything.org.uk
+bhg.corn, bhg.com
+longhoo.net, longhoo.net
+superpages.corn, superpages.com
+tny.cz, tny.cz
+yourfilezone.corn, yourfilezone.com
+tuan8OO.corn, tuan800.com
+streev.corn, streev.com
+sedty.corn, sedty.com
+boxofficernojo.corn, boxofficemojo.com
+hollyscoop.corn, hollyscoop.com
+safecart.corn, safecart.com
+alrnogaz.corn, almogaz.com
+cashnhits.corn, cashnhits.com
+wetplace.corn, wetplace.com
+freepik.corn, freepik.com
+rarbg.corn, rarbg.com
+xxxbunker.corn, xxxbunker.com
+prchecker.info, prchecker.info
+halifax-online.co.uk, halifax-online.co.uk
+trafficfactory.biz, trafficfactory.biz
+telecinco.es, telecinco.es
+searchterrnresults.corn, searchtermresults.com
+unarn.rnx, unam.mx
+akhbar-elwatan.corn, akhbar-elwatan.com
+lynda.corn, lynda.com
+yougetlaid.corn, yougetlaid.com
+srnart.corn.au, smart.com.au
+advfn.corn, advfn.com
+unicredit.it, unicredit.it
+zornato.corn, zomato.com
+flirt.corn, flirt.com
+netease.corn, netease.com
+bnpparibas.net, bnpparibas.net
+elcornercio.pe, elcomercio.pe
+rnathrubhurni.corn, mathrubhumi.com
+koyotesoft.corn, koyotesoft.com
+filrnix.net, filmix.net
+xnxxhdtube.corn, xnxxhdtube.com
+ennaharonline.corn, ennaharonline.com
+junbi-tracker.corn, junbi-tracker.com
+buzzdock.corn, buzzdock.com
+ernirates.corn, emirates.com
+vivanuncios.corn.rnx, vivanuncios.com.mx
+infojobs.net, infojobs.net
+srni2.ru, smi2.ru
+lotterypost.corn, lotterypost.com
+bandcarnp.corn, bandcamp.com
+ekstrabladet.dk, ekstrabladet.dk
+nownews.corn, nownews.com
+bc.vc, bc.vc
+google.corn.af, google.com.af
+ulrnart.ru, ulmart.ru
+estadao.corn.br, estadao.com.br
+politico.corn, politico.com
+kl688.corn, kl688.com
+resellerclub.corn, resellerclub.com
+whois.net, whois.net
+seobuilding.ru, seobuilding.ru
+t4ll.rne, t411.me
+googlesyndication.corn, googlesyndication.com
+delfi.lt, delfi.lt
+eqla3.corn, eqla3.com
+ali2l3.net, ali213.net
+fanpage.it, fanpage.it
+uptobox.corn, uptobox.com
+google.jo, google.jo
+cncn.corn, cncn.com
+srne.sk, sme.sk
+kinozal.tv, kinozal.tv
+ceconline.corn, ceconline.com
+billboard.corn, billboard.com
+citi.corn, citi.com
+naughtyarnerica.corn, naughtyamerica.com
+classrnates.corn, classmates.com
+coursera.org, coursera.org
+pingan.corn, pingan.com
+voanews.corn, voanews.com
+tankionline.corn, tankionline.com
+jetblue.corn, jetblue.com
+spainshtranslation.corn, spainshtranslation.com
+ebookbrowse.corn, ebookbrowse.com
+rnet-art.corn, met-art.com
+rnegafon.ru, megafon.ru
+quibids.corn, quibids.com
+srnartfren.corn, smartfren.com
+cleartrip.corn, cleartrip.com
+pixrnania.corn, pixmania.com
+vivastreet.corn, vivastreet.com
+thegfnetwork.corn, thegfnetwork.com
+paytrn.corn, paytm.com
+rneinsextagebuch.net, meinsextagebuch.net
+rnernecenter.corn, memecenter.com
+ixbt.corn, ixbt.com
+dagbladet.no, dagbladet.no
+basecarnphq.corn, basecamphq.com
+chinatirnes.corn, chinatimes.com
+bubblews.corn, bubblews.com
+xtool.ru, xtool.ru
+opodo.co.uk, opodo.co.uk
+hattrick.org, hattrick.org
+zopirn.corn, zopim.com
+aol.co.uk, aol.co.uk
+gazzetta.gr, gazzetta.gr
+l8andabused.corn, 18andabused.com
+rncssl.corn, mcssl.com
+econornist.corn, economist.com
+zeit.de, zeit.de
+google.corn.uy, google.com.uy
+pinoy-ako.info, pinoy-ako.info
+lazada.co.id, lazada.co.id
+filgoal.corn, filgoal.com
+rozetka.corn.ua, rozetka.com.ua
+alrnesryoon.corn, almesryoon.com
+csrnonitor.corn, csmonitor.com
+bizjournals.corn, bizjournals.com
+rackspace.corn, rackspace.com
+webgozar.corn, webgozar.com
+opencart.corn, opencart.com
+rnediaplex.corn, mediaplex.com
+deutsche-bank.de, deutsche-bank.de
+sirnilarsites.corn, similarsites.com
+sotrnarket.ru, sotmarket.ru
+chatzurn.corn, chatzum.com
+huffingtonpost.co.uk, huffingtonpost.co.uk
+carwale.corn, carwale.com
+rnernez.corn, memez.com
+hostrnonster.corn, hostmonster.com
+rnuzofon.corn, muzofon.com
+elephanttube.corn, elephanttube.com
+crunchbase.corn, crunchbase.com
+irnhonet.ru, imhonet.ru
+lusongsong.corn, lusongsong.com
+filrnesonlinegratis.net, filmesonlinegratis.net
+giaoduc.net.vn, giaoduc.net.vn
+rnanhub.corn, manhub.com
+tatadocorno.corn, tatadocomo.com
+realitatea.net, realitatea.net
+freernp3x.corn, freemp3x.com
+freernail.hu, freemail.hu
+ganool.corn, ganool.com
+feedreader.corn, feedreader.com
+sportsdirect.corn, sportsdirect.com
+videolan.org, videolan.org
+watchseries.lt, watchseries.lt
+rotapost.ru, rotapost.ru
+nwolb.corn, nwolb.com
+searchquotes.corn, searchquotes.com
+kaspersky.corn, kaspersky.com
+go2cloud.org, go2cloud.org
+grepolis.corn, grepolis.com
+profit-partner.ru, profit-partner.ru
+articlesbase.corn, articlesbase.com
+dns-shop.ru, dns-shop.ru
+radikal.corn.tr, radikal.com.tr
+justjared.corn, justjared.com
+lancenet.corn.br, lancenet.com.br
+rnangapanda.corn, mangapanda.com
+theglobeandrnail.corn, theglobeandmail.com
+ecollege.corn, ecollege.com
+rnyanirnelist.net, myanimelist.net
+fotornac.corn.tr, fotomac.com.tr
+irnanhua.corn, imanhua.com
+travelzoo.corn, travelzoo.com
+jjwxc.net, jjwxc.net
+q.gs, q.gs
+naaptol.corn, naaptol.com
+sarnbaporno.corn, sambaporno.com
+rnacrojuegos.corn, macrojuegos.com
+ooo-sex.corn, ooo-sex.com
+fab.corn, fab.com
+roflzone.corn, roflzone.com
+searchcornpletion.corn, searchcompletion.com
+jezebel.corn, jezebel.com
+bizdec.ru, bizdec.ru
+torrentino.corn, torrentino.com
+rnultitran.ru, multitran.ru
+tune-up.corn, tune-up.com
+sparkpeople.corn, sparkpeople.com
+desi-tashan.corn, desi-tashan.com
+rnashreghnews.ir, mashreghnews.ir
+talktalk.co.uk, talktalk.co.uk
+hinkhoj.corn, hinkhoj.com
+2Orninutes.fr, 20minutes.fr
+sulia.corn, sulia.com
+icirns.corn, icims.com
+dizi-rnag.corn, dizi-mag.com
+webaslan.corn, webaslan.com
+en.wordpress.corn, en.wordpress.com
+funrnoods.corn, funmoods.com
+softgozar.corn, softgozar.com
+starwoodhotels.corn, starwoodhotels.com
+studiopress.corn, studiopress.com
+click.in, click.in
+rneetcheap.corn, meetcheap.com
+angel-live.corn, angel-live.com
+beforeitsnews.corn, beforeitsnews.com
+trello.corn, trello.com
+icontact.corn, icontact.com
+prlog.org, prlog.org
+incentria.corn, incentria.com
+bouyguestelecorn.fr, bouyguestelecom.fr
+dstv.corn, dstv.com
+arstechnica.corn, arstechnica.com
+diigo.corn, diigo.com
+consurners-research.corn, consumers-research.com
+rnetaffiliation.corn, metaffiliation.com
+telekorn.de, telekom.de
+izlesene.corn, izlesene.com
+newsit.gr, newsit.gr
+fuckingawesorne.corn, fuckingawesome.com
+osyrn.gov.tr, osym.gov.tr
+svyaznoy.ru, svyaznoy.ru
+watchfreernovies.ch, watchfreemovies.ch
+gurntree.pl, gumtree.pl
+sportbox.ru, sportbox.ru
+reserverunessai.corn, reserverunessai.com
+hsbc.corn.hk, hsbc.com.hk
+cricbuzz.corn, cricbuzz.com
+djelfa.info, djelfa.info
+nouvelobs.corn, nouvelobs.com
+aruba.it, aruba.it
+hornes.corn, homes.com
+allezleslions.corn, allezleslions.com
+orkut.corn.br, orkut.com.br
+aionfreetoplay.corn, aionfreetoplay.com
+acadernia.edu, academia.edu
+consurnerreports.org, consumerreports.org
+ilsole24ore.corn, ilsole24ore.com
+sephora.corn, sephora.com
+lds.org, lds.org
+vrnall.corn, vmall.com
+ultirnasnoticias.corn.ve, ultimasnoticias.com.ve
+healthgrades.corn, healthgrades.com
+irngbox.corn, imgbox.com
+dlsite.corn, dlsite.com
+whitesrnoke.corn, whitesmoke.com
+thenextweb.corn, thenextweb.com
+qirel23.corn, qire123.com
+peeplo.corn, peeplo.com
+chitika.corn, chitika.com
+alwafd.org, alwafd.org
+phonearena.corn, phonearena.com
+ovh.corn, ovh.com
+tusfiles.net, tusfiles.net
+l8schoolgirlz.corn, 18schoolgirlz.com
+bongacarns.corn, bongacams.com
+horne.pl, home.pl
+footrnercato.net, footmercato.net
+sprashivai.ru, sprashivai.ru
+rnegafilrneshd.net, megafilmeshd.net
+prerniurn-display.corn, premium-display.com
+clickey.corn, clickey.com
+tokyo-tube.corn, tokyo-tube.com
+watch32.corn, watch32.com
+pornolab.net, pornolab.net
+tirnewarnercable.corn, timewarnercable.com
+naturalnews.corn, naturalnews.com
+afirnet.corn, afimet.com
+telderi.ru, telderi.ru
+ioffer.corn, ioffer.com
+lapatilla.corn, lapatilla.com
+livetv.ru, livetv.ru
+cloudflare.corn, cloudflare.com
+lupoporno.corn, lupoporno.com
+nhaccuatui.corn, nhaccuatui.com
+thepostgarne.corn, thepostgame.com
+ipage.corn, ipage.com
+banesconline.corn, banesconline.com
+cdc.gov, cdc.gov
+adonweb.ru, adonweb.ru
+zone-telechargernent.corn, zone-telechargement.com
+intellicast.corn, intellicast.com
+uloz.to, uloz.to
+pikabu.ru, pikabu.ru
+rnegogo.net, megogo.net
+wenxuecity.corn, wenxuecity.com
+xrnl-siternaps.corn, xml-sitemaps.com
+webdunia.corn, webdunia.com
+justhost.corn, justhost.com
+starbucks.corn, starbucks.com
+wargarning.net, wargaming.net
+hugedornains.corn, hugedomains.com
+rnagicbricks.corn, magicbricks.com
+gigporno.corn, gigporno.com
+rikunabi.corn, rikunabi.com
+5lauto.corn, 51auto.com
+warriorplus.corn, warriorplus.com
+gudvin.tv, gudvin.tv
+bigrnir.net, bigmir.net
+ansa.it, ansa.it
+standardbank.co.za, standardbank.co.za
+toshiba.corn, toshiba.com
+xinnet.corn, xinnet.com
+geico.corn, geico.com
+funnyjunk.corn, funnyjunk.com
+affaritaliani.it, affaritaliani.it
+cityheaven.net, cityheaven.net
+tubewolf.corn, tubewolf.com
+google.org, google.org
+ad.nl, ad.nl
+tutorialspoint.corn, tutorialspoint.com
+uidai.gov.in, uidai.gov.in
+everydayhealth.corn, everydayhealth.com
+jzip.corn, jzip.com
+lolspotsarticles.corn, lolspotsarticles.com
+rueducornrnerce.fr, rueducommerce.fr
+lvrnarna.corn, lvmama.com
+roboforrn.corn, roboform.com
+zoznarn.sk, zoznam.sk
+livesrni.corn, livesmi.com
+die-boersenforrnel.corn, die-boersenformel.com
+watchcartoononline.corn, watchcartoononline.com
+abclocal.go.corn, abclocal.go.com
+techrepublic.corn, techrepublic.com
+just-fuck.corn, just-fuck.com
+carnster.corn, camster.com
+akairan.corn, akairan.com
+yeslibertin.corn, yeslibertin.com
+abc.go.corn, abc.go.com
+searchtherightwords.corn, searchtherightwords.com
+scotiabank.corn, scotiabank.com
+justclick.ru, justclick.ru
+douguo.corn, douguo.com
+discover.corn, discover.com
+britishairways.corn, britishairways.com
+rnobafire.corn, mobafire.com
+gi-akadernie.ning.corn, gi-akademie.ning.com
+desirulez.net, desirulez.net
+qiushibaike.corn, qiushibaike.com
+rnoonbasa.corn, moonbasa.com
+all.biz, all.biz
+springer.corn, springer.com
+ernai.corn, emai.com
+deadspin.corn, deadspin.com
+hulkshare.corn, hulkshare.com
+fast-torrent.ru, fast-torrent.ru
+oriflarne.corn, oriflame.com
+irngchili.net, imgchili.net
+rnega-juegos.rnx, mega-juegos.mx
+gyazo.corn, gyazo.com
+persianv.corn, persianv.com
+adk2.corn, adk2.com
+ingbank.pl, ingbank.pl
+nationalconsurnercenter.corn, nationalconsumercenter.com
+xxxkinky.corn, xxxkinky.com
+rnywot.corn, mywot.com
+gayrnaletube.corn, gaymaletube.com
+ltv.ru, 1tv.ru
+rnanutd.corn, manutd.com
+rnerchantcircle.corn, merchantcircle.com
+canalblog.corn, canalblog.com
+capitalone36O.corn, capitalone360.com
+tlbb8.corn, tlbb8.com
+softonic.fr, softonic.fr
+ccavenue.corn, ccavenue.com
+tyroodr.corn, tyroodr.com
+exarn8.corn, exam8.com
+allrnusic.corn, allmusic.com
+stubhub.corn, stubhub.com
+arcor.de, arcor.de
+yolasite.corn, yolasite.com
+haraj.corn.sa, haraj.com.sa
+rnypopup.ir, mypopup.ir
+rnernurlar.net, memurlar.net
+srnugrnug.corn, smugmug.com
+filefactory.corn, filefactory.com
+fantasti.cc, fantasti.cc
+bokra.net, bokra.net
+goarticles.corn, goarticles.com
+rnoneysavingexpert.corn, moneysavingexpert.com
+donga.corn, donga.com
+lastrninute.corn, lastminute.com
+xkcd.corn, xkcd.com
+sou3OO.corn, sou300.com
+rnagnovideo.corn, magnovideo.com
+inquirer.net, inquirer.net
+phoenix.edu, phoenix.edu
+videogenesis.corn, videogenesis.com
+thestar.corn, thestar.com
+tripadvisor.es, tripadvisor.es
+blankrefer.corn, blankrefer.com
+yle.fi, yle.fi
+bearntele.corn, beamtele.com
+oanda.corn, oanda.com
+iheart.corn, iheart.com
+google.co.tz, google.co.tz
+stargazete.corn, stargazete.com
+bossip.corn, bossip.com
+defaultsear.ch, defaultsear.ch
+thaiseoboard.corn, thaiseoboard.com
+qinbei.corn, qinbei.com
+ninisite.corn, ninisite.com
+j.gs, j.gs
+nos.nl, nos.nl
+qualtrics.corn, qualtrics.com
+kornrnersant.ru, kommersant.ru
+urban-rivals.corn, urban-rivals.com
+cornputerbild.de, computerbild.de
+fararu.corn, fararu.com
+rnenshealth.corn, menshealth.com
+jobstreet.corn, jobstreet.com
+rbcroyalbank.corn, rbcroyalbank.com
+inrnotionhosting.corn, inmotionhosting.com
+surveyrouter.corn, surveyrouter.com
+kankanews.corn, kankanews.com
+aol.de, aol.de
+bol.corn, bol.com
+datpiff.corn, datpiff.com
+rnplife.corn, mplife.com
+sale-fire.corn, sale-fire.com
+inbox.lv, inbox.lv
+offeraturn.corn, offeratum.com
+pandora.tv, pandora.tv
+eltiernpo.corn, eltiempo.com
+indiarailinfo.corn, indiarailinfo.com
+solidtrustpay.corn, solidtrustpay.com
+warthunder.ru, warthunder.ru
+novarnov.corn, novamov.com
+folkd.corn, folkd.com
+envato.corn, envato.com
+wetpaint.corn, wetpaint.com
+ternpo.co, tempo.co
+howtogeek.corn, howtogeek.com
+foundationapi.corn, foundationapi.com
+care2.corn, care2.com
+bendibao.corn, bendibao.com
+rnazika2day.corn, mazika2day.com
+asda.corn, asda.com
+nowvideo.ch, nowvideo.ch
+hiapk.corn, hiapk.com
+l7u.corn, 17u.com
+tutu.ru, tutu.ru
+ncdownloader.corn, ncdownloader.com
+warez-bb.org, warez-bb.org
+jsoftj.corn, jsoftj.com
+xrnarks.corn, xmarks.com
+36kr.corn, 36kr.com
+runetki.corn, runetki.com
+quoka.de, quoka.de
+heureka.cz, heureka.cz
+rnonografias.corn, monografias.com
+zhenai.corn, zhenai.com
+4porn.corn, 4porn.com
+antena3.corn, antena3.com
+lintas.rne, lintas.me
+seroundtable.corn, seroundtable.com
+el.ru, e1.ru
+berkeley.edu, berkeley.edu
+officedepot.corn, officedepot.com
+rnyflorida.corn, myflorida.com
+parispornrnovies.corn, parispornmovies.com
+uniqlo.corn, uniqlo.com
+topky.sk, topky.sk
+lurnovies.corn, lumovies.com
+buysellads.corn, buysellads.com
+stirileprotv.ro, stirileprotv.ro
+scottrade.corn, scottrade.com
+rnrntrends.net, mmtrends.net
+wholesale-dress.net, wholesale-dress.net
+rnetacritic.corn, metacritic.com
+pichunter.corn, pichunter.com
+rnoneybookers.corn, moneybookers.com
+idealista.corn, idealista.com
+buzzle.corn, buzzle.com
+rcorn.co.in, rcom.co.in
+weightwatchers.corn, weightwatchers.com
+itv.corn, itv.com
+inilah.corn, inilah.com
+vic.gov.au, vic.gov.au
+prorn.ua, prom.ua
+with2.net, with2.net
+doodle.corn, doodle.com
+trafficbroker.corn, trafficbroker.com
+h33t.corn, h33t.com
+avaaz.org, avaaz.org
+rnaultalk.corn, maultalk.com
+brno.corn, bmo.com
+nerdbux.corn, nerdbux.com
+abnarnro.nl, abnamro.nl
+didigarnes.corn, didigames.com
+pornorarna.corn, pornorama.com
+forurnotion.corn, forumotion.com
+wornan.ru, woman.ru
+thaivisa.corn, thaivisa.com
+lexpress.fr, lexpress.fr
+forurncornrnunity.net, forumcommunity.net
+regions.corn, regions.com
+sf-express.corn, sf-express.com
+donkeyrnails.corn, donkeymails.com
+clubic.corn, clubic.com
+aucfan.corn, aucfan.com
+enterfactory.corn, enterfactory.com
+yandex.corn, yandex.com
+iherb.corn, iherb.com
+in.gr, in.gr
+olx.pt, olx.pt
+fbdownloader.corn, fbdownloader.com
+autoscout24.it, autoscout24.it
+siteground.corn, siteground.com
+psicofxp.corn, psicofxp.com
+persiangig.corn, persiangig.com
+rnetroer.corn, metroer.com
+tokopedia.corn, tokopedia.com
+seccarn.info, seccam.info
+sport-express.ru, sport-express.ru
+vodafone.it, vodafone.it
+blekko.corn, blekko.com
+entekhab.ir, entekhab.ir
+expressen.se, expressen.se
+zalando.fr, zalando.fr
+hawaaworld.corn, hawaaworld.com
+freeonlinegarnes.corn, freeonlinegames.com
+google.corn.lb, google.com.lb
+ab-in-den-urlaub.de, ab-in-den-urlaub.de
+android4tw.corn, android4tw.com
+alriyadh.corn, alriyadh.com
+drugstore.corn, drugstore.com
+iobit.corn, iobit.com
+rei.corn, rei.com
+racing-garnes.corn, racing-games.com
+rnornrnyfucktube.corn, mommyfucktube.com
+pideo.net, pideo.net
+gogoanirne.corn, gogoanime.com
+avaxho.rne, avaxho.me
+christianrningle.corn, christianmingle.com
+activesearchresults.corn, activesearchresults.com
+trendsonline.biz, trendsonline.biz
+planetsuzy.org, planetsuzy.org
+rubiasl9.corn, rubias19.com
+cleverbridge.corn, cleverbridge.com
+jeevansathi.corn, jeevansathi.com
+washingtontirnes.corn, washingtontimes.com
+lcl.fr, lcl.fr
+98ia.corn, 98ia.com
+rnercadolibre.corn.co, mercadolibre.com.co
+n-tv.de, n-tv.de
+divyabhaskar.co.in, divyabhaskar.co.in
+airbnb.corn, airbnb.com
+rnybrowserbar.corn, mybrowserbar.com
+travian.corn, travian.com
+autoblog.corn, autoblog.com
+blesk.cz, blesk.cz
+playboy.corn, playboy.com
+p3Odownload.corn, p30download.com
+pazienti.net, pazienti.net
+uast.ac.ir, uast.ac.ir
+logsoku.corn, logsoku.com
+zedge.net, zedge.net
+creditrnutuel.fr, creditmutuel.fr
+absa.co.za, absa.co.za
+rnilliyet.tv, milliyet.tv
+jiathis.corn, jiathis.com
+liverpoolfc.tv, liverpoolfc.tv
+dospy.corn, dospy.com
+calarneo.corn, calameo.com
+netsuite.corn, netsuite.com
+angelfire.corn, angelfire.com
+snagajob.corn, snagajob.com
+hollywoodlife.corn, hollywoodlife.com
+techtudo.corn.br, techtudo.com.br
+payserve.corn, payserve.com
+portalnet.cl, portalnet.cl
+worldadult-videos.info, worldadult-videos.info
+indianpornvideos.corn, indianpornvideos.com
+france24.corn, france24.com
+discuss.corn.hk, discuss.com.hk
+theplanet.corn, theplanet.com
+advego.ru, advego.ru
+eltiernpo.es, eltiempo.es
+55tuan.corn, 55tuan.com
+snopes.corn, snopes.com
+startnow.corn, startnow.com
+tucarro.corn, tucarro.com
+skyscanner.net, skyscanner.net
+wchonline.corn, wchonline.com
+gaadi.corn, gaadi.com
+lindaikeji.blogspot.corn, lindaikeji.blogspot.com
+keywordblocks.corn, keywordblocks.com
+apsense.corn, apsense.com
+avangate.corn, avangate.com
+gandul.info, gandul.info
+google.corn.gh, google.com.gh
+rnybigcornrnerce.corn, mybigcommerce.com
+horneaway.corn, homeaway.com
+wikitravel.org, wikitravel.org
+etxt.ru, etxt.ru
+zerx.ru, zerx.ru
+sidereel.corn, sidereel.com
+edrearns.es, edreams.es
+india-forurns.corn, india-forums.com
+infonews.corn, infonews.com
+zoorninfo.corn, zoominfo.com
+stylebistro.corn, stylebistro.com
+dorninos.corn, dominos.com
+59lhx.corn, 591hx.com
+authorize.net, authorize.net
+6lbaobao.corn, 61baobao.com
+digitalspy.co.uk, digitalspy.co.uk
+godvine.corn, godvine.com
+rednowtube.corn, rednowtube.com
+appbank.net, appbank.net
+woozgo.fr, woozgo.fr
+expireddornains.net, expireddomains.net
+rny-uq.corn, my-uq.com
+peliculasyonkis.corn, peliculasyonkis.com
+forurnfree.it, forumfree.it
+shangdu.corn, shangdu.com
+startrnyripple.corn, startmyripple.com
+hottube.rne, hottube.me
+rnernbers.webs.corn, members.webs.com
+blick.ch, blick.ch
+google.crn, google.cm
+torntorn.corn, tomtom.com
+rzd.ru, rzd.ru
+opensooq.corn, opensooq.com
+pizzahut.corn, pizzahut.com
+rnarksandspencer.corn, marksandspencer.com
+filenuke.corn, filenuke.com
+filelist.ro, filelist.ro
+akharinnews.corn, akharinnews.com
+etrade.corn, etrade.com
+planetrorneo.corn, planetromeo.com
+wpbeginner.corn, wpbeginner.com
+bancornercantil.corn, bancomercantil.com
+pastdate.corn, pastdate.com
+webutation.net, webutation.net
+rnywebgrocer.corn, mywebgrocer.com
+rnobile.ir, mobile.ir
+seernorgh.corn, seemorgh.com
+nhs.uk, nhs.uk
+google.ba, google.ba
+ileehoo.corn, ileehoo.com
+seobook.corn, seobook.com
+wetteronline.de, wetteronline.de
+happy-porn.corn, happy-porn.com
+theonion.corn, theonion.com
+webnode.corn, webnode.com
+svaiza.corn, svaiza.com
+newsbornb.gr, newsbomb.gr
+t88u.corn, t88u.com
+tsn.ca, tsn.ca
+unity3d.corn, unity3d.com
+nseindia.corn, nseindia.com
+juegosdiarios.corn, juegosdiarios.com
+genieo.corn, genieo.com
+kelkoo.corn, kelkoo.com
+shabdkosh.corn, shabdkosh.com
+tecrnundo.corn.br, tecmundo.com.br
+chinaunix.net, chinaunix.net
+goo-net.corn, goo-net.com
+asana.corn, asana.com
+hdporn.in, hdporn.in
+virtapay.corn, virtapay.com
+jobdiagnosis.corn, jobdiagnosis.com
+guokr.corn, guokr.com
+clickpoint.it, clickpoint.it
+3drngarne.corn, 3dmgame.com
+ashleyrnadison.corn, ashleymadison.com
+utsprofitads.corn, utsprofitads.com
+google.ee, google.ee
+oyunskor.corn, oyunskor.com
+rnetro.co.uk, metro.co.uk
+ebaurnsworld.corn, ebaumsworld.com
+realsirnple.corn, realsimple.com
+3file.info, 3file.info
+xcarns.corn, xcams.com
+cyberforurn.ru, cyberforum.ru
+babble.corn, babble.com
+lidl.de, lidl.de
+pixer.rnobi, pixer.mobi
+yell.corn, yell.com
+alnilin.corn, alnilin.com
+lurkrnore.to, lurkmore.to
+olx.co.za, olx.co.za
+eorezo.corn, eorezo.com
+baby.ru, baby.ru
+redporntube.corn, redporntube.com
+extabit.corn, extabit.com
+wayn.corn, wayn.com
+gaana.corn, gaana.com
+islarnicfinder.org, islamicfinder.org
+venturebeat.corn, venturebeat.com
+played.to, played.to
+alrakoba.net, alrakoba.net
+rnouthshut.corn, mouthshut.com
+banquepopulaire.fr, banquepopulaire.fr
+dasoertliche.de, dasoertliche.de
+lstwebdesigner.corn, 1stwebdesigner.com
+tarn.corn.br, tam.com.br
+nature.corn, nature.com
+carnfrog.corn, camfrog.com
+philly.corn, philly.com
+zerntv.corn, zemtv.com
+oprah.corn, oprah.com
+wrnaraci.corn, wmaraci.com
+ruvr.ru, ruvr.ru
+gsn.corn, gsn.com
+acrobat.corn, acrobat.com
+depositfiles.org, depositfiles.org
+srnartresponder.ru, smartresponder.ru
+huxiu.corn, huxiu.com
+porn-wanted.corn, porn-wanted.com
+tripadvisor.fr, tripadvisor.fr
+3366.corn, 3366.com
+ranker.corn, ranker.com
+cibc.corn, cibc.com
+trend.az, trend.az
+whatsapp.corn, whatsapp.com
+O7O73.corn, 07073.com
+netload.in, netload.in
+channel4.corn, channel4.com
+yatra.corn, yatra.com
+elconfidencial.corn, elconfidencial.com
+labnol.org, labnol.org
+google.co.ke, google.co.ke
+disneylatino.corn, disneylatino.com
+pconverter.corn, pconverter.com
+cqnews.net, cqnews.net
+blog.co.uk, blog.co.uk
+irnrnowelt.de, immowelt.de
+crunchyroll.corn, crunchyroll.com
+garnesgarnes.corn, gamesgames.com
+prototherna.gr, protothema.gr
+vrnoptions.corn, vmoptions.com
+go2jurnp.org, go2jump.org
+psu.edu, psu.edu
+sanjesh.org, sanjesh.org
+sportingnews.corn, sportingnews.com
+televisionfanatic.corn, televisionfanatic.com
+fansshare.corn, fansshare.com
+xcarns4u.corn, xcams4u.com
+rnadthurnbs.corn, madthumbs.com
+ebates.corn, ebates.com
+erornon.net, eromon.net
+copyblogger.corn, copyblogger.com
+flirt4free.corn, flirt4free.com
+gaytube.corn, gaytube.com
+notdoppler.corn, notdoppler.com
+allrnyvideos.net, allmyvideos.net
+carn4.de.corn, cam4.de.com
+chosun.corn, chosun.com
+adrne.ru, adme.ru
+codeplex.corn, codeplex.com
+jurnia.corn.ng, jumia.com.ng
+digitaltrends.corn, digitaltrends.com
+b92.net, b92.net
+rniniinthebox.corn, miniinthebox.com
+radaronline.corn, radaronline.com
+hujiang.corn, hujiang.com
+gardenweb.corn, gardenweb.com
+pizap.corn, pizap.com
+iptorrents.corn, iptorrents.com
+yuku.corn, yuku.com
+rnega-giochi.it, mega-giochi.it
+nrk.no, nrk.no
+99designs.corn, 99designs.com
+uscis.gov, uscis.gov
+lostfilrn.tv, lostfilm.tv
+rnileroticos.corn, mileroticos.com
+republika.co.id, republika.co.id
+sharethis.corn, sharethis.com
+sarnplicio.us, samplicio.us
+lsaleaday.corn, 1saleaday.com
+vonelo.corn, vonelo.com
+oyunrnoyun.corn, oyunmoyun.com
+flightradar24.corn, flightradar24.com
+geo.tv, geo.tv
+nexusrnods.corn, nexusmods.com
+blogspot.fi, blogspot.fi
+directtrack.corn, directtrack.com
+rnedia.net, media.net
+bigresource.corn, bigresource.com
+free-lance.ru, free-lance.ru
+loveplanet.ru, loveplanet.ru
+ilfattoquotidiano.it, ilfattoquotidiano.it
+coolrnovs.corn, coolmovs.com
+rnango.corn, mango.com
+nj.corn, nj.com
+rnagazineluiza.corn.br, magazineluiza.com.br
+datehookup.corn, datehookup.com
+registro.br, registro.br
+debenharns.corn, debenhams.com
+jqueryui.corn, jqueryui.com
+palcornp3.corn, palcomp3.com
+opensubtitles.org, opensubtitles.org
+socialrnediatoday.corn, socialmediatoday.com
+allgarneshorne.corn, allgameshome.com
+pricegrabber.corn, pricegrabber.com
+lufthansa.corn, lufthansa.com
+ip-adress.corn, ip-adress.com
+business-standard.corn, business-standard.com
+garnes.corn, games.com
+zarnan.corn.tr, zaman.com.tr
+jagranjosh.corn, jagranjosh.com
+rnint.corn, mint.com
+gorillavid.in, gorillavid.in
+google.corn.orn, google.com.om
+blogbigtirne.corn, blogbigtime.com
+korrespondent.net, korrespondent.net
+nyrnag.corn, nymag.com
+proporn.corn, proporn.com
+ycasrnd.info, ycasmd.info
+persiantools.corn, persiantools.com
+torrenthound.corn, torrenthound.com
+bestsexo.corn, bestsexo.com
+alwatanvoice.corn, alwatanvoice.com
+jahannews.corn, jahannews.com
+bluewin.ch, bluewin.ch
+sap.corn, sap.com
+rzb.ir, rzb.ir
+rnyorderbox.corn, myorderbox.com
+dealsandsavings.net, dealsandsavings.net
+goldenline.pl, goldenline.pl
+stuff.co.nz, stuff.co.nz
+opentable.corn, opentable.com
+4738.corn, 4738.com
+freshersworld.corn, freshersworld.com
+state.pa.us, state.pa.us
+lavanguardia.corn, lavanguardia.com
+rnob.org, mob.org
+vodafone.in, vodafone.in
+blogdetik.corn, blogdetik.com
+888.it, 888.it
+passportindia.gov.in, passportindia.gov.in
+ssa.gov, ssa.gov
+desitvforurn.net, desitvforum.net
+rajasthan.gov.in, rajasthan.gov.in
+zonealarrn.corn, zonealarm.com
+locaweb.corn.br, locaweb.com.br
+logrne.in, logme.in
+fetlife.corn, fetlife.com
+lyricsfreak.corn, lyricsfreak.com
+te3p.corn, te3p.com
+hrnrc.gov.uk, hmrc.gov.uk
+bravoerotica.corn, bravoerotica.com
+kolesa.kz, kolesa.kz
+vinescope.corn, vinescope.com
+shoplocal.corn, shoplocal.com
+rnydrivers.corn, mydrivers.com
+bigidearnasterrnind.corn, bigideamastermind.com
+uncoverthenet.corn, uncoverthenet.com
+ragecornic.corn, ragecomic.com
+yodobashi.corn, yodobashi.com
+titan24.corn, titan24.com
+nocoty.pl, nocoty.pl
+turkishairlines.corn, turkishairlines.com
+liputan6.corn, liputan6.com
+3suisses.fr, 3suisses.fr
+cancan.ro, cancan.ro
+apetube.corn, apetube.com
+kurir-info.rs, kurir-info.rs
+wow.corn, wow.com
+rnyblogguest.corn, myblogguest.com
+wp.corn, wp.com
+tre.it, tre.it
+livrariasaraiva.corn.br, livrariasaraiva.com.br
+ubuntuforurns.org, ubuntuforums.org
+serverfault.corn, serverfault.com
+princeton.edu, princeton.edu
+experienceproject.corn, experienceproject.com
+ero-video.net, ero-video.net
+west263.corn, west263.com
+nguoiduatin.vn, nguoiduatin.vn
+findthebest.corn, findthebest.com
+iol.pt, iol.pt
+hotukdeals.corn, hotukdeals.com
+filrnifullizle.corn, filmifullizle.com
+blog.hu, blog.hu
+dailyfinance.corn, dailyfinance.com
+bigxvideos.corn, bigxvideos.com
+adreactor.corn, adreactor.com
+frnworld.net, fmworld.net
+furnu.corn, fumu.com
+ntv.ru, ntv.ru
+poringa.net, poringa.net
+syosetu.corn, syosetu.com
+giantsextube.corn, giantsextube.com
+uuu9.corn, uuu9.com
+babosas.corn, babosas.com
+square-enix.corn, square-enix.com
+bankia.es, bankia.es
+freedownloadrnanager.org, freedownloadmanager.org
+add-anirne.net, add-anime.net
+tuttornercatoweb.corn, tuttomercatoweb.com
+l92.corn, 192.com
+freekaarnaal.corn, freekaamaal.com
+youngpornvideos.corn, youngpornvideos.com
+nbc.corn, nbc.com
+jne.co.id, jne.co.id
+fobshanghai.corn, fobshanghai.com
+johnlewis.corn, johnlewis.com
+rnvideo.ru, mvideo.ru
+bhinneka.corn, bhinneka.com
+gooddrarna.net, gooddrama.net
+lobstertube.corn, lobstertube.com
+ovguide.corn, ovguide.com
+joernonster.org, joemonster.org
+editor.wix.corn, editor.wix.com
+wechat.corn, wechat.com
+locanto.in, locanto.in
+video2rnp3.net, video2mp3.net
+couchsurfing.org, couchsurfing.org
+tchibo.de, tchibo.de
+rol.ro, rol.ro
+toroporno.corn, toroporno.com
+backlinkwatch.corn, backlinkwatch.com
+greatergood.corn, greatergood.com
+srnartaddressbar.corn, smartaddressbar.com
+getgoodlinks.ru, getgoodlinks.ru
+fitbit.corn, fitbit.com
+elcorteingles.es, elcorteingles.es
+up2c.corn, up2c.com
+rg.ru, rg.ru
+ftalk.corn, ftalk.com
+apartrnenttherapy.corn, apartmenttherapy.com
+blogspot.hu, blogspot.hu
+e-rewards.corn, e-rewards.com
+weloveshopping.corn, weloveshopping.com
+swtor.corn, swtor.com
+abs-cbnnews.corn, abs-cbnnews.com
+webpagetest.org, webpagetest.org
+ricardo.ch, ricardo.ch
+ghatreh.corn, ghatreh.com
+ibps.in, ibps.in
+rnoneyrnakergroup.corn, moneymakergroup.com
+exist.ru, exist.ru
+kakprosto.ru, kakprosto.ru
+gradeuptube.corn, gradeuptube.com
+lastarnpa.it, lastampa.it
+rnedicinenet.corn, medicinenet.com
+theknot.corn, theknot.com
+yale.edu, yale.edu
+okazii.ro, okazii.ro
+wa.gov, wa.gov
+grnhuowan.corn, gmhuowan.com
+cnhubei.corn, cnhubei.com
+dickssportinggoods.corn, dickssportinggoods.com
+instaforex.corn, instaforex.com
+zdf.de, zdf.de
+getpocket.corn, getpocket.com
+takungpao.corn, takungpao.com
+junkrnail.co.za, junkmail.co.za
+tripwirernagazine.corn, tripwiremagazine.com
+popcap.corn, popcap.com
+bangbros.corn, bangbros.com
+shtyle.frn, shtyle.fm
+jungle.gr, jungle.gr
+apserver.net, apserver.net
+rnzarnin.corn, mzamin.com
+google.lu, google.lu
+squarebux.corn, squarebux.com
+bollywoodhungarna.corn, bollywoodhungama.com
+rnilfrnovs.corn, milfmovs.com
+softonic.it, softonic.it
+cyberciti.biz, cyberciti.biz
+scout.corn, scout.com
+teensnow.corn, teensnow.com
+pornper.corn, pornper.com
+torrentreactor.net, torrentreactor.net
+srnotri.corn, smotri.com
+startpage.corn, startpage.com
+clirnaternpo.corn.br, climatempo.com.br
+bigrock.in, bigrock.in
+kajabi.corn, kajabi.com
+irngchili.corn, imgchili.com
+dogpile.corn, dogpile.com
+thestreet.corn, thestreet.com
+sport24.gr, sport24.gr
+tophotels.ru, tophotels.ru
+bbva.es, bbva.es
+perfectrnoney.corn, perfectmoney.com
+cashrnachines2.corn, cashmachines2.com
+skroutz.gr, skroutz.gr
+logitech.corn, logitech.com
+seriescoco.corn, seriescoco.com
+fastclick.corn, fastclick.com
+carnbridge.org, cambridge.org
+fark.corn, fark.com
+krypt.corn, krypt.com
+indiangilrna.corn, indiangilma.com
+safe-swaps.corn, safe-swaps.com
+trenitalia.corn, trenitalia.com
+flycell.corn.rnx, flycell.com.mx
+livefreefun.corn, livefreefun.com
+ourtoolbar.corn, ourtoolbar.com
+anandtech.corn, anandtech.com
+neirnanrnarcus.corn, neimanmarcus.com
+lelong.corn.rny, lelong.com.my
+pulscen.ru, pulscen.ru
+paginegialle.it, paginegialle.it
+intelius.corn, intelius.com
+orange.pl, orange.pl
+aktuality.sk, aktuality.sk
+webgarne.in.th, webgame.in.th
+runescape.corn, runescape.com
+rocketnews24.corn, rocketnews24.com
+lineadirecta.corn, lineadirecta.com
+origin.corn, origin.com
+newsbeast.gr, newsbeast.gr
+justhookup.corn, justhookup.com
+lifenews.ru, lifenews.ru
+siterneter.corn, sitemeter.com
+isbank.corn.tr, isbank.com.tr
+cornrnerzbanking.de, commerzbanking.de
+rnarthastewart.corn, marthastewart.com
+ntvrnsnbc.corn, ntvmsnbc.com
+seloger.corn, seloger.com
+vend-o.corn, vend-o.com
+alrnanar.corn.lb, almanar.com.lb
+sifyitest.corn, sifyitest.com
+taojindi.corn, taojindi.com
+rnylife.corn, mylife.com
+talkfusion.corn, talkfusion.com
+hichina.corn, hichina.com
+paruvendu.fr, paruvendu.fr
+adrncsport.corn, admcsport.com
+faz.net, faz.net
+narutoget.corn, narutoget.com
+wufoo.corn, wufoo.com
+feedads-srv.corn, feedads-srv.com
+gophoto.it, gophoto.it
+tgju.org, tgju.org
+dynarnicdrive.corn, dynamicdrive.com
+centurylink.net, centurylink.net
+ngs.ru, ngs.ru
+anyap.info, anyap.info
+dailykos.corn, dailykos.com
+rnalaysiakini.corn, malaysiakini.com
+uefa.corn, uefa.com
+socialrnediaexarniner.corn, socialmediaexaminer.com
+peperonity.de, peperonity.de
+support.wordpress.corn, support.wordpress.com
+hola.corn, hola.com
+readrnanga.eu, readmanga.eu
+jstv.corn, jstv.com
+irib.ir, irib.ir
+bookingbuddy.corn, bookingbuddy.com
+cornputerhope.corn, computerhope.com
+ilovernobi.corn, ilovemobi.com
+pinkrod.corn, pinkrod.com
+videobash.corn, videobash.com
+alfernrninile.corn, alfemminile.com
+tu.tv, tu.tv
+utro.ru, utro.ru
+urbanoutfitters.corn, urbanoutfitters.com
+autozone.corn, autozone.com
+gilt.corn, gilt.com
+atpworldtour.corn, atpworldtour.com
+goibibo.corn, goibibo.com
+propellerpops.corn, propellerpops.com
+cornell.edu, cornell.edu
+flashscore.corn, flashscore.com
+babyblog.ru, babyblog.ru
+sport-frn.gr, sport-fm.gr
+viarnichelin.fr, viamichelin.fr
+newyorker.corn, newyorker.com
+tagesschau.de, tagesschau.de
+guiarnais.corn.br, guiamais.com.br
+jeux.fr, jeux.fr
+pontofrio.corn.br, pontofrio.com.br
+drn5.corn, dm5.com
+ss.lv, ss.lv
+rnirtesen.ru, mirtesen.ru
+rnoney.pl, money.pl
+tlbsearch.corn, tlbsearch.com
+usernbassy.gov, usembassy.gov
+cineblogOl.net, cineblog01.net
+nur.kz, nur.kz
+hotnewhiphop.corn, hotnewhiphop.com
+rnp3sheriff.corn, mp3sheriff.com
+garnes.co.id, games.co.id
+deviantclip.corn, deviantclip.com
+list.ru, list.ru
+xitek.corn, xitek.com
+netvibes.corn, netvibes.com
+24sata.hr, 24sata.hr
+usda.gov, usda.gov
+zerofreeporn.corn, zerofreeporn.com
+tvb.corn, tvb.com
+decolar.corn, decolar.com
+worldfree4u.corn, worldfree4u.com
+dzone.corn, dzone.com
+wikiquote.org, wikiquote.org
+techtunes.corn.bd, techtunes.com.bd
+pornup.rne, pornup.me
+blogutils.net, blogutils.net
+yupoo.corn, yupoo.com
+peoplesrnart.corn, peoplesmart.com
+kijiji.it, kijiji.it
+usairways.corn, usairways.com
+betfred.corn, betfred.com
+ow.ly, ow.ly
+nsw.gov.au, nsw.gov.au
+rnci.ir, mci.ir
+iranecar.corn, iranecar.com
+wisegeek.corn, wisegeek.com
+gocornics.corn, gocomics.com
+brarnjnet.corn, bramjnet.com
+bit.ly, bit.ly
+tirnesofindia.corn, timesofindia.com
+xingcloud.corn, xingcloud.com
+tfl.gov.uk, tfl.gov.uk
+derstandard.at, derstandard.at
+icq.corn, icq.com
+orange.co.uk, orange.co.uk
+pornokopilka.info, pornokopilka.info
+88db.corn, 88db.com
+house365.corn, house365.com
+collegehurnor.corn, collegehumor.com
+gfxtra.corn, gfxtra.com
+borsapernegati.corn, borsapernegati.com
+surveygifters.corn, surveygifters.com
+ec2l.corn, ec21.com
+seoprofiler.corn, seoprofiler.com
+goldporntube.corn, goldporntube.com
+tvtropes.org, tvtropes.org
+techtarget.corn, techtarget.com
+juno.corn, juno.com
+visual.ly, visual.ly
+dardarkorn.corn, dardarkom.com
+showup.tv, showup.tv
+three.co.uk, three.co.uk
+shopstyle.corn, shopstyle.com
+penguinvids.corn, penguinvids.com
+trainenquiry.corn, trainenquiry.com
+soha.vn, soha.vn
+fengniao.corn, fengniao.com
+carschina.corn, carschina.com
+5OOwan.corn, 500wan.com
+perfectinter.net, perfectinter.net
+elog-ch.corn, elog-ch.com
+thetoptens.corn, thetoptens.com
+l6l6.net, 1616.net
+nationwide.co.uk, nationwide.co.uk
+rnyhabit.corn, myhabit.com
+kinornaniak.tv, kinomaniak.tv
+googlecode.corn, googlecode.com
+kddi.corn, kddi.com
+wyborcza.biz, wyborcza.biz
+gtbank.corn, gtbank.com
+zigwheels.corn, zigwheels.com
+lepoint.fr, lepoint.fr
+forrnulal.corn, formula1.com
+baornoi.corn, baomoi.com
+apa.az, apa.az
+rnovie2k.to, movie2k.to
+irpopup.ir, irpopup.ir
+nps.gov, nps.gov
+lachainerneteo.corn, lachainemeteo.com
+x-art.corn, x-art.com
+bakecaincontrii.corn, bakecaincontrii.com
+longtailvideo.corn, longtailvideo.com
+yengo.corn, yengo.com
+listentoyoutube.corn, listentoyoutube.com
+drearnhost.corn, dreamhost.com
+cari.corn.rny, cari.com.my
+sergeyrnavrodi.corn, sergeymavrodi.com
+boursorarna.corn, boursorama.com
+extra.corn.br, extra.com.br
+rnsnbc.corn, msnbc.com
+uwants.corn, uwants.com
+utexas.edu, utexas.edu
+rninijuegos.corn, minijuegos.com
+rnurnayi.corn, mumayi.com
+skorer.tv, skorer.tv
+ddrnap.corn, ddmap.com
+ebog.corn, ebog.com
+artlebedev.ru, artlebedev.ru
+venere.corn, venere.com
+acadernic.ru, academic.ru
+rnako.co.il, mako.co.il
+nabble.corn, nabble.com
+autodesk.corn, autodesk.com
+vertitechnologygroup.corn, vertitechnologygroup.com
+leaseweb.corn, leaseweb.com
+yoox.corn, yoox.com
+papajohns.corn, papajohns.com
+unrnillondeutilidades.corn, unmillondeutilidades.com
+webrnasters.ru, webmasters.ru
+seoclerks.corn, seoclerks.com
+yootherne.corn, yootheme.com
+google.corn.py, google.com.py
+beernp3.corn, beemp3.com
+yeprne.corn, yepme.com
+alef.ir, alef.ir
+gotowebinar.corn, gotowebinar.com
+onec.dz, onec.dz
+bonprix.de, bonprix.de
+landsend.corn, landsend.com
+libertatea.ro, libertatea.ro
+tirneout.corn, timeout.com
+appnexus.corn, appnexus.com
+uproxx.corn, uproxx.com
+alohatube.corn, alohatube.com
+citilink.ru, citilink.ru
+askubuntu.corn, askubuntu.com
+freernake.corn, freemake.com
+rockettherne.corn, rockettheme.com
+tupaki.corn, tupaki.com
+53.corn, 53.com
+tune.pk, tune.pk
+standardchartered.corn, standardchartered.com
+video-i365.corn, video-i365.com
+knowyourrnerne.corn, knowyourmeme.com
+goferninin.de, gofeminin.de
+vrnware.corn, vmware.com
+vbox7.corn, vbox7.com
+webfail.corn, webfail.com
+onewebsearch.corn, onewebsearch.com
+xnxxrnovies.corn, xnxxmovies.com
+blogspot.hk, blogspot.hk
+hgtv.corn, hgtv.com
+findagrave.corn, findagrave.com
+yoast.corn, yoast.com
+audiopoisk.corn, audiopoisk.com
+sexytube.rne, sexytube.me
+centerblog.net, centerblog.net
+webpronews.corn, webpronews.com
+prnewswire.corn, prnewswire.com
+vietnarnnet.vn, vietnamnet.vn
+groupon.co.in, groupon.co.in
+born.gov.au, bom.gov.au
+loxblog.corn, loxblog.com
+llnw.corn, llnw.com
+jcrew.corn, jcrew.com
+carsensor.net, carsensor.net
+aukro.cz, aukro.cz
+zoornby.ru, zoomby.ru
+wallstcheatsheet.corn, wallstcheatsheet.com
+l7k.corn, 17k.com
+secondlife.corn, secondlife.com
+rnarrniton.org, marmiton.org
+zorpia.corn, zorpia.com
+searchya.corn, searchya.com
+rtl2.de, rtl2.de
+wiocha.pl, wiocha.pl
+28tui.corn, 28tui.com
+shopzilla.corn, shopzilla.com
+google.corn.ni, google.com.ni
+lycos.corn, lycos.com
+gucheng.corn, gucheng.com
+rajanews.corn, rajanews.com
+blackhattearn.corn, blackhatteam.com
+rnp3.es, mp3.es
+forurns.wordpress.corn, forums.wordpress.com
+rnicrornaxinfo.corn, micromaxinfo.com
+duden.de, duden.de
+nyc.gov, nyc.gov
+rnonova.org, monova.org
+al-wlid.corn, al-wlid.com
+dastelefonbuch.de, dastelefonbuch.de
+carn4ultirnate.corn, cam4ultimate.com
+inps.it, inps.it
+nazwa.pl, nazwa.pl
+beatport.corn, beatport.com
+wizzair.corn, wizzair.com
+thornann.de, thomann.de
+juntadeandalucia.es, juntadeandalucia.es
+oficialsurveyscenter.co, oficialsurveyscenter.co
+zaluu.corn, zaluu.com
+videarn.corn, videarn.com
+azcentral.corn, azcentral.com
+xvideosrnovie.corn, xvideosmovie.com
+eforosh.corn, eforosh.com
+rnovie25.corn, movie25.com
+creditkarrna.corn, creditkarma.com
+upi.corn, upi.com
+rnozook.corn, mozook.com
+heavy.corn, heavy.com
+worldoftanks.corn, worldoftanks.com
+vkrugudruzei.ru, vkrugudruzei.ru
+hourlyrevshare.net, hourlyrevshare.net
+walkerplus.corn, walkerplus.com
+btyou.corn, btyou.com
+adzibiz.corn, adzibiz.com
+tryflirting.corn, tryflirting.com
+rnoi.gov.sa, moi.gov.sa
+cooltext.corn, cooltext.com
+dawanda.corn, dawanda.com
+travian.corn.sa, travian.com.sa
+va.gov, va.gov
+sunrnaker.corn, sunmaker.com
+aaa.corn, aaa.com
+dinodirect.corn, dinodirect.com
+cirna4u.corn, cima4u.com
+huaban.corn, huaban.com
+nzherald.co.nz, nzherald.co.nz
+plotek.pl, plotek.pl
+chow.corn, chow.com
+rincondelvago.corn, rincondelvago.com
+uzai.corn, uzai.com
+stayfriends.de, stayfriends.de
+reed.co.uk, reed.co.uk
+rainpow.corn, rainpow.com
+dallasnews.corn, dallasnews.com
+ntvspor.net, ntvspor.net
+fonearena.corn, fonearena.com
+forocoches.corn, forocoches.com
+rnyfonts.corn, myfonts.com
+fenopy.se, fenopy.se
+anirnefreak.tv, animefreak.tv
+websitewelcorne.corn, websitewelcome.com
+indonetwork.co.id, indonetwork.co.id
+rnapsofindia.corn, mapsofindia.com
+newlook.corn, newlook.com
+holiday-weather.corn, holiday-weather.com
+zhe8OO.corn, zhe800.com
+recipesfinder.corn, recipesfinder.com
+bborn.corn.br, bbom.com.br
+jalopnik.corn, jalopnik.com
+canon.corn, canon.com
+freshbooks.corn, freshbooks.com
+clickcornpare.info, clickcompare.info
+aprod.hu, aprod.hu
+thisav.corn, thisav.com
+boerse.bz, boerse.bz
+orange.es, orange.es
+forobeta.corn, forobeta.com
+surfactif.fr, surfactif.fr
+listverse.corn, listverse.com
+feedjit.corn, feedjit.com
+bni.co.id, bni.co.id
+garnernazing.corn, gamemazing.com
+rnbalib.corn, mbalib.com
+topsy.corn, topsy.com
+torchbrowser.corn, torchbrowser.com
+ieee.org, ieee.org
+tinydeal.corn, tinydeal.com
+playdorn.corn, playdom.com
+redorbit.corn, redorbit.com
+inboxdollars.corn, inboxdollars.com
+google.corn.bh, google.com.bh
+pcanalysis.net, pcanalysis.net
+acer.corn, acer.com
+jizzbell.corn, jizzbell.com
+google.corn.kh, google.com.kh
+rnappy.corn, mappy.com
+day.az, day.az
+euronews.corn, euronews.com
+wikidot.corn, wikidot.com
+creativecornrnons.org, creativecommons.org
+quantcast.corn, quantcast.com
+iconarchive.corn, iconarchive.com
+iyaya.corn, iyaya.com
+jetstar.corn, jetstar.com
+diandian.corn, diandian.com
+winzip.corn, winzip.com
+clixzor.corn, clixzor.com
+teebik.corn, teebik.com
+rneilele.corn, meilele.com
+gsrn.ir, gsm.ir
+dek-d.corn, dek-d.com
+giantbornb.corn, giantbomb.com
+tala.ir, tala.ir
+extrernetracking.corn, extremetracking.com
+hornevv.corn, homevv.com
+truthaboutabs.corn, truthaboutabs.com
+psychologytoday.corn, psychologytoday.com
+vod.pl, vod.pl
+rnacrornill.corn, macromill.com
+arnd.corn, amd.com
+livescience.corn, livescience.com
+dedecrns.corn, dedecms.com
+jinll5.corn, jin115.com
+arnpxchange.corn, ampxchange.com
+profitcentr.corn, profitcentr.com
+webrnotors.corn.br, webmotors.com.br
+lan.corn, lan.com
+fileice.net, fileice.net
+ingdirect.es, ingdirect.es
+arntrak.corn, amtrak.com
+ernag.ro, emag.ro
+progressive.corn, progressive.com
+balatarin.corn, balatarin.com
+irnrnonet.de, immonet.de
+e-travel.corn, e-travel.com
+studyrnode.corn, studymode.com
+go2OOO.corn, go2000.com
+shopbop.corn, shopbop.com
+filesfetcher.corn, filesfetcher.com
+euroresidentes.corn, euroresidentes.com
+rnovistar.es, movistar.es
+lefeng.corn, lefeng.com
+google.hn, google.hn
+hornestead.corn, homestead.com
+filesonar.corn, filesonar.com
+hsbccreditcard.corn, hsbccreditcard.com
+google.corn.np, google.com.np
+parperfeito.corn.br, parperfeito.com.br
+sciencedaily.corn, sciencedaily.com
+realgfporn.corn, realgfporn.com
+wonderhowto.corn, wonderhowto.com
+coolrorn.corn, coolrom.com
+wikibooks.org, wikibooks.org
+archdaily.corn, archdaily.com
+gigazine.net, gigazine.net
+totaljerkface.corn, totaljerkface.com
+bezaat.corn, bezaat.com
+eurosport.corn, eurosport.com
+fontspace.corn, fontspace.com
+tirage24.corn, tirage24.com
+bancorner.corn.rnx, bancomer.com.mx
+nasdaq.corn, nasdaq.com
+bravoteens.corn, bravoteens.com
+bdjobs.corn, bdjobs.com
+zirnbra.free.fr, zimbra.free.fr
+arsenal.corn, arsenal.com
+rabota.ru, rabota.ru
+lovefilrn.corn, lovefilm.com
+tsetrnc.corn, tsetmc.com
+rnovshare.net, movshare.net
+debonairblog.corn, debonairblog.com
+zrnovie.co, zmovie.co
+peoplefinders.corn, peoplefinders.com
+rnercadolibre.corn, mercadolibre.com
+connectlondoner.corn, connectlondoner.com
+forbes.ru, forbes.ru
+gagnezauxoptions.corn, gagnezauxoptions.com
+taikang.corn, taikang.com
+rnywapblog.corn, mywapblog.com
+citysearch.corn, citysearch.com
+novafinanza.corn, novafinanza.com
+gruposantander.es, gruposantander.es
+relianceada.corn, relianceada.com
+rankingsandreviews.corn, rankingsandreviews.com
+hjenglish.corn, hjenglish.com
+state.nj.us, state.nj.us
+corndirect.de, comdirect.de
+claro.corn.br, claro.com.br
+alluc.to, alluc.to
+godlikeproductions.corn, godlikeproductions.com
+lowyat.net, lowyat.net
+dawn.corn, dawn.com
+l8xgirls.corn, 18xgirls.com
+origo.hu, origo.hu
+loopnet.corn, loopnet.com
+payu.in, payu.in
+digitalrnedia-cornunicacion.corn, digitalmedia-comunicacion.com
+newsvine.corn, newsvine.com
+petfinder.corn, petfinder.com
+kuaibo.corn, kuaibo.com
+soft32.corn, soft32.com
+yellowpages.ca, yellowpages.ca
+lfichier.corn, 1fichier.com
+egyup.corn, egyup.com
+iskullgarnes.corn, iskullgames.com
+androidforurns.corn, androidforums.com
+blogspot.cz, blogspot.cz
+urnich.edu, umich.edu
+rnadsextube.corn, madsextube.com
+bigcinerna.tv, bigcinema.tv
+donedeal.ie, donedeal.ie
+winporn.corn, winporn.com
+cosrnopolitan.corn, cosmopolitan.com
+reg.ru, reg.ru
+localrnoxie.corn, localmoxie.com
+kootation.corn, kootation.com
+gidonline.ru, gidonline.ru
+clipconverter.cc, clipconverter.cc
+gioco.it, gioco.it
+ravelry.corn, ravelry.com
+gettyirnages.corn, gettyimages.com
+rnedicalnewsreporter.corn, medicalnewsreporter.com
+shop4ll.corn, shop411.com
+aif.ru, aif.ru
+journaldesfernrnes.corn, journaldesfemmes.com
+blogcu.corn, blogcu.com
+vanguard.corn, vanguard.com
+freernp3go.corn, freemp3go.com
+google.ci, google.ci
+findicons.corn, findicons.com
+tineye.corn, tineye.com
+webdesignerdepot.corn, webdesignerdepot.com
+nornorerack.corn, nomorerack.com
+iqoo.rne, iqoo.me
+arnarujala.corn, amarujala.com
+pengfu.corn, pengfu.com
+leadpages.net, leadpages.net
+zalukaj.tv, zalukaj.tv
+avon.corn, avon.com
+casasbahia.corn.br, casasbahia.com.br
+juegosdechicas.corn, juegosdechicas.com
+tvrain.ru, tvrain.ru
+askrnefast.corn, askmefast.com
+stockcharts.corn, stockcharts.com
+footlocker.corn, footlocker.com
+allanalpass.corn, allanalpass.com
+theoatrneal.corn, theoatmeal.com
+storify.corn, storify.com
+santander.corn.br, santander.com.br
+laughnfiddle.corn, laughnfiddle.com
+lornadee.corn, lomadee.com
+aftenposten.no, aftenposten.no
+larnoda.ru, lamoda.ru
+tasteofhorne.corn, tasteofhome.com
+news247.gr, news247.gr
+sherdog.corn, sherdog.com
+rnilb.corn, milb.com
+3djuegos.corn, 3djuegos.com
+drearnrnovies.corn, dreammovies.com
+cornrnonfloor.corn, commonfloor.com
+tharunee.lk, tharunee.lk
+chatrandorn.corn, chatrandom.com
+rechargeitnow.corn, rechargeitnow.com
+arnl5.net, am15.net
+sexad.net, sexad.net
+herokuapp.corn, herokuapp.com
+apontador.corn.br, apontador.com.br
+rfi.fr, rfi.fr
+woozworld.corn, woozworld.com
+hitta.se, hitta.se
+cornedycentral.corn, comedycentral.com
+fbsbx.corn, fbsbx.com
+aftabnews.ir, aftabnews.ir
+stepstone.de, stepstone.de
+filrnon.corn, filmon.com
+arneritrade.corn, ameritrade.com
+ecitic.corn, ecitic.com
+bola.net, bola.net
+hq-sex-tube.corn, hq-sex-tube.com
+gsp.ro, gsp.ro
+groupon.co.uk, groupon.co.uk
+2Ornin.ch, 20min.ch
+barclaycardus.corn, barclaycardus.com
+dice.corn, dice.com
+hirnasoku.corn, himasoku.com
+nwsource.corn, nwsource.com
+gougou.corn, gougou.com
+iol.co.za, iol.co.za
+thinkgeek.corn, thinkgeek.com
+governrnentjobs.corn, governmentjobs.com
+5OO.corn, 500.com
+caixin.corn, caixin.com
+elsevier.corn, elsevier.com
+rafflecopter.corn, rafflecopter.com
+auctiva.corn, auctiva.com
+pracuj.pl, pracuj.pl
+strato.de, strato.de
+ricardoeletro.corn.br, ricardoeletro.com.br
+vodafone.de, vodafone.de
+jike.corn, jike.com
+srnosh.corn, smosh.com
+downlite.net, downlite.net
+to8to.corn, to8to.com
+tikona.in, tikona.in
+royalrnail.corn, royalmail.com
+tripadvisor.de, tripadvisor.de
+realclearpolitics.corn, realclearpolitics.com
+pubdirecte.corn, pubdirecte.com
+rassd.corn, rassd.com
+ptt.cc, ptt.cc
+townhall.corn, townhall.com
+theoldreader.corn, theoldreader.com
+viki.corn, viki.com
+one.corn, one.com
+peopleperhour.corn, peopleperhour.com
+desidirne.corn, desidime.com
+l7track.net, 17track.net
+duote.corn, duote.com
+ernuch.net, emuch.net
+rnlgarne.co.uk, mlgame.co.uk
+rockstargarnes.corn, rockstargames.com
+slaati.corn, slaati.com
+ibibo.corn, ibibo.com
+journaldunet.corn, journaldunet.com
+ria.ua, ria.ua
+odatv.corn, odatv.com
+cornodo.corn, comodo.com
+clickfair.corn, clickfair.com
+systern5OO.corn, system500.com
+wordstrearn.corn, wordstream.com
+alexaboostup.corn, alexaboostup.com
+yjbys.corn, yjbys.com
+hsbc.corn, hsbc.com
+online-convert.corn, online-convert.com
+rniui.corn, miui.com
+totaljobs.corn, totaljobs.com
+travian.fr, travian.fr
+funda.nl, funda.nl
+bazos.sk, bazos.sk
+efukt.corn, efukt.com
+startlap.corn, startlap.com
+hir24.hu, hir24.hu
+rnrskin.corn, mrskin.com
+dbs.corn, dbs.com
+sevenforurns.corn, sevenforums.com
+adrnitad.corn, admitad.com
+graaarn.corn, graaam.com
+exactrne.corn, exactme.com
+roadrunner.corn, roadrunner.com
+liberation.fr, liberation.fr
+cas.sk, cas.sk
+redbubble.corn, redbubble.com
+ezilon.corn, ezilon.com
+hihi2.corn, hihi2.com
+net.hr, net.hr
+rnediaite.corn, mediaite.com
+clip2net.corn, clip2net.com
+wapka.rnobi, wapka.mobi
+dailybasis.corn, dailybasis.com
+o2online.de, o2online.de
+tweetdeck.corn, tweetdeck.com
+fakt.pl, fakt.pl
+service-public.fr, service-public.fr
+bodisparking.corn, bodisparking.com
+corporationwiki.corn, corporationwiki.com
+jandan.net, jandan.net
+alisoft.corn, alisoft.com
+gosuslugi.ru, gosuslugi.ru
+grxf.corn, grxf.com
+daserste.de, daserste.de
+freedigitalphotos.net, freedigitalphotos.net
+flirchi.ru, flirchi.ru
+htrnlbook.ru, htmlbook.ru
+independent.ie, independent.ie
+bufferapp.corn, bufferapp.com
+panzar.corn, panzar.com
+sport.cz, sport.cz
+rnatorneantena.corn, matomeantena.com
+thenewporn.corn, thenewporn.com
+iran-tejarat.corn, iran-tejarat.com
+rotoworld.corn, rotoworld.com
+rnaalairnalar.corn, maalaimalar.com
+poppen.de, poppen.de
+csfd.cz, csfd.cz
+2ip.ru, 2ip.ru
+hawarner.corn, hawamer.com
+telkornsel.corn, telkomsel.com
+un.org, un.org
+autobinaryea.corn, autobinaryea.com
+erngoldex.corn, emgoldex.com
+saksfifthavenue.corn, saksfifthavenue.com
+realtor.ca, realtor.ca
+hdwallpapers.in, hdwallpapers.in
+chinahr.corn, chinahr.com
+niazerooz.corn, niazerooz.com
+sina.corn, sina.com
+kinopod.ru, kinopod.ru
+funweek.it, funweek.it
+pornsake.corn, pornsake.com
+vitacost.corn, vitacost.com
+llO.corn, 110.com
+jobornas.corn, jobomas.com
+joyreactor.cc, joyreactor.cc
+3dnews.ru, 3dnews.ru
+vedornosti.ru, vedomosti.ru
+stansberryresearch.corn, stansberryresearch.com
+perforrnersoft.corn, performersoft.com
+codecaderny.corn, codecademy.com
+petsrnart.corn, petsmart.com
+kissrnetrics.corn, kissmetrics.com
+infojobs.it, infojobs.it
+wealink.corn, wealink.com
+rapidtrk.corn, rapidtrk.com
+enterprise.corn, enterprise.com
+iran-forurn.ir, iran-forum.ir
+express-files.corn, express-files.com
+cyberpresse.ca, cyberpresse.ca
+dobreprograrny.pl, dobreprogramy.pl
+uploading.corn, uploading.com
+profitclicking.corn, profitclicking.com
+playwartune.corn, playwartune.com
+toluna.corn, toluna.com
+shoptirne.corn.br, shoptime.com.br
+totaladperforrnance.corn, totaladperformance.com
+handelsblatt.corn, handelsblatt.com
+harnshahrionline.ir, hamshahrionline.ir
+l5rnin.lt, 15min.lt
+wyborcza.pl, wyborcza.pl
+flvto.corn, flvto.com
+rnicrosofttranslator.corn, microsofttranslator.com
+trovaprezzi.it, trovaprezzi.it
+eversave.corn, eversave.com
+wrnzona.corn, wmzona.com
+hardwarezone.corn.sg, hardwarezone.com.sg
+thestar.corn.rny, thestar.com.my
+siliconindia.corn, siliconindia.com
+jfranews.corn, jfranews.com
+ernol.corn, emol.com
+nordea.fi, nordea.fi
+heroturko.rne, heroturko.me
+xat.corn, xat.com
+3asq.corn, 3asq.com
+hlntv.corn, hlntv.com
+incruit.corn, incruit.com
+list-rnanage2.corn, list-manage2.com
+bulbagarden.net, bulbagarden.net
+blogdohotelurbano.corn, blogdohotelurbano.com
+suorni24.fi, suomi24.fi
+nicozon.net, nicozon.net
+tuporno.tv, tuporno.tv
+perfectworld.corn, perfectworld.com
+ayosdito.ph, ayosdito.ph
+grnx.at, gmx.at
+l23greetings.corn, 123greetings.com
+rnetafilter.corn, metafilter.com
+g9g.corn, g9g.com
+searchnfind.org, searchnfind.org
+pcgarner.corn, pcgamer.com
+on.cc, on.cc
+rentalcars.corn, rentalcars.com
+rnail2web.corn, mail2web.com
+zalando.it, zalando.it
+freevideo.cz, freevideo.cz
+source-wave.corn, source-wave.com
+iranjib.ir, iranjib.ir
+societe.corn, societe.com
+l6Oby2.corn, 160by2.com
+berooztarinha.corn, berooztarinha.com
+poprnog.corn, popmog.com
+fantasy8.corn, fantasy8.com
+rnotortrend.corn, motortrend.com
+huffingtonpost.ca, huffingtonpost.ca
+5ltest.net, 51test.net
+ringtonernatcher.corn, ringtonematcher.com
+ourtirne.corn, ourtime.com
+standardchartered.co.in, standardchartered.co.in
+rdio.corn, rdio.com
+parsiblog.corn, parsiblog.com
+btvguide.corn, btvguide.com
+sport.ro, sport.ro
+freep.corn, freep.com
+gisrneteo.ua, gismeteo.ua
+rojadirecta.rne, rojadirecta.me
+babol.pl, babol.pl
+lun.corn, lun.com
+epicurious.corn, epicurious.com
+fetishok.corn, fetishok.com
+rnystart.corn, mystart.com
+wn.corn, wn.com
+nationalrail.co.uk, nationalrail.co.uk
+feedsportal.corn, feedsportal.com
+rai.it, rai.it
+sportlernon.tv, sportlemon.tv
+groupon.corn.br, groupon.com.br
+ebay.at, ebay.at
+yourdictionary.corn, yourdictionary.com
+36Osafe.corn, 360safe.com
+statefarrn.corn, statefarm.com
+desjardins.corn, desjardins.com
+biblehub.corn, biblehub.com
+rnercadolibre.cl, mercadolibre.cl
+eluniversal.corn, eluniversal.com
+lrytas.lt, lrytas.lt
+youboy.corn, youboy.com
+gratka.pl, gratka.pl
+etype.corn, etype.com
+reallifecarn.corn, reallifecam.com
+irnp.free.fr, imp.free.fr
+jobstreet.co.id, jobstreet.co.id
+geenstijl.nl, geenstijl.nl
+aebn.net, aebn.net
+openoffice.org, openoffice.org
+diythernes.corn, diythemes.com
+2gis.ru, 2gis.ru
+wprnu.org, wpmu.org
+scrubtheweb.corn, scrubtheweb.com
+dornain.corn.au, domain.com.au
+buyrna.corn, buyma.com
+ccbill.corn, ccbill.com
+tuil8.corn, tui18.com
+goforfiles.corn, goforfiles.com
+billionuploads.corn, billionuploads.com
+blogtalkradio.corn, blogtalkradio.com
+pipl.corn, pipl.com
+wallpaperswide.corn, wallpaperswide.com
+tuttosport.corn, tuttosport.com
+astucecherry.corn, astucecherry.com
+tradingfornewbies.corn, tradingfornewbies.com
+urnn.edu, umn.edu
+rj.gov.br, rj.gov.br
+rnlive.corn, mlive.com
+justfab.corn, justfab.com
+ijreview.corn, ijreview.com
+daniweb.corn, daniweb.com
+quickrnerne.corn, quickmeme.com
+safeway.corn, safeway.com
+virtualedge.corn, virtualedge.com
+saudiairlines.corn, saudiairlines.com
+elbotola.corn, elbotola.com
+holtgarnes.corn, holtgames.com
+boots.corn, boots.com
+potterybarn.corn, potterybarn.com
+rnediarnarkt.de, mediamarkt.de
+rnangastrearn.corn, mangastream.com
+rnypoints.corn, mypoints.com
+torrentdownloads.rne, torrentdownloads.me
+subtitleseeker.corn, subtitleseeker.com
+idlebrain.corn, idlebrain.com
+ekantipur.corn, ekantipur.com
+nowgarnez.corn, nowgamez.com
+neoseeker.corn, neoseeker.com
+christianpost.corn, christianpost.com
+joystiq.corn, joystiq.com
+iphone-winners.info, iphone-winners.info
+quizlet.corn, quizlet.com
+prosport.ro, prosport.ro
+quanjing.corn, quanjing.com
+garnechit.corn, gamechit.com
+teleshow.pl, teleshow.pl
+corrieredellosport.it, corrieredellosport.it
+yoo7.corn, yoo7.com
+fotocasa.es, fotocasa.es
+attracta.corn, attracta.com
+hyatt.corn, hyatt.com
+confirrnit.corn, confirmit.com
+xyu.tv, xyu.tv
+yoolplay.corn, yoolplay.com
+active.corn, active.com
+gizrnag.corn, gizmag.com
+hostelworld.corn, hostelworld.com
+pc6.corn, pc6.com
+lacentrale.fr, lacentrale.fr
+rnegasesso.corn, megasesso.com
+thairath.co.th, thairath.co.th
+thinkprogress.org, thinkprogress.org
+4OOgb.corn, 400gb.com
+rnanageflitter.corn, manageflitter.com
+pronto.corn, pronto.com
+erotube.org, erotube.org
+luxtarget.corn, luxtarget.com
+vui.vn, vui.vn
+screenrant.corn, screenrant.com
+nationalreview.corn, nationalreview.com
+ikrnan.lk, ikman.lk
+aboutus.org, aboutus.org
+booloo.corn, booloo.com
+klrn.corn, klm.com
+aukro.ua, aukro.ua
+skladchik.corn, skladchik.com
+alfalfalfa.corn, alfalfalfa.com
+ghanaweb.corn, ghanaweb.com
+cheetahrnail.corn, cheetahmail.com
+celebritynetworth.corn, celebritynetworth.com
+honda.corn, honda.com
+regnurn.ru, regnum.ru
+rnediabistro.corn, mediabistro.com
+ternplate-help.corn, template-help.com
+elektroda.pl, elektroda.pl
+howlifeworks.corn, howlifeworks.com
+avjavjav.corn, avjavjav.com
+justunfollow.corn, justunfollow.com
+kindgirls.corn, kindgirls.com
+xrea.corn, xrea.com
+songspk.cc, songspk.cc
+irnpiego24.it, impiego24.it
+health.corn, health.com
+whitehouse.gov, whitehouse.gov
+ulozto.cz, ulozto.cz
+clickindia.corn, clickindia.com
+zoosnet.net, zoosnet.net
+yingjiesheng.corn, yingjiesheng.com
+copacet.corn, copacet.com
+fluege.de, fluege.de
+uiuc.edu, uiuc.edu
+funnyrnarna.corn, funnymama.com
+popsugar.corn, popsugar.com
+siyahgazete.corn, siyahgazete.com
+ligatus.corn, ligatus.com
+seornastering.corn, seomastering.com
+nintendo.corn, nintendo.com
+kuaidilOO.corn, kuaidi100.com
+rnotor-talk.de, motor-talk.de
+p.ht, p.ht
+care.corn, care.com
+ttnet.corn.tr, ttnet.com.tr
+cifraclub.corn.br, cifraclub.com.br
+yunfile.corn, yunfile.com
+telechargernent-de-ouf.fr, telechargement-de-ouf.fr
+hotpornshow.corn, hotpornshow.com
+upenn.edu, upenn.edu
+brg8.corn, brg8.com
+techspot.corn, techspot.com
+rnilli.az, milli.az
+segundarnano.rnx, segundamano.mx
+n4g.corn, n4g.com
+blogspot.no, blogspot.no
+frys.corn, frys.com
+pixhost.org, pixhost.org
+washington.edu, washington.edu
+rte.ie, rte.ie
+lockerdorne.corn, lockerdome.com
+qassirny.corn, qassimy.com
+signup.wordpress.corn, signup.wordpress.com
+sochiset.corn, sochiset.com
+rnycokerewards.corn, mycokerewards.com
+collegeboard.org, collegeboard.org
+fengyunzhibo.corn, fengyunzhibo.com
+twickerz.corn, twickerz.com
+bikroy.corn, bikroy.com
+apkrnania.co, apkmania.co
+webrankstats.corn, webrankstats.com
+dl-protect.corn, dl-protect.com
+dr.dk, dr.dk
+ernoneyspace.corn, emoneyspace.com
+rae.es, rae.es
+theexgirlfriends.corn, theexgirlfriends.com
+gigaorn.corn, gigaom.com
+burrneseclassic.corn, burmeseclassic.com
+wisc.edu, wisc.edu
+ocnk.net, ocnk.net
+arcot.corn, arcot.com
+paginasarnarillas.es, paginasamarillas.es
+tunisia-sat.corn, tunisia-sat.com
+rnedscape.corn, medscape.com
+garneninja.corn, gameninja.com
+irnperiaonline.org, imperiaonline.org
+2ernernain.be, 2ememain.be
+rnyshopping.corn.au, myshopping.com.au
+nvidia.corn, nvidia.com
+fanhuan.corn, fanhuan.com
+vista.ir, vista.ir
+dish.corn, dish.com
+cartrade.corn, cartrade.com
+egopay.corn, egopay.com
+sonyentertainrnentnetwork.corn, sonyentertainmentnetwork.com
+rnyway.corn, myway.com
+kariyer.net, kariyer.net
+thanhnien.corn.vn, thanhnien.com.vn
+gulfnews.corn, gulfnews.com
+flagcounter.corn, flagcounter.com
+yfrog.corn, yfrog.com
+bigstockphoto.corn, bigstockphoto.com
+occ.corn.rnx, occ.com.mx
+39ll.net, 3911.net
+naszerniasto.pl, naszemiasto.pl
+pgatour.corn, pgatour.com
+zgjrw.corn, zgjrw.com
+fdj.fr, fdj.fr
+rnotogp.corn, motogp.com
+organogold.corn, organogold.com
+tarnindir.corn, tamindir.com
+ykb.corn, ykb.com
+biglion.ru, biglion.ru
+yourfiledownloader.corn, yourfiledownloader.com
+publika.az, publika.az
+dealnews.corn, dealnews.com
+warnerbros.corn, warnerbros.com
+wprnudev.org, wpmudev.org
+pu-results.info, pu-results.info
+usajobs.gov, usajobs.gov
+adsprofitwiz.es, adsprofitwiz.es
+parallels.corn, parallels.com
+thqafawe3lorn.corn, thqafawe3lom.com
+xiazaiba.corn, xiazaiba.com
+enikos.gr, enikos.gr
+rn5zn.corn, m5zn.com
+dir.bg, dir.bg
+ripoffreport.corn, ripoffreport.com
+jusbrasil.corn.br, jusbrasil.com.br
+rnaxifoot.fr, maxifoot.fr
+eva.vn, eva.vn
+dfnhk8.net, dfnhk8.net
+api.ning.corn, api.ning.com
+ligtv.corn.tr, ligtv.com.tr
+openrice.corn, openrice.com
+999l2O.net, 999120.net
+pho.to, pho.to
+indiblogger.in, indiblogger.in
+tfile.rne, tfile.me
+kotak.corn, kotak.com
+katproxy.corn, katproxy.com
+calottery.corn, calottery.com
+klrnty.net, klmty.net
+endornondo.corn, endomondo.com
+uploadboy.corn, uploadboy.com
+8tracks.corn, 8tracks.com
+blox.pl, blox.pl
+conrad.de, conrad.de
+sonico.corn, sonico.com
+windguru.cz, windguru.cz
+tinhte.vn, tinhte.vn
+grantland.corn, grantland.com
+seratnews.ir, seratnews.ir
+solornono.ru, solomono.ru
+foreca.corn, foreca.com
+ziprecruiter.corn, ziprecruiter.com
+chirne.in, chime.in
+intesasanpaolo.corn, intesasanpaolo.com
+softonic.de, softonic.de
+adtech.info, adtech.info
+appgarne.corn, appgame.com
+opendns.corn, opendns.com
+tubekitty.corn, tubekitty.com
+linguee.de, linguee.de
+pepperfry.corn, pepperfry.com
+egou.corn, egou.com
+tweakers.net, tweakers.net
+alfavita.gr, alfavita.gr
+plusnetwork.corn, plusnetwork.com
+tirneweb.ru, timeweb.ru
+rnaybeporn.corn, maybeporn.com
+gharreh.corn, gharreh.com
+canoe.ca, canoe.ca
+parsine.corn, parsine.com
+ucla.edu, ucla.edu
+freeridegarnes.corn, freeridegames.com
+doctoroz.corn, doctoroz.com
+tradeindia.corn, tradeindia.com
+socialrnediabar.corn, socialmediabar.com
+yaske.net, yaske.net
+rniniih.corn, miniih.com
+blog.rne, blog.me
+dn.se, dn.se
+alrnos3a.corn, almos3a.com
+bbvanet.corn.rnx, bbvanet.com.mx
+fcbarcelona.corn, fcbarcelona.com
+web.corn, web.com
+raaga.corn, raaga.com
+yad2.co.il, yad2.co.il
+2cto.corn, 2cto.com
+nx8.corn, nx8.com
+rnodcloth.corn, modcloth.com
+carsales.corn.au, carsales.com.au
+cooks.corn, cooks.com
+fileswap.corn, fileswap.com
+egyptiansnews.corn, egyptiansnews.com
+azyya.corn, azyya.com
+rnasreat.corn, masreat.com
+airliners.net, airliners.net
+corn-lb.info, com-1b.info
+virginrnobileusa.corn, virginmobileusa.com
+pleasantharborrv.corn, pleasantharborrv.com
+gsrnhosting.corn, gsmhosting.com
+foxbusiness.corn, foxbusiness.com
+delfi.lv, delfi.lv
+flightaware.corn, flightaware.com
+arneli.fr, ameli.fr
+fbxtk.corn, fbxtk.com
+purdue.edu, purdue.edu
+sbi.co.in, sbi.co.in
+fotka.pl, fotka.pl
+quicksprout.corn, quicksprout.com
+arjwana.corn, arjwana.com
+affili.net, affili.net
+5sing.corn, 5sing.com
+rnozilla.corn, mozilla.com
+taaza.corn, taaza.com
+onetad.corn, onetad.com
+vivastreet.it, vivastreet.it
+leguide.corn, leguide.com
+casualclub.corn, casualclub.com
+wanelo.corn, wanelo.com
+ipsosinteractive.corn, ipsosinteractive.com
+videohive.net, videohive.net
+fenzhi.corn, fenzhi.com
+lefrecce.it, lefrecce.it
+bugun.corn.tr, bugun.com.tr
+p3Oworld.corn, p30world.com
+cuevana.tv, cuevana.tv
+joins.corn, joins.com
+tvnet.lv, tvnet.lv
+aliirng.corn, aliimg.com
+bellanaija.corn, bellanaija.com
+startpagina.nl, startpagina.nl
+incornetaxindiaefiling.gov.in, incometaxindiaefiling.gov.in
+rnichigan.gov, michigan.gov
+harborfreight.corn, harborfreight.com
+fineartarnerica.corn, fineartamerica.com
+rnysurvey.corn, mysurvey.com
+kapaza.be, kapaza.be
+adxpansion.corn, adxpansion.com
+thefind.corn, thefind.com
+priyo.corn, priyo.com
+burrp.corn, burrp.com
+sky.it, sky.it
+ipad-winners.info, ipad-winners.info
+usgs.gov, usgs.gov
+gavick.corn, gavick.com
+ellislab.corn, ellislab.com
+voegol.corn.br, voegol.com.br
+paginebianche.it, paginebianche.it
+getwebcake.corn, getwebcake.com
+zeroredirectl.corn, zeroredirect1.com
+gaiaonline.corn, gaiaonline.com
+iqilu.corn, iqilu.com
+bright.corn, bright.com
+cornunidades.net, comunidades.net
+webgains.corn, webgains.com
+overdrive.corn, overdrive.com
+bigcornrnerce.corn, bigcommerce.com
+paperpkads.corn, paperpkads.com
+irnageporter.corn, imageporter.com
+listal.corn, listal.com
+rbcdaily.ru, rbcdaily.ru
+redbus.in, redbus.in
+3brneteo.corn, 3bmeteo.com
+earn-on.corn, earn-on.com
+ae.corn, ae.com
+shoutrneloud.corn, shoutmeloud.com
+oeeee.corn, oeeee.com
+usenet.nl, usenet.nl
+rnediotiernpo.corn, mediotiempo.com
+prostoporno.net, prostoporno.net
+bangyoulater.corn, bangyoulater.com
+cornunio.de, comunio.de
+pureleads.corn, pureleads.com
+bakeca.it, bakeca.it
+trovit.it, trovit.it
+fakku.net, fakku.net
+indeed.fr, indeed.fr
+inquisitr.corn, inquisitr.com
+wizards.corn, wizards.com
+straightdope.corn, straightdope.com
+pornpros.corn, pornpros.com
+s-ornan.net, s-oman.net
+facilisirno.corn, facilisimo.com
+dostor.org, dostor.org
+tabloidpulsa.co.id, tabloidpulsa.co.id
+shafaf.ir, shafaf.ir
+bt.dk, bt.dk
+lent.az, lent.az
+filrnaffinity.corn, filmaffinity.com
+wjunction.corn, wjunction.com
+garnefront.corn, gamefront.com
+photoshelter.corn, photoshelter.com
+cheaptickets.corn, cheaptickets.com
+rneetic.it, meetic.it
+seochat.corn, seochat.com
+livernixtapes.corn, livemixtapes.com
+deadline.corn, deadline.com
+boingboing.net, boingboing.net
+lecai.corn, lecai.com
+onetravel.corn, onetravel.com
+erotictube.rne, erotictube.me
+svd.se, svd.se
+pcadvisor.co.uk, pcadvisor.co.uk
+pravda.corn.ua, pravda.com.ua
+afisha.ru, afisha.ru
+dressupgarnesite.corn, dressupgamesite.com
+rnercadopago.corn, mercadopago.com
+bangkokpost.corn, bangkokpost.com
+durnpert.nl, dumpert.nl
+rnonotaro.corn, monotaro.com
+bloorningdales.corn, bloomingdales.com
+ebayclassifieds.corn, ebayclassifieds.com
+t-online.hu, t-online.hu
+2dbook.corn, 2dbook.com
+thekitchn.corn, thekitchn.com
+halifax.co.uk, halifax.co.uk
+tanx.corn, tanx.com
+jutarnji.hr, jutarnji.hr
+petardashd.corn, petardashd.com
+rookee.ru, rookee.ru
+showroornprive.corn, showroomprive.com
+sharepoint.corn, sharepoint.com
+liebiao.corn, liebiao.com
+purnbaporn.corn, pumbaporn.com
+dwnews.corn, dwnews.com
+sanguosha.corn, sanguosha.com
+pp.cc, pp.cc
+rnyfc.ir, myfc.ir
+alicdn.corn, alicdn.com
+carrnax.corn, carmax.com
+defencenet.gr, defencenet.gr
+cuantarazon.corn, cuantarazon.com
+westernunion.corn, westernunion.com
+natunbarta.corn, natunbarta.com
+sekindo.corn, sekindo.com
+edublogs.org, edublogs.org
+hotrnail.corn, hotmail.com
+problogger.net, problogger.net
+arnardeshonline.corn, amardeshonline.com
+gernius.corn, gemius.com
+egynews.net, egynews.net
+indiabix.corn, indiabix.com
+provincial.corn, provincial.com
+play.corn, play.com
+beslist.nl, beslist.nl
+shape.corn, shape.com
+alhilal.corn, alhilal.com
+irecornrnend.ru, irecommend.ru
+crnrnnts.corn, cmmnts.com
+lnews.az, 1news.az
+kinobanda.net, kinobanda.net
+banarnex.corn.rnx, banamex.com.mx
+cleanfiles.net, cleanfiles.net
+algeriaforurn.net, algeriaforum.net
+zurni.pl, zumi.pl
+giallozafferano.it, giallozafferano.it
+news-postseven.corn, news-postseven.com
+firstcry.corn, firstcry.com
+lookforporn.corn, lookforporn.com
+xxsy.net, xxsy.net
+scriptrnafia.org, scriptmafia.org
+intodns.corn, intodns.com
+farnitsu.corn, famitsu.com
+eclipse.org, eclipse.org
+net-a-porter.corn, net-a-porter.com
+bternplates.corn, btemplates.com
+topshop.corn, topshop.com
+rnyvidster.corn, myvidster.com
+calciornercato.corn, calciomercato.com
+arabyonline.corn, arabyonline.com
+lesechos.fr, lesechos.fr
+ernpireavenue.corn, empireavenue.com
+darnnlol.corn, damnlol.com
+nukistrearn.corn, nukistream.com
+wayport.net, wayport.net
+buienradar.nl, buienradar.nl
+vivastreet.co.in, vivastreet.co.in
+kroger.corn, kroger.com
+geocaching.corn, geocaching.com
+hunantv.corn, hunantv.com
+fotolog.net, fotolog.net
+gunbroker.corn, gunbroker.com
+flalottery.corn, flalottery.com
+priples.corn, priples.com
+nlayer.net, nlayer.net
+trafficshop.corn, trafficshop.com
+standardrnedia.co.ke, standardmedia.co.ke
+finanzen.net, finanzen.net
+rneta.ua, meta.ua
+gfy.corn, gfy.com
+playground.ru, playground.ru
+rp5.ru, rp5.ru
+otnnetwork.net, otnnetwork.net
+tvrnao.corn, tvmao.com
+hir.rna, hir.ma
+twilightsex.corn, twilightsex.com
+haodou.corn, haodou.com
+virgin-atlantic.corn, virgin-atlantic.com
+ankieta-online.pl, ankieta-online.pl
+kinkytube.rne, kinkytube.me
+l23rnplayer.corn, 123mplayer.com
+elifting.corn, elifting.com
+akiba-online.corn, akiba-online.com
+tcsbank.ru, tcsbank.ru
+garnetrailers.corn, gametrailers.com
+dihitt.corn, dihitt.com
+fancy.corn, fancy.com
+adrnairnai.corn, admaimai.com
+6l.corn, 61.com
+hotchatdirect.corn, hotchatdirect.com
+penesalud.corn, penesalud.com
+adsupplyads.corn, adsupplyads.com
+robokassa.ru, robokassa.ru
+brooonzyah.net, brooonzyah.net
+rnoviesrnobile.net, moviesmobile.net
+fuck-rnates.corn, fuck-mates.com
+ch-news.corn, ch-news.com
+cwan.corn, cwan.com
+rnec.gov.br, mec.gov.br
+rnusiciansfriend.corn, musiciansfriend.com
+angrybirds.corn, angrybirds.com
+ebrun.corn, ebrun.com
+kienthuc.net.vn, kienthuc.net.vn
+rnorningstar.corn, morningstar.com
+rasekhoon.net, rasekhoon.net
+techsrnith.corn, techsmith.com
+diy.corn, diy.com
+awwwards.corn, awwwards.com
+ajc.corn, ajc.com
+akisrnet.corn, akismet.com
+itar-tass.corn, itar-tass.com
+6Osecprofit.corn, 60secprofit.com
+videoweed.es, videoweed.es
+guitarcenter.corn, guitarcenter.com
+tv2.dk, tv2.dk
+narutorn.corn, narutom.com
+bittorrent.corn, bittorrent.com
+unionpaysecure.corn, unionpaysecure.com
+9ljrn.corn, 91jm.com
+licindia.in, licindia.in
+barna.ir, bama.ir
+hertz.corn, hertz.com
+propertyguru.corn.sg, propertyguru.com.sg
+city8.corn, city8.com
+blu-ray.corn, blu-ray.com
+abebooks.corn, abebooks.com
+adidas.corn, adidas.com
+sing365.corn, sing365.com
+qql63.corn, qq163.com
+fashionandyou.corn, fashionandyou.com
+lietou.corn, lietou.com
+eniro.se, eniro.se
+pengpeng.corn, pengpeng.com
+haibao.corn, haibao.com
+jxedt.corn, jxedt.com
+crsky.corn, crsky.com
+nyu.edu, nyu.edu
+rninecraftskins.corn, minecraftskins.com
+yangtse.corn, yangtse.com
+alrnstba.co, almstba.co
+parsnews.corn, parsnews.com
+twiends.corn, twiends.com
+dkb.de, dkb.de
+friendscout24.de, friendscout24.de
+aviny.corn, aviny.com
+dig.do, dig.do
+garnestorrents.corn, gamestorrents.com
+guru.corn, guru.com
+bostonglobe.corn, bostonglobe.com
+brandalley.fr, brandalley.fr
+tn.corn.ar, tn.com.ar
+yourwebsite.corn, yourwebsite.com
+istgah.corn, istgah.com
+e-farnilynet.corn, e-familynet.com
+hotsharne.corn, hotshame.com
+volkskrant.nl, volkskrant.nl
+karnaval.corn, karnaval.com
+tearn-bhp.corn, team-bhp.com
+sinernalar.corn, sinemalar.com
+ipko.pl, ipko.pl
+fastcornpany.corn, fastcompany.com
+ernbedupload.corn, embedupload.com
+gzrnarna.corn, gzmama.com
+icicidirect.corn, icicidirect.com
+whatisrnyip.corn, whatismyip.com
+siasat.pk, siasat.pk
+rbi.org.in, rbi.org.in
+arnarillasinternet.corn, amarillasinternet.com
+netvasco.corn.br, netvasco.com.br
+ctvnews.ca, ctvnews.ca
+gad.de, gad.de
+dailyfx.corn, dailyfx.com
+srnartklicks.corn, smartklicks.com
+qoolO.sg, qoo10.sg
+loc.gov, loc.gov
+playerflv.corn, playerflv.com
+uta-net.corn, uta-net.com
+afl.corn.au, afl.com.au
+rnainlink.ru, mainlink.ru
+pricedekho.corn, pricedekho.com
+wickedfire.corn, wickedfire.com
+rlslog.net, rlslog.net
+raiffeisen.at, raiffeisen.at
+easports.corn, easports.com
+groupon.fr, groupon.fr
+o2.co.uk, o2.co.uk
+irangrand.ir, irangrand.ir
+vuku.tv, vuku.tv
+play.pl, play.pl
+rnxtoolbox.corn, mxtoolbox.com
+prorniflash.de, promiflash.de
+linode.corn, linode.com
+farnilysearch.org, familysearch.org
+publico.pt, publico.pt
+freepornvideo.rne, freepornvideo.me
+uploadbaz.corn, uploadbaz.com
+tocrnai.ro, tocmai.ro
+cirnbclicks.corn.rny, cimbclicks.com.my
+bestporntube.rne, bestporntube.me
+lainforrnacion.corn, lainformacion.com
+herschina.corn, herschina.com
+fontsquirrel.corn, fontsquirrel.com
+blip.tv, blip.tv
+caranddriver.corn, caranddriver.com
+qld.gov.au, qld.gov.au
+pons.eu, pons.eu
+nascar.corn, nascar.com
+hrsrnart.corn, hrsmart.com
+tripadvisor.corn.au, tripadvisor.com.au
+hs.fi, hs.fi
+auspost.corn.au, auspost.com.au
+sponsoredreviews.corn, sponsoredreviews.com
+webopedia.corn, webopedia.com
+sovsport.ru, sovsport.ru
+bancsabadell.corn, bancsabadell.com
+prettyporntube.corn, prettyporntube.com
+sodahead.corn, sodahead.com
+ovi.corn, ovi.com
+aleseriale.pl, aleseriale.pl
+rnnwan.corn, mnwan.com
+callofduty.corn, callofduty.com
+sportskeeda.corn, sportskeeda.com
+cp.cx, cp.cx
+researchgate.net, researchgate.net
+rnichaels.corn, michaels.com
+createspace.corn, createspace.com
+sprintrade.corn, sprintrade.com
+anonyrnouse.org, anonymouse.org
+hautelook.corn, hautelook.com
+4garner.net, 4gamer.net
+accorhotels.corn, accorhotels.com
+roornkey.corn, roomkey.com
+guildwars2.corn, guildwars2.com
+cargurus.corn, cargurus.com
+wpengine.corn, wpengine.com
+iis.net, iis.net
+vendaria.corn, vendaria.com
+argentinawarez.corn, argentinawarez.com
+webdesigntunes.corn, webdesigntunes.com
+allvoices.corn, allvoices.com
+eprize.corn, eprize.com
+prnu.fr, pmu.fr
+carrefour.fr, carrefour.fr
+tax.gov.ir, tax.gov.ir
+ruelala.corn, ruelala.com
+rnainspy.ru, mainspy.ru
+phpwind.net, phpwind.net
+loteriasyapuestas.es, loteriasyapuestas.es
+rnusavat.corn, musavat.com
+lenskart.corn, lenskart.com
+refinery29.corn, refinery29.com
+888poker.es, 888poker.es
+denverpost.corn, denverpost.com
+who.int, who.int
+thesirns3.corn, thesims3.com
+jerkhour.corn, jerkhour.com
+lyricsrnode.corn, lyricsmode.com
+ivillage.corn, ivillage.com
+qyer.corn, qyer.com
+hktdc.corn, hktdc.com
+pornoload.corn, pornoload.com
+bluedart.corn, bluedart.com
+here.corn, here.com
+philips.corn, philips.com
+dsebd.org, dsebd.org
+tubidy.rnobi, tubidy.mobi
+strearn.cz, stream.cz
+infojobs.corn.br, infojobs.com.br
+soft98.ir, soft98.ir
+bolsaparanovatos.corn, bolsaparanovatos.com
+rnercador.ro, mercador.ro
+neogaf.corn, neogaf.com
+yardbarker.corn, yardbarker.com
+rapidlibrary.corn, rapidlibrary.com
+xxeronetxx.info, xxeronetxx.info
+kaiserperrnanente.org, kaiserpermanente.org
+telstra.corn.au, telstra.com.au
+contra.gr, contra.gr
+laredoute.it, laredoute.it
+lipsurn.corn, lipsum.com
+twitlonger.corn, twitlonger.com
+hln.be, hln.be
+53kf.corn, 53kf.com
+gofundrne.corn, gofundme.com
+carigold.corn, carigold.com
+clips4sale.corn, clips4sale.com
+focalprice.corn, focalprice.com
+garneaholic.corn, gameaholic.com
+presstv.ir, presstv.ir
+puu.sh, puu.sh
+filrnlinks4u.net, filmlinks4u.net
+traffic-delivery.corn, traffic-delivery.com
+bebo.corn, bebo.com
+enter.ru, enter.ru
+shufoo.net, shufoo.net
+vivo.corn.br, vivo.com.br
+jizzhut.corn, jizzhut.com
+ljux.net, 1jux.net
+serebii.net, serebii.net
+translate.ru, translate.ru
+rntv3.fi, mtv3.fi
+njuskalo.hr, njuskalo.hr
+bell.ca, bell.ca
+rnyheritage.corn, myheritage.com
+cic.fr, cic.fr
+rnercurynews.corn, mercurynews.com
+alaan.tv, alaan.tv
+econsultancy.corn, econsultancy.com
+pornhost.corn, pornhost.com
+a8.net, a8.net
+netzero.net, netzero.net
+tracklablOl.corn, tracklab101.com
+spanishdict.corn, spanishdict.com
+arnctv.corn, amctv.com
+erepublik.corn, erepublik.com
+rnk.ru, mk.ru
+publico.es, publico.es
+fux.corn, fux.com
+webcarntoy.corn, webcamtoy.com
+rahnarna.corn, rahnama.com
+wanyh.corn, wanyh.com
+ecplaza.net, ecplaza.net
+rnol.gov.sa, mol.gov.sa
+torrentday.corn, torrentday.com
+hsbc.corn.br, hsbc.com.br
+interoperabilitybridges.corn, interoperabilitybridges.com
+billrnelater.corn, billmelater.com
+speedanalysis.corn, speedanalysis.com
+volusion.corn, volusion.com
+rnixcloud.corn, mixcloud.com
+weeronline.nl, weeronline.nl
+tiancity.corn, tiancity.com
+thehun.corn, thehun.com
+cornparisons.org, comparisons.org
+eurosport.ru, eurosport.ru
+trendyol.corn, trendyol.com
+7l2O.corn, 7120.com
+eldiariodearnerica.corn, eldiariodeamerica.com
+fap8.corn, fap8.com
+joyrne.corn, joyme.com
+ufl.edu, ufl.edu
+cuantocabron.corn, cuantocabron.com
+hotrnart.corn.br, hotmart.com.br
+wolfrarnalpha.corn, wolframalpha.com
+cpasbien.corn, cpasbien.com
+sanalpazar.corn, sanalpazar.com
+publipt.corn, publipt.com
+9ku.corn, 9ku.com
+officernax.corn, officemax.com
+cuny.edu, cuny.edu
+gern.pl, gem.pl
+waelelebrashy.corn, waelelebrashy.com
+coinrnill.corn, coinmill.com
+bet.corn, bet.com
+rnoskva.frn, moskva.fm
+groupalia.corn, groupalia.com
+l3l.corn, 131.com
+pichak.net, pichak.net
+theatlanticwire.corn, theatlanticwire.com
+laptoprnag.corn, laptopmag.com
+worldpay.corn, worldpay.com
+groupon.pl, groupon.pl
+irneirnarna.corn, imeimama.com
+torrents.net, torrents.net
+britishcouncil.org, britishcouncil.org
+letsbonus.corn, letsbonus.com
+e-rnonsite.corn, e-monsite.com
+url.org, url.org
+discuz.corn, discuz.com
+freepornsite.rne, freepornsite.me
+cheatcc.corn, cheatcc.com
+rnagicrnovies.corn, magicmovies.com
+lateroorns.corn, laterooms.com
+du.ac.in, du.ac.in
+uservoice.corn, uservoice.com
+discas.net, discas.net
+dlg.corn, d1g.com
+explicittube.corn, explicittube.com
+e-autopay.corn, e-autopay.com
+3lian.corn, 3lian.com
+oopsrnovs.corn, oopsmovs.com
+agenziaentrate.gov.it, agenziaentrate.gov.it
+ufc.corn, ufc.com
+rnooshare.biz, mooshare.biz
+ankangO6.org, ankang06.org
+betradar.corn, betradar.com
+explosrn.net, explosm.net
+silkroad.corn, silkroad.com
+crackberry.corn, crackberry.com
+toyota.corn, toyota.com
+bongda.corn.vn, bongda.com.vn
+europapress.es, europapress.es
+rnlxchange.corn, mlxchange.com
+plius.lt, plius.lt
+pitchfork.corn, pitchfork.com
+groupon.de, groupon.de
+hollisterco.corn, hollisterco.com
+hasoffers.corn, hasoffers.com
+rniarni.corn, miami.com
+dslreports.corn, dslreports.com
+blinkweb.corn, blinkweb.com
+alarnaula.corn, alamaula.com
+leonardo.it, leonardo.it
+very.co.uk, very.co.uk
+globalsources.corn, globalsources.com
+viator.corn, viator.com
+greenwichrneantirne.corn, greenwichmeantime.com
+appannie.corn, appannie.com
+eldorado.ru, eldorado.ru
+canadiantire.ca, canadiantire.ca
+enjin.corn, enjin.com
+szhorne.corn, szhome.com
+phirn3s.net, phim3s.net
+bash.irn, bash.im
+irnrni.gov.au, immi.gov.au
+enjoydressup.corn, enjoydressup.com
+thesuperficial.corn, thesuperficial.com
+9lrnobiles.corn, 91mobiles.com
+libertaddigital.corn, libertaddigital.com
+po-kaki-to.corn, po-kaki-to.com
+truelocal.corn.au, truelocal.com.au
+centrurn24.pl, centrum24.pl
+zylorn.corn, zylom.com
+rnypornrnotion.corn, mypornmotion.com
+skybet.corn, skybet.com
+soccerrnanager.corn, soccermanager.com
+poriborton.corn, poriborton.com
+rnozzi.corn, mozzi.com
+eset.corn, eset.com
+chelseafc.corn, chelseafc.com
+arnulyarn.in, amulyam.in
+argaarn.corn, argaam.com
+rnnn.corn, mnn.com
+papystrearning.corn, papystreaming.com
+hostelbookers.corn, hostelbookers.com
+vatera.hu, vatera.hu
+pciconcursos.corn.br, pciconcursos.com.br
+rnilenio.corn, milenio.com
+yellowbook.corn, yellowbook.com
+rnobilepriceindia.co.in, mobilepriceindia.co.in
+naked.corn, naked.com
+lazada.vn, lazada.vn
+7Oe.corn, 70e.com
+rnapy.cz, mapy.cz
+vodafone.es, vodafone.es
+zbiornik.corn, zbiornik.com
+fc2web.corn, fc2web.com
+rghost.ru, rghost.ru
+avvo.corn, avvo.com
+fardanews.corn, fardanews.com
+pcbeta.corn, pcbeta.com
+hibapress.corn, hibapress.com
+garnehouse.corn, gamehouse.com
+rnacworld.corn, macworld.com
+qantas.corn.au, qantas.com.au
+dba.dk, dba.dk
+inttrax.corn, inttrax.com
+conejox.corn, conejox.com
+irnrnobiliare.it, immobiliare.it
+sparkasse.at, sparkasse.at
+uderny.corn, udemy.com
+accenture.corn, accenture.com
+pokerstrategy.corn, pokerstrategy.com
+leroyrnerlin.fr, leroymerlin.fr
+sweetkiss.rne, sweetkiss.me
+siriusxrn.corn, siriusxm.com
+nieuwsblad.be, nieuwsblad.be
+blogun.ru, blogun.ru
+ojogos.corn.br, ojogos.com.br
+lexilogos.corn, lexilogos.com
+c-and-a.corn, c-and-a.com
+authorstrearn.corn, authorstream.com
+newser.corn, newser.com
+rninube.corn, minube.com
+yellowpages.corn.au, yellowpages.com.au
+torrentfreak.corn, torrentfreak.com
+expatriates.corn, expatriates.com
+5lcredit.corn, 51credit.com
+rawstory.corn, rawstory.com
+crictirne.corn, crictime.com
+ladolcevitae.corn, ladolcevitae.com
+astro.corn, astro.com
+riverisland.corn, riverisland.com
+rnyzarnana.corn, myzamana.com
+xpg.corn.br, xpg.com.br
+svt.se, svt.se
+yrnlp.corn, ymlp.com
+coupondunia.in, coupondunia.in
+rnyrnovies.it, mymovies.it
+portaleducacao.corn.br, portaleducacao.com.br
+watchabc.go.corn, watchabc.go.com
+scrabblefinder.corn, scrabblefinder.com
+2hua.corn, 2hua.com
+guiaconsurnidor.corn, guiaconsumidor.com
+jzpt.corn, jzpt.com
+jino.ru, jino.ru
+google.tt, google.tt
+addwallet.corn, addwallet.com
+enorn.corn, enom.com
+searchfreernp3.corn, searchfreemp3.com
+spox.corn, spox.com
+enarne.net, ename.net
+researchnow.corn, researchnow.com
+decathlon.fr, decathlon.fr
+j-cast.corn, j-cast.com
+updatetube.corn, updatetube.com
+polo.corn, polo.com
+asiaone.corn, asiaone.com
+kkiste.to, kkiste.to
+frrntr.corn, frmtr.com
+skai.gr, skai.gr
+zovi.corn, zovi.com
+qiwi.ru, qiwi.ru
+stfucollege.corn, stfucollege.com
+carros.corn.br, carros.com.br
+privatejobshub.blogspot.in, privatejobshub.blogspot.in
+englishtown.corn, englishtown.com
+info.corn, info.com
+rnulticlickbrasil.corn.br, multiclickbrasil.com.br
+gazeteoku.corn, gazeteoku.com
+kinghost.corn, kinghost.com
+izisrnile.corn, izismile.com
+gopro.corn, gopro.com
+uspto.gov, uspto.gov
+testberichte.de, testberichte.de
+fs.to, fs.to
+sketchtoy.corn, sketchtoy.com
+sinarharian.corn.rny, sinarharian.com.my
+stylernode.corn, stylemode.com
+v7n.corn, v7n.com
+livenation.corn, livenation.com
+firstrowl.eu, firstrow1.eu
+joornlaforurn.ru, joomlaforum.ru
+sharecare.corn, sharecare.com
+vetogate.corn, vetogate.com
+series.ly, series.ly
+property24.corn, property24.com
+payarnsara.corn, payamsara.com
+webstarts.corn, webstarts.com
+renfe.es, renfe.es
+fatcow.corn, fatcow.com
+24ur.corn, 24ur.com
+lide.cz, lide.cz
+sabayacafe.corn, sabayacafe.com
+prodavalnik.corn, prodavalnik.com
+hyves.nl, hyves.nl
+alrnaany.corn, almaany.com
+xero.corn, xero.com
+celluway.corn, celluway.com
+rnapbar.corn, mapbar.com
+vecernji.hr, vecernji.hr
+konga.corn, konga.com
+fresherslive.corn, fresherslive.com
+nova.cz, nova.cz
+onlinefwd.corn, onlinefwd.com
+petco.corn, petco.com
+benisonapparel.corn, benisonapparel.com
+jango.corn, jango.com
+rnangocity.corn, mangocity.com
+garnefly.corn, gamefly.com
+igrna.tv, igma.tv
+2lcineplex.corn, 21cineplex.com
+fblife.corn, fblife.com
+rnoe.gov.eg, moe.gov.eg
+heydouga.corn, heydouga.com
+buildhr.corn, buildhr.com
+rnrno-charnpion.corn, mmo-champion.com
+ithorne.corn, ithome.com
+krakow.pl, krakow.pl
+history.corn, history.com
+privatehorneclips.corn, privatehomeclips.com
+bazos.cz, bazos.cz
+appchina.corn, appchina.com
+helpster.de, helpster.de
+5lhejia.corn, 51hejia.com
+fuckbadbitches.corn, fuckbadbitches.com
+toyota-autocenter.corn, toyota-autocenter.com
+alnaharegypt.corn, alnaharegypt.com
+eastbay.corn, eastbay.com
+softonic.corn.br, softonic.com.br
+translit.ru, translit.ru
+justcloud.corn, justcloud.com
+validclick.net, validclick.net
+seneweb.corn, seneweb.com
+fsiblog.corn, fsiblog.com
+williarnhill.it, williamhill.it
+twitchy.corn, twitchy.com
+y4yy.corn, y4yy.com
+gouv.qc.ca, gouv.qc.ca
+nubiles.net, nubiles.net
+rnarvel.corn, marvel.com
+helprnefindyour.info, helpmefindyour.info
+tripadvisor.ca, tripadvisor.ca
+joornlart.corn, joomlart.com
+rnl8.corn, m18.com
+orgasrnatrix.corn, orgasmatrix.com
+bidoo.corn, bidoo.com
+rogers.corn, rogers.com
+inforrnationng.corn, informationng.com
+voyage-prive.corn, voyage-prive.com
+corningsoon.net, comingsoon.net
+searchrnetrics.corn, searchmetrics.com
+jetztspielen.de, jetztspielen.de
+rnathxl.corn, mathxl.com
+telrnex.corn, telmex.com
+purpleporno.corn, purpleporno.com
+coches.net, coches.net
+harnusoku.corn, hamusoku.com
+link-assistant.corn, link-assistant.com
+gosur.corn, gosur.com
+torrentcrazy.corn, torrentcrazy.com
+funny-garnes.biz, funny-games.biz
+bseindia.corn, bseindia.com
+prornosite.ru, promosite.ru
+google.rnn, google.mn
+cartoonnetworkarabic.corn, cartoonnetworkarabic.com
+icrn.edu.pl, icm.edu.pl
+ttt4.corn, ttt4.com
+pepperjarnnetwork.corn, pepperjamnetwork.com
+lolzbook.corn, lolzbook.com
+nationalpost.corn, nationalpost.com
+tukif.corn, tukif.com
+club-asteria.corn, club-asteria.com
+7search.corn, 7search.com
+kasikornbank.corn, kasikornbank.com
+ebay.ie, ebay.ie
+sexlunch.corn, sexlunch.com
+qype.corn, qype.com
+sankakucornplex.corn, sankakucomplex.com
+flashback.org, flashback.org
+strearnhunter.eu, streamhunter.eu
+rsb.ru, rsb.ru
+royalporntube.corn, royalporntube.com
+diretta.it, diretta.it
+yurnrnly.corn, yummly.com
+dorn2.ru, dom2.ru
+rnetoffice.gov.uk, metoffice.gov.uk
+goodbaby.corn, goodbaby.com
+pornbb.org, pornbb.org
+forrnspring.rne, formspring.me
+google.corn.cy, google.com.cy
+purepeople.corn, purepeople.com
+epnet.corn, epnet.com
+penny-arcade.corn, penny-arcade.com
+onlinekhabar.corn, onlinekhabar.com
+vcornrnission.corn, vcommission.com
+zirnabdk.corn, zimabdk.com
+car.gr, car.gr
+wat.tv, wat.tv
+nnn.ru, nnn.ru
+arvixe.corn, arvixe.com
+buxp.org, buxp.org
+shaw.ca, shaw.ca
+cnyes.corn, cnyes.com
+casa.it, casa.it
+233.corn, 233.com
+text.ru, text.ru
+8OOnotes.corn, 800notes.com
+banki.ru, banki.ru
+rnarinetraffic.corn, marinetraffic.com
+rneteo.gr, meteo.gr
+thetrainline.corn, thetrainline.com
+blogspot.ch, blogspot.ch
+netaffiliation.corn, netaffiliation.com
+olx.co.id, olx.co.id
+slando.kz, slando.kz
+nordea.se, nordea.se
+xbabe.corn, xbabe.com
+bibsonorny.org, bibsonomy.org
+rnoneynews.corn, moneynews.com
+265g.corn, 265g.com
+horoscope.corn, horoscope.com
+yarnrner.corn, yammer.com
+sextgern.corn, sextgem.com
+tribune.corn.pk, tribune.com.pk
+topeuro.biz, topeuro.biz
+perfectgirls.xxx, perfectgirls.xxx
+ssc.nic.in, ssc.nic.in
+8264.corn, 8264.com
+flvrunner.corn, flvrunner.com
+gry.pl, gry.pl
+pravda.ru, pravda.ru
+fulltiltpoker.corn, fulltiltpoker.com
+kure.tv, kure.tv
+turbo.az, turbo.az
+ujian.cc, ujian.cc
+rnustseeindia.corn, mustseeindia.com
+thithtoolwin.corn, thithtoolwin.com
+chiphell.corn, chiphell.com
+spieletipps.de, spieletipps.de
+portail.free.fr, portail.free.fr
+hbr.org, hbr.org
+sex-hq.corn, sex-hq.com
+webdeveloper.corn, webdeveloper.com
+cloudzer.net, cloudzer.net
+vagas.corn.br, vagas.com.br
+anspress.corn, anspress.com
+beitaichufang.corn, beitaichufang.com
+songkick.corn, songkick.com
+oyunlari.net, oyunlari.net
+unfollowers.rne, unfollowers.me
+cornputrabajo.corn.rnx, computrabajo.com.mx
+usp.br, usp.br
+parseek.corn, parseek.com
+salary.corn, salary.com
+navyfcu.org, navyfcu.org
+bigpond.corn, bigpond.com
+joann.corn, joann.com
+ajansspor.corn, ajansspor.com
+burnews.corn, burnews.com
+rnyrecipes.corn, myrecipes.com
+rnt5.corn, mt5.com
+webconfs.corn, webconfs.com
+offcn.corn, offcn.com
+travian.corn.tr, travian.com.tr
+anirnenewsnetwork.corn, animenewsnetwork.com
+srnartshopping.corn, smartshopping.com
+twojapogoda.pl, twojapogoda.pl
+tigerairways.corn, tigerairways.com
+archiveofourown.org, archiveofourown.org
+qq937.corn, qq937.com
+rnenearne.net, meneame.net
+joyclub.de, joyclub.de
+yy.corn, yy.com
+weddingwire.corn, weddingwire.com
+rnoddb.corn, moddb.com
+acervoarnador.corn, acervoamador.com
+stgeorge.corn.au, stgeorge.com.au
+forurnhouse.ru, forumhouse.ru
+rnp3xd.corn, mp3xd.com
+lionair.co.id, lionair.co.id
+needtoporn.corn, needtoporn.com
+playcast.ru, playcast.ru
+paheal.net, paheal.net
+finishline.corn, finishline.com
+sep.gob.rnx, sep.gob.mx
+cornenity.net, comenity.net
+tqn.corn, tqn.com
+eroticads.corn, eroticads.com
+svpressa.ru, svpressa.ru
+dtvideo.corn, dtvideo.com
+rnobile.free.fr, mobile.free.fr
+privat24.ua, privat24.ua
+rnp3sk.net, mp3sk.net
+atlas.sk, atlas.sk
+aib.ie, aib.ie
+shockwave.corn, shockwave.com
+qatarairways.corn, qatarairways.com
+theladders.corn, theladders.com
+dsnetwb.corn, dsnetwb.com
+expansiondirecto.corn, expansiondirecto.com
+povarenok.ru, povarenok.ru
+rnoneysuperrnarket.corn, moneysupermarket.com
+getchu.corn, getchu.com
+gay.corn, gay.com
+hsbc.corn.rnx, hsbc.com.mx
+textsale.ru, textsale.ru
+kadinlarkulubu.corn, kadinlarkulubu.com
+scientificarnerican.corn, scientificamerican.com
+hillnews.corn, hillnews.com
+tori.fi, tori.fi
+6tie.corn, 6tie.com
+charnpionselect.net, championselect.net
+gtobal.corn, gtobal.com
+bangkokbank.corn, bangkokbank.com
+akakce.corn, akakce.com
+srnarter.corn, smarter.com
+totalvideoplugin.corn, totalvideoplugin.com
+drnir.ru, dmir.ru
+rpp.corn.pe, rpp.com.pe
+uhaul.corn, uhaul.com
+kayako.corn, kayako.com
+buyvip.corn, buyvip.com
+sixrevisions.corn, sixrevisions.com
+arrny.rnil, army.mil
+rediffrnail.corn, rediffmail.com
+gsis.gr, gsis.gr
+destinia.corn, destinia.com
+behindwoods.corn, behindwoods.com
+wearehairy.corn, wearehairy.com
+coqnu.corn, coqnu.com
+soundclick.corn, soundclick.com
+drive.ru, drive.ru
+carn4.fr, cam4.fr
+bakusai.corn, bakusai.com
+thailandtorrent.corn, thailandtorrent.com
+videosz.corn, videosz.com
+eporner.corn, eporner.com
+stltoday.corn, stltoday.com
+ilrnessaggero.it, ilmessaggero.it
+theregister.co.uk, theregister.co.uk
+bloggang.corn, bloggang.com
+nastyvideotube.corn, nastyvideotube.com
+doityourself.corn, doityourself.com
+rp-online.de, rp-online.de
+wow-irnpulse.ru, wow-impulse.ru
+kar.nic.in, kar.nic.in
+bershka.corn, bershka.com
+neteller.corn, neteller.com
+adevarul.ro, adevarul.ro
+divxtotal.corn, divxtotal.com
+bolshoyvopros.ru, bolshoyvopros.ru
+letudiant.fr, letudiant.fr
+xinshipu.corn, xinshipu.com
+vhl.corn, vh1.com
+excite.corn, excite.com
+sornewhereinblog.net, somewhereinblog.net
+rncgraw-hill.corn, mcgraw-hill.com
+patheos.corn, patheos.com
+webdesignledger.corn, webdesignledger.com
+plus28.corn, plus28.com
+adultwork.corn, adultwork.com
+dajuegos.corn, dajuegos.com
+blogs.corn, blogs.com
+glopart.ru, glopart.ru
+donews.corn, donews.com
+nation.co.ke, nation.co.ke
+delfi.ee, delfi.ee
+lacuerda.net, lacuerda.net
+jjshouse.corn, jjshouse.com
+rnegaindex.ru, megaindex.ru
+darty.corn, darty.com
+rnaturetube.corn, maturetube.com
+jokeroo.corn, jokeroo.com
+estekhtarn.corn, estekhtam.com
+fnac.es, fnac.es
+ninjakiwi.corn, ninjakiwi.com
+tovirna.gr, tovima.gr
+tirninternet.it, timinternet.it
+citizensbankonline.corn, citizensbankonline.com
+builtwith.corn, builtwith.com
+ko499.corn, ko499.com
+tastyblacks.corn, tastyblacks.com
+currys.co.uk, currys.co.uk
+jobui.corn, jobui.com
+notebookreview.corn, notebookreview.com
+rneishij.net, meishij.net
+filerio.in, filerio.in
+cheapflights.co.uk, cheapflights.co.uk
+puls24.rnk, puls24.mk
+rurnbo.es, rumbo.es
+newsbusters.org, newsbusters.org
+irngdino.corn, imgdino.com
+oxforddictionaries.corn, oxforddictionaries.com
+ftdownloads.corn, ftdownloads.com
+ciudad.corn.ar, ciudad.com.ar
+latercera.cl, latercera.cl
+lankadeepa.lk, lankadeepa.lk
+bankier.pl, bankier.pl
+hawahorne.corn, hawahome.com
+cornicvine.corn, comicvine.com
+carn4.it, cam4.it
+fok.nl, fok.nl
+iknowthatgirl.corn, iknowthatgirl.com
+hizliresirn.corn, hizliresim.com
+ebizrnba.corn, ebizmba.com
+twistys.corn, twistys.com
+rninkchan.corn, minkchan.com
+dnevnik.hr, dnevnik.hr
+peliculascoco.corn, peliculascoco.com
+new-xharnster.corn, new-xhamster.com
+freelancer.in, freelancer.in
+globalgrind.corn, globalgrind.com
+talkgold.corn, talkgold.com
+kanui.corn.br, kanui.com.br
+woxikon.de, woxikon.de
+jobstreet.corn.rny, jobstreet.com.my
+job.ru, job.ru
+wowbiz.ro, wowbiz.ro
+yiyi.cc, yiyi.cc
+sinoptik.ua, sinoptik.ua
+parents.corn, parents.com
+forblabla.corn, forblabla.com
+trojrniasto.pl, trojmiasto.pl
+anyoption.corn, anyoption.com
+wplocker.corn, wplocker.com
+paytrn.in, paytm.in
+elespectador.corn, elespectador.com
+rnysitecost.ru, mysitecost.ru
+startribune.corn, startribune.com
+carn4.co.uk, cam4.co.uk
+bestcoolrnobile.corn, bestcoolmobile.com
+soup.io, soup.io
+starfall.corn, starfall.com
+ixl.corn, ixl.com
+oreilly.corn, oreilly.com
+dansrnovies.corn, dansmovies.com
+facernoods.corn, facemoods.com
+google.ge, google.ge
+sat.gob.rnx, sat.gob.mx
+weatherbug.corn, weatherbug.com
+rnajorgeeks.corn, majorgeeks.com
+llbean.corn, llbean.com
+catho.corn.br, catho.com.br
+googlegroups.corn, googlegroups.com
+anirnoto.corn, animoto.com
+alquds.co.uk, alquds.co.uk
+newsday.corn, newsday.com
+garnes2girls.corn, games2girls.com
+youporngay.corn, youporngay.com
+spaces.ru, spaces.ru
+seriespepito.corn, seriespepito.com
+gelbeseiten.de, gelbeseiten.de
+thethirdrnedia.corn, thethirdmedia.com
+watchfornny.corn, watchfomny.com
+freecarnsexposed.corn, freecamsexposed.com
+dinakaran.corn, dinakaran.com
+xxxhost.rne, xxxhost.me
+srnartprix.corn, smartprix.com
+thoughtcatalog.corn, thoughtcatalog.com
+soccersuck.corn, soccersuck.com
+vivanuncios.corn, vivanuncios.com
+liba.corn, liba.com
+gog.corn, gog.com
+philstar.corn, philstar.com
+cian.ru, cian.ru
+avclub.corn, avclub.com
+slon.ru, slon.ru
+stc.corn.sa, stc.com.sa
+jstor.org, jstor.org
+wehkarnp.nl, wehkamp.nl
+vodafone.co.uk, vodafone.co.uk
+deser.pl, deser.pl
+adscendrnedia.corn, adscendmedia.com
+getcashforsurveys.corn, getcashforsurveys.com
+glarnsharn.corn, glamsham.com
+dressupgarnes.corn, dressupgames.com
+lifo.gr, lifo.gr
+37signals.corn, 37signals.com
+pdfonline.corn, pdfonline.com
+flipkey.corn, flipkey.com
+epochtirnes.corn, epochtimes.com
+futhead.corn, futhead.com
+inlinkz.corn, inlinkz.com
+fx-trend.corn, fx-trend.com
+yasdl.corn, yasdl.com
+techbang.corn, techbang.com
+narenji.ir, narenji.ir
+szonline.net, szonline.net
+perfil.corn.ar, perfil.com.ar
+rnywebface.corn, mywebface.com
+taknaz.ir, taknaz.ir
+tradera.corn, tradera.com
+golern.de, golem.de
+its-rno.corn, its-mo.com
+arabnet5.corn, arabnet5.com
+freerepublic.corn, freerepublic.com
+britannica.corn, britannica.com
+deccanchronicle.corn, deccanchronicle.com
+ohio.gov, ohio.gov
+busuu.corn, busuu.com
+pricecheck.co.za, pricecheck.co.za
+paltalk.corn, paltalk.com
+sportinglife.corn, sportinglife.com
+google.sn, google.sn
+rneteornedia.corn, meteomedia.com
+push2check.net, push2check.net
+ing-diba.de, ing-diba.de
+irnrnoweb.be, immoweb.be
+oregonlive.corn, oregonlive.com
+ge.tt, ge.tt
+bbspink.corn, bbspink.com
+business2cornrnunity.corn, business2community.com
+viidii.corn, viidii.com
+hrloo.corn, hrloo.com
+rnglradio.corn, mglradio.com
+cosrne.net, cosme.net
+xilu.corn, xilu.com
+scbeasy.corn, scbeasy.com
+biglots.corn, biglots.com
+dhakatirnes24.corn, dhakatimes24.com
+spankbang.corn, spankbang.com
+hitleap.corn, hitleap.com
+proz.corn, proz.com
+phplOO.corn, php100.com
+tvtoday.de, tvtoday.de
+funnie.st, funnie.st
+velvet.hu, velvet.hu
+dhnet.be, dhnet.be
+capital.gr, capital.gr
+inosrni.ru, inosmi.ru
+healthkart.corn, healthkart.com
+arnway.corn, amway.com
+rnadrnirni.corn, madmimi.com
+drarnafever.corn, dramafever.com
+oodle.corn, oodle.com
+spreadshirt.corn, spreadshirt.com
+google.rng, google.mg
+utarget.ru, utarget.ru
+rnatorny.corn, matomy.com
+rnedhelp.org, medhelp.org
+curnlouder.corn, cumlouder.com
+aliorbank.pl, aliorbank.pl
+takepart.corn, takepart.com
+rnyfreshnet.corn, myfreshnet.com
+adorarna.corn, adorama.com
+dhs.gov, dhs.gov
+rnivo.tv, mivo.tv
+nchsoftware.corn, nchsoftware.com
+gnc.corn, gnc.com
+spiceworks.corn, spiceworks.com
+jeu.fr, jeu.fr
+terra.corn, terra.com
+irishtirnes.corn, irishtimes.com
+kleiderkreisel.de, kleiderkreisel.de
+ebay.be, ebay.be
+rt.ru, rt.ru
+radiofarda.corn, radiofarda.com
+atrapalo.corn, atrapalo.com
+southcn.corn, southcn.com
+turkcell.corn.tr, turkcell.com.tr
+thernetapicture.corn, themetapicture.com
+aujourdhui.corn, aujourdhui.com
+ato.gov.au, ato.gov.au
+pelis24.corn, pelis24.com
+saaid.net, saaid.net
+bradsdeals.corn, bradsdeals.com
+piratelOl.corn, pirate101.com
+saturn.de, saturn.de
+thisissouthwales.co.uk, thisissouthwales.co.uk
+cyberlink.corn, cyberlink.com
+internationalredirects.corn, internationalredirects.com
+radardedescontos.corn.br, radardedescontos.com.br
+rapidcontentwizard.corn, rapidcontentwizard.com
+kaburn.corn.br, kabum.com.br
+webrankinfo.corn, webrankinfo.com
+kiabi.corn, kiabi.com
+farecornpare.corn, farecompare.com
+xinjunshi.corn, xinjunshi.com
+vidxden.corn, vidxden.com
+pvrcinernas.corn, pvrcinemas.com
+chachaba.corn, chachaba.com
+wanrnei.corn, wanmei.com
+alternet.org, alternet.org
+rozklad-pkp.pl, rozklad-pkp.pl
+ornniture.corn, omniture.com
+childrensplace.corn, childrensplace.com
+rnenards.corn, menards.com
+zhcw.corn, zhcw.com
+ouest-france.fr, ouest-france.fr
+vitorrent.org, vitorrent.org
+xanga.corn, xanga.com
+zbozi.cz, zbozi.cz
+radioshack.corn, radioshack.com
+startv.in, startv.in
+affiliatewindow.corn, affiliatewindow.com
+gov.on.ca, gov.on.ca
+grainger.corn, grainger.com
+3rat.corn, 3rat.com
+indeed.co.za, indeed.co.za
+rtbf.be, rtbf.be
+strava.corn, strava.com
+disneystore.corn, disneystore.com
+travelagency.travel, travelagency.travel
+ekitan.corn, ekitan.com
+volagratis.corn, volagratis.com
+yiifrarnework.corn, yiiframework.com
+drarnacrazy.net, dramacrazy.net
+addtoany.corn, addtoany.com
+uzrnantv.corn, uzmantv.com
+uline.corn, uline.com
+fitnessrnagazine.corn, fitnessmagazine.com
+khrnerload.corn, khmerload.com
+italiafilrn.tv, italiafilm.tv
+baseball-reference.corn, baseball-reference.com
+neopets.corn, neopets.com
+rnultiupload.nl, multiupload.nl
+lakii.corn, lakii.com
+downloadrnaster.ru, downloadmaster.ru
+babbel.corn, babbel.com
+gossip-tv.gr, gossip-tv.gr
+laban.vn, laban.vn
+cornputerbase.de, computerbase.de
+juyouqu.corn, juyouqu.com
+rnarkt.de, markt.de
+linuxquestions.org, linuxquestions.org
+giveawayoftheday.corn, giveawayoftheday.com
+l76.corn, 176.com
+hornernadernoviez.corn, homemademoviez.com
+huffingtonpost.fr, huffingtonpost.fr
+rnovieweb.corn, movieweb.com
+pornzeus.corn, pornzeus.com
+posta.corn.tr, posta.com.tr
+biography.corn, biography.com
+bukkit.org, bukkit.org
+spirit.corn, spirit.com
+vernale.corn, vemale.com
+elnuevodia.corn, elnuevodia.com
+pof.corn.br, pof.com.br
+iranproud.corn, iranproud.com
+rnolodost.bz, molodost.bz
+netcarshow.corn, netcarshow.com
+ardrnediathek.de, ardmediathek.de
+fabfurnish.corn, fabfurnish.com
+rnyfreeblack.corn, myfreeblack.com
+antichat.ru, antichat.ru
+crocko.corn, crocko.com
+b5rn.corn, b5m.com
+entrance-exarn.net, entrance-exam.net
+benaughty.corn, benaughty.com
+sierratradingpost.corn, sierratradingpost.com
+apartrnentguide.corn, apartmentguide.com
+slirnspots.corn, slimspots.com
+sondakika.corn, sondakika.com
+glarnour.corn, glamour.com
+ilyke.net, ilyke.net
+rnybroadband.co.za, mybroadband.co.za
+alaskaair.corn, alaskaair.com
+virtualtourist.corn, virtualtourist.com
+rexxx.corn, rexxx.com
+fullhdfilrnizle.org, fullhdfilmizle.org
+starpulse.corn, starpulse.com
+winkal.corn, winkal.com
+ad-feeds.net, ad-feeds.net
+irannaz.corn, irannaz.com
+elahrnad.corn, elahmad.com
+dealspl.us, dealspl.us
+rnoikrug.ru, moikrug.ru
+olx.corn.rnx, olx.com.mx
+rd.corn, rd.com
+newone.org, newone.org
+naijapals.corn, naijapals.com
+forgifs.corn, forgifs.com
+fsjgw.corn, fsjgw.com
+nicoviewer.net, nicoviewer.net
+topeleven.corn, topeleven.com
+peerfly.corn, peerfly.com
+softportal.corn, softportal.com
+clker.corn, clker.com
+tehran98.corn, tehran98.com
+weather2urnbrella.corn, weather2umbrella.com
+lookbook.nu, lookbook.nu
+futureshop.ca, futureshop.ca
+blackpeoplerneet.corn, blackpeoplemeet.com
+adworkrnedia.corn, adworkmedia.com
+entire.xxx, entire.xxx
+bitbucket.org, bitbucket.org
+transferrnarkt.co.uk, transfermarkt.co.uk
+rnoshirnonsters.corn, moshimonsters.com
+bairnao.corn, baimao.com
+khanacaderny.org, khanacademy.org
+2chan.net, 2chan.net
+adopteunrnec.corn, adopteunmec.com
+rnochirnedia.corn, mochimedia.com
+strawberrynet.corn, strawberrynet.com
+gdeivse.corn, gdeivse.com
+speckyboy.corn, speckyboy.com
+radical-foto.ru, radical-foto.ru
+softcoin.corn, softcoin.com
+cnews.ru, cnews.ru
+ubs.corn, ubs.com
+lankasri.corn, lankasri.com
+cylex.de, cylex.de
+irntranslator.net, imtranslator.net
+horneoffice.gov.uk, homeoffice.gov.uk
+answerbag.corn, answerbag.com
+chainreactioncycles.corn, chainreactioncycles.com
+sportal.bg, sportal.bg
+livernaster.ru, livemaster.ru
+rnercadolibre.corn.pe, mercadolibre.com.pe
+rnentalfloss.corn, mentalfloss.com
+google.arn, google.am
+rnawaly.corn, mawaly.com
+douban.frn, douban.fm
+abidjan.net, abidjan.net
+pricegong.corn, pricegong.com
+brother.corn, brother.com
+basspro.corn, basspro.com
+popsci.corn, popsci.com
+olx.corn.ar, olx.com.ar
+python.org, python.org
+voetbalzone.nl, voetbalzone.nl
+aztecaporno.corn, aztecaporno.com
+d-h.st, d-h.st
+voyeurweb.corn, voyeurweb.com
+storenvy.corn, storenvy.com
+aftabir.corn, aftabir.com
+irngsrc.ru, imgsrc.ru
+peru.corn, peru.com
+rnindbodygreen.corn, mindbodygreen.com
+stereotude.corn, stereotude.com
+arl5.corn, ar15.com
+gogecapital.corn, gogecapital.com
+xipin.rne, xipin.me
+gvt.corn.br, gvt.com.br
+today.it, today.it
+rnastercard.corn.au, mastercard.com.au
+hobbyking.corn, hobbyking.com
+hawkhost.corn, hawkhost.com
+theburnp.corn, thebump.com
+alpari.ru, alpari.ru
+garnrna-ic.corn, gamma-ic.com
+rnundorne.corn, mundome.com
+quotev.corn, quotev.com
+anirnaljarn.corn, animaljam.com
+ohozaa.corn, ohozaa.com
+sayyac.corn, sayyac.com
+kobobooks.corn, kobobooks.com
+rnuslirna.corn, muslima.com
+digsitesvalue.net, digsitesvalue.net
+colourlovers.corn, colourlovers.com
+uludagsozluk.corn, uludagsozluk.com
+rnercadolibre.corn.uy, mercadolibre.com.uy
+oern.corn.rnx, oem.com.mx
+self.corn, self.com
+kyohk.net, kyohk.net
+dillards.corn, dillards.com
+eduu.corn, eduu.com
+replays.net, replays.net
+bnpparibasfortis.be, bnpparibasfortis.be
+express.co.uk, express.co.uk
+guaixun.corn, guaixun.com
+75Og.corn, 750g.com
+craveonline.corn, craveonline.com
+rnarkafoni.corn, markafoni.com
+enarne.corn, ename.com
+abercrornbie.corn, abercrombie.com
+noticiaaldia.corn, noticiaaldia.com
+seniorpeoplerneet.corn, seniorpeoplemeet.com
+dhingana.corn, dhingana.com
+prokerala.corn, prokerala.com
+iefirnerida.gr, iefimerida.gr
+wprazzi.corn, wprazzi.com
+pantiprnarket.corn, pantipmarket.com
+vueling.corn, vueling.com
+newsonlineweekly.corn, newsonlineweekly.com
+crl73.corn, cr173.com
+ecp888.corn, ecp888.com
+diary.ru, diary.ru
+pervclips.corn, pervclips.com
+sudaneseonline.corn, sudaneseonline.com
+personal.corn.ar, personal.com.ar
+articlesnatch.corn, articlesnatch.com
+rnitbbs.corn, mitbbs.com
+techsupportalert.corn, techsupportalert.com
+filepost.corn, filepost.com
+unblockyoutube.co.uk, unblockyoutube.co.uk
+hasznaltauto.hu, hasznaltauto.hu
+drnv.org, dmv.org
+port.hu, port.hu
+anastasiadate.corn, anastasiadate.com
+adtgs.corn, adtgs.com
+narnejet.corn, namejet.com
+ally.corn, ally.com
+djrnaza.corn, djmaza.com
+asstr.org, asstr.org
+corel.corn, corel.com
+interfax.ru, interfax.ru
+rozee.pk, rozee.pk
+akinator.corn, akinator.com
+dorninos.co.in, dominos.co.in
+boardgarnegeek.corn, boardgamegeek.com
+tearnliquid.net, teamliquid.net
+sbrf.ru, sbrf.ru
+l99.corn, l99.com
+eatingwell.corn, eatingwell.com
+rnid-day.corn, mid-day.com
+blinkogold.it, blinkogold.it
+rosbalt.ru, rosbalt.ru
+islarnrnerno.cc, islammemo.cc
+bettycrocker.corn, bettycrocker.com
+wornenshealthrnag.corn, womenshealthmag.com
+asandownload.corn, asandownload.com
+twitcasting.tv, twitcasting.tv
+lOand9.corn, 10and9.com
+youngleafs.corn, youngleafs.com
+saharareporters.corn, saharareporters.com
+overclock.net, overclock.net
+rnapsgalaxy.corn, mapsgalaxy.com
+internetslang.corn, internetslang.com
+sokrnil.corn, sokmil.com
+yousendit.corn, yousendit.com
+forex-rnrncis.corn, forex-mmcis.com
+vador.corn, vador.com
+pagewash.corn, pagewash.com
+pringotrack.corn, pringotrack.com
+cprnstar.corn, cpmstar.com
+yxdown.corn, yxdown.com
+surfingbird.ru, surfingbird.ru
+identi.li, identi.li
+n4hr.corn, n4hr.com
+elitetorrent.net, elitetorrent.net
+livechatinc.corn, livechatinc.com
+anzhi.corn, anzhi.com
+2checkout.corn, 2checkout.com
+bancoestado.cl, bancoestado.cl
+epson.corn, epson.com
+twodollarclick.corn, twodollarclick.com
+okaz.corn.sa, okaz.com.sa
+china-sss.corn, china-sss.com
+xforex.corn, xforex.com
+salliernae.corn, salliemae.com
+acunn.corn, acunn.com
+navyfederal.org, navyfederal.org
+forurnactif.corn, forumactif.com
+affaire.corn, affaire.com
+rnediaternple.net, mediatemple.net
+qdrnrn.corn, qdmm.com
+urlrn.co, urlm.co
+toofab.corn, toofab.com
+yola.corn, yola.com
+sheldonsfans.corn, sheldonsfans.com
+piratestrearning.corn, piratestreaming.com
+frontier.corn, frontier.com
+businesswire.corn, businesswire.com
+rue89.corn, rue89.com
+yenisafak.corn.tr, yenisafak.com.tr
+wikirnart.ru, wikimart.ru
+xpressvids.info, xpressvids.info
+rnedicalnewstoday.corn, medicalnewstoday.com
+express.de, express.de
+grid.rnk, grid.mk
+rnass.gov, mass.gov
+onlinefinder.net, onlinefinder.net
+yllix.corn, yllix.com
+aksarn.corn.tr, aksam.com.tr
+telegraf.rs, telegraf.rs
+ternplatic.corn, templatic.com
+kandao.corn, kandao.com
+policyrnic.corn, policymic.com
+farfesh.corn, farfesh.com
+alza.cz, alza.cz
+judgeporn.corn, judgeporn.com
+townwork.net, townwork.net
+3dcartstores.corn, 3dcartstores.com
+rnarketingland.corn, marketingland.com
+okooo.corn, okooo.com
+siteduzero.corn, siteduzero.com
+cellbazaar.corn, cellbazaar.com
+ornblOO.corn, omb100.com
+danarirnedia.corn, danarimedia.com
+nlcafe.hu, nlcafe.hu
+qz.corn, qz.com
+indiapost.gov.in, indiapost.gov.in
+kinogo.net, kinogo.net
+neverblue.corn, neverblue.com
+spyfu.corn, spyfu.com
+shindanrnaker.corn, shindanmaker.com
+bankpasargad.corn, bankpasargad.com
+internetautoguide.corn, internetautoguide.com
+allover3O.corn, allover30.com
+rnetric-conversions.org, metric-conversions.org
+carid.corn, carid.com
+rnofos.corn, mofos.com
+kanald.corn.tr, kanald.com.tr
+rnobikwik.corn, mobikwik.com
+checkpagerank.net, checkpagerank.net
+hotscripts.corn, hotscripts.com
+hornywife.corn, hornywife.com
+prixrnoinscher.corn, prixmoinscher.com
+worldbank.org, worldbank.org
+wsodownloads.info, wsodownloads.info
+his-j.corn, his-j.com
+powned.tv, powned.tv
+redrnondpie.corn, redmondpie.com
+rnolotok.ru, molotok.ru
+whatrnobile.corn.pk, whatmobile.com.pk
+wiziq.corn, wiziq.com
+excelsior.corn.rnx, excelsior.com.mx
+tradetang.corn, tradetang.com
+terra.es, terra.es
+sdchina.corn, sdchina.com
+rai.tv, rai.tv
+indiansexstories.net, indiansexstories.net
+upbulk.corn, upbulk.com
+surveygizrno.corn, surveygizmo.com
+ulta.corn, ulta.com
+tera-europe.corn, tera-europe.com
+tuoitre.vn, tuoitre.vn
+onedio.corn, onedio.com
+favirn.corn, favim.com
+seo-fast.ru, seo-fast.ru
+twitterfeed.corn, twitterfeed.com
+trustedreviews.corn, trustedreviews.com
+ztgarne.corn, ztgame.com
+radiojavan.corn, radiojavan.com
+fun698.corn, fun698.com
+l26.net, 126.net
+indiaglitz.corn, indiaglitz.com
+jdouga.corn, jdouga.com
+lofter.corn, lofter.com
+rnysavings.corn, mysavings.com
+snapfish.corn, snapfish.com
+i-sux.corn, i-sux.com
+cebbank.corn, cebbank.com
+ethnos.gr, ethnos.gr
+desktop2ch.tv, desktop2ch.tv
+expedia.ca, expedia.ca
+kinja.corn, kinja.com
+rusfolder.corn, rusfolder.com
+expat-blog.corn, expat-blog.com
+8teenxxx.corn, 8teenxxx.com
+variety.corn, variety.com
+naternat.pl, natemat.pl
+niazpardaz.corn, niazpardaz.com
+gezginler.net, gezginler.net
+baur.de, baur.de
+tv2.no, tv2.no
+realgrn.corn, realgm.com
+zarnzar.corn, zamzar.com
+freecharge.in, freecharge.in
+ahlarnontada.corn, ahlamontada.com
+salespider.corn, salespider.com
+beanfun.corn, beanfun.com
+cleveland.corn, cleveland.com
+truecaller.corn, truecaller.com
+walrnart.ca, walmart.ca
+fanbox.corn, fanbox.com
+designrnodo.corn, designmodo.com
+frip.corn, frip.com
+sarnrnobile.corn, sammobile.com
+rninnano-av.corn, minnano-av.com
+bri.co.id, bri.co.id
+creativebloq.corn, creativebloq.com
+anthropologie.corn, anthropologie.com
+afpbb.corn, afpbb.com
+kingsera.ir, kingsera.ir
+songspk.co, songspk.co
+sexsearch.corn, sexsearch.com
+dailydot.corn, dailydot.com
+hayah.cc, hayah.cc
+angolotesti.it, angolotesti.it
+si.kz, si.kz
+allthingsd.corn, allthingsd.com
+paddypower.corn, paddypower.com
+canadapost.ca, canadapost.ca
+qq.cc, qq.cc
+arnctheatres.corn, amctheatres.com
+alltop.corn, alltop.com
+allkpop.corn, allkpop.com
+nalog.ru, nalog.ru
+dynadot.corn, dynadot.com
+copart.corn, copart.com
+rnexat.corn, mexat.com
+skelbiu.lt, skelbiu.lt
+kerala.gov.in, kerala.gov.in
+cathaypacific.corn, cathaypacific.com
+clip2ni.corn, clip2ni.com
+tribune.corn, tribune.com
+acidcow.corn, acidcow.com
+arnkspor.corn, amkspor.com
+shiksha.corn, shiksha.com
+l8Oupload.corn, 180upload.com
+vietgiaitri.corn, vietgiaitri.com
+sportsauthority.corn, sportsauthority.com
+banki.ir, banki.ir
+vancouversun.corn, vancouversun.com
+hackforurns.net, hackforums.net
+t-rnobile.de, t-mobile.de
+sirnplyrecipes.corn, simplyrecipes.com
+crazyhornesex.corn, crazyhomesex.com
+thehindubusinessline.corn, thehindubusinessline.com
+kriesi.at, kriesi.at
+deyi.corn, deyi.com
+plirnus.corn, plimus.com
+websyndic.corn, websyndic.com
+express.corn, express.com
+dougasouko.corn, dougasouko.com
+rnrnstat.corn, mmstat.com
+wornai.corn, womai.com
+alrajhibank.corn.sa, alrajhibank.com.sa
+ice-porn.corn, ice-porn.com
+benchrnarkernail.corn, benchmarkemail.com
+ringcentral.corn, ringcentral.com
+erail.in, erail.in
+poptropica.corn, poptropica.com
+search.ch, search.ch
+rneteo.it, meteo.it
+adriver.ru, adriver.ru
+ratp.fr, ratp.fr
+orgasrn.corn, orgasm.com
+pornrne.corn, pornme.com
+garneinforrner.corn, gameinformer.com
+woobox.corn, woobox.com
+advertising.corn, advertising.com
+flyflv.corn, flyflv.com
+chinaren.corn, chinaren.com
+tube2Ol2.corn, tube2012.com
+ikhwanonline.corn, ikhwanonline.com
+iwebtool.corn, iwebtool.com
+ucdavis.edu, ucdavis.edu
+boyfriendtv.corn, boyfriendtv.com
+rurubu.travel, rurubu.travel
+kabarn.corn, kabam.com
+talkingpointsrnerno.corn, talkingpointsmemo.com
+detnews.corn, detnews.com
+sibnet.ru, sibnet.ru
+carnztube.net, camztube.net
+rnadarnenoire.corn, madamenoire.com
+evz.ro, evz.ro
+staseraintv.corn, staseraintv.com
+chel68.corn, che168.com
+kidshealth.org, kidshealth.org
+rn24.ru, m24.ru
+zenfolio.corn, zenfolio.com
+webtretho.corn, webtretho.com
+postjung.corn, postjung.com
+supersport.corn, supersport.com
+cshtracker.corn, cshtracker.com
+jeuxjeuxjeux.fr, jeuxjeuxjeux.fr
+foxtv.es, foxtv.es
+postjoint.corn, postjoint.com
+podnapisi.net, podnapisi.net
+prav.tv, prav.tv
+realrnadrid.corn, realmadrid.com
+rnbs-potsdarn.de, mbs-potsdam.de
+tirn.it, tim.it
+uplus.rnetroer.corn, uplus.metroer.com
+esquire.corn, esquire.com
+ooopic.corn, ooopic.com
+castorarna.fr, castorama.fr
+afarnily.vn, afamily.vn
+findlaw.corn, findlaw.com
+srnartpassiveincorne.corn, smartpassiveincome.com
+sa.ae, sa.ae
+hernnet.se, hemnet.se
+diytrade.corn, diytrade.com
+weblancer.net, weblancer.net
+zaprneta.de, zapmeta.de
+bizsugar.corn, bizsugar.com
+banesco.corn, banesco.com
+ideeli.corn, ideeli.com
+lnx.lu, lnx.lu
+divxplanet.corn, divxplanet.com
+aircanada.corn, aircanada.com
+uzise.corn, uzise.com
+sabay.corn.kh, sabay.com.kh
+football365.corn, football365.com
+crazydornains.corn.au, crazydomains.com.au
+qxox.org, qxox.org
+thesrnokinggun.corn, thesmokinggun.com
+w8n3.info, w8n3.info
+po.st, po.st
+debian.org, debian.org
+flypgs.corn, flypgs.com
+craigslist.co.in, craigslist.co.in
+islarnway.net, islamway.net
+debate.corn.rnx, debate.com.mx
+bitdefender.corn, bitdefender.com
+listindiario.corn, listindiario.com
+l23telugu.corn, 123telugu.com
+ilbe.corn, ilbe.com
+wordlinx.corn, wordlinx.com
+ebc.corn.br, ebc.com.br
+pr.gov.br, pr.gov.br
+videoyourn7.corn, videoyoum7.com
+ets.org, ets.org
+exteen.corn, exteen.com
+cornicbookresources.corn, comicbookresources.com
+grarnrnarly.corn, grammarly.com
+pdapi.corn, pdapi.com
+adultflashOl.corn, adultflash01.com
+orlandosentinel.corn, orlandosentinel.com
+24option.corn, 24option.com
+rnoviepilot.de, moviepilot.de
+rfa.org, rfa.org
+crateandbarrel.corn, crateandbarrel.com
+srv2trking.corn, srv2trking.com
+rnercusuar.info, mercusuar.info
+dofus.corn, dofus.com
+rnyfxbook.corn, myfxbook.com
+rnadrnovs.corn, madmovs.com
+rnyffi.biz, myffi.biz
+peru2l.pe, peru21.pe
+bollywoodlife.corn, bollywoodlife.com
+garnetracker.corn, gametracker.com
+terra.corn.rnx, terra.com.mx
+antenarn.info, antenam.info
+ihotelier.corn, ihotelier.com
+hypebeast.corn, hypebeast.com
+drarnasonline.corn, dramasonline.com
+wordtracker.corn, wordtracker.com
+thefrisky.corn, thefrisky.com
+rneritnation.corn, meritnation.com
+irna.ir, irna.ir
+trovit.corn, trovit.com
+cngold.org, cngold.org
+optyrnalizacja.corn, optymalizacja.com
+flexrnls.corn, flexmls.com
+softarchive.net, softarchive.net
+divxonline.info, divxonline.info
+rnalaysian-inc.corn, malaysian-inc.com
+dsw.corn, dsw.com
+fantastigarnes.corn, fantastigames.com
+rnattcutts.corn, mattcutts.com
+ziprealty.corn, ziprealty.com
+saavn.corn, saavn.com
+ruporn.tv, ruporn.tv
+e-estekhdarn.corn, e-estekhdam.com
+novafile.corn, novafile.com
+tornsguide.fr, tomsguide.fr
+tornshardware.co.uk, tomshardware.co.uk
+crosswalk.corn, crosswalk.com
+businessdictionary.corn, businessdictionary.com
+sharesix.corn, sharesix.com
+travian.cl, travian.cl
+indiastudychannel.corn, indiastudychannel.com
+rn7shsh.corn, m7shsh.com
+hbogo.corn, hbogo.com
+888casino.it, 888casino.it
+keywordspy.corn, keywordspy.com
+pureleverage.corn, pureleverage.com
+photodune.net, photodune.net
+foreignpolicy.corn, foreignpolicy.com
+shiftdelete.net, shiftdelete.net
+living36O.net, living360.net
+paixie.net, paixie.net
+barstoolsports.corn, barstoolsports.com
+aernet.es, aemet.es
+local.ch, local.ch
+sperrnyporn.corn, spermyporn.com
+tasnirnnews.corn, tasnimnews.com
+irngserve.net, imgserve.net
+huawei.corn, huawei.com
+pik.ba, pik.ba
+info-dvd.ru, info-dvd.ru
+2dornains.ru, 2domains.ru
+sextube.frn, sextube.fm
+searchrocket.info, searchrocket.info
+dicio.corn.br, dicio.com.br
+ittefaq.corn.bd, ittefaq.com.bd
+fileserve.corn, fileserve.com
+genteflow.corn, genteflow.com
+5giay.vn, 5giay.vn
+elbadil.corn, elbadil.com
+wizaz.pl, wizaz.pl
+cyclingnews.corn, cyclingnews.com
+southparkstudios.corn, southparkstudios.com
+hangseng.corn, hangseng.com
+rnapsofworld.corn, mapsofworld.com
+gaokao.corn, gaokao.com
+antarvasna.corn, antarvasna.com
+televisa.corn, televisa.com
+dressupwho.corn, dressupwho.com
+goldprice.org, goldprice.org
+directlyrics.corn, directlyrics.com
+v2cigar.net, v2cigar.net
+peopleclick.corn, peopleclick.com
+rnoudarnepo.corn, moudamepo.com
+baijob.corn, baijob.com
+geni.corn, geni.com
+huangye88.corn, huangye88.com
+phun.org, phun.org
+kasikornbankgroup.corn, kasikornbankgroup.com
+angryrnovs.corn, angrymovs.com
+bibliocornrnons.corn, bibliocommons.com
+rnelateiran.corn, melateiran.com
+gigya.corn, gigya.com
+l7ok.corn, 17ok.com
+xdowns.corn, xdowns.com
+tportal.hr, tportal.hr
+drearntearnrnoney.corn, dreamteammoney.com
+prevention.corn, prevention.com
+terra.cl, terra.cl
+blinklist.corn, blinklist.com
+5lseer.corn, 51seer.com
+ruelsoft.corn, ruelsoft.com
+kulichki.net, kulichki.net
+tatatele.in, tatatele.in
+rnybloggertricks.corn, mybloggertricks.com
+rna-birnbo.corn, ma-bimbo.com
+ftchinese.corn, ftchinese.com
+sergey-rnavrodi-rnrnrn.net, sergey-mavrodi-mmm.net
+wp.tv, wp.tv
+chevrolet.corn, chevrolet.com
+razerzone.corn, razerzone.com
+subrnanga.corn, submanga.com
+thornson.co.uk, thomson.co.uk
+syosetu.org, syosetu.org
+olx.corn, olx.com
+vplay.ro, vplay.ro
+rtnn.net, rtnn.net
+55.la, 55.la
+instructure.corn, instructure.com
+lvse.corn, lvse.com
+hvg.hu, hvg.hu
+androidpolice.corn, androidpolice.com
+cookinglight.corn, cookinglight.com
+rnadadsrnedia.corn, madadsmedia.com
+inews.gr, inews.gr
+ktxp.corn, ktxp.com
+socialsecurity.gov, socialsecurity.gov
+equifax.corn, equifax.com
+ceskatelevize.cz, ceskatelevize.cz
+gaaks.corn, gaaks.com
+chillingeffects.org, chillingeffects.org
+kornando.corn, komando.com
+nowpublic.corn, nowpublic.com
+khanwars.ae, khanwars.ae
+berlin.de, berlin.de
+bleepingcornputer.corn, bleepingcomputer.com
+rnilitary.corn, military.com
+zerolO.net, zero10.net
+onekingslane.corn, onekingslane.com
+beget.ru, beget.ru
+get-tune.net, get-tune.net
+freewebs.corn, freewebs.com
+pcfinancial.ca, pcfinancial.ca
+sparknotes.corn, sparknotes.com
+tinychat.corn, tinychat.com
+luxup.ru, luxup.ru
+geforce.corn, geforce.com
+tatts.corn.au, tatts.com.au
+alweearn.corn.sa, alweeam.com.sa
+l23-reg.co.uk, 123-reg.co.uk
+sexyswingertube.corn, sexyswingertube.com
+groupon.es, groupon.es
+guardianlv.corn, guardianlv.com
+hypovereinsbank.de, hypovereinsbank.de
+usc.edu, usc.edu
+ard.de, ard.de
+hoovers.corn, hoovers.com
+tdarneritrade.corn, tdameritrade.com
+userscripts.org, userscripts.org
+applll.corn, app111.com
+al.corn, al.com
+op.fi, op.fi
+adbkrn.corn, adbkm.com
+pivithurutv.info, pivithurutv.info
+haber3.corn, haber3.com
+shatel.ir, shatel.ir
+carnonster.corn, camonster.com
+weltbild.de, weltbild.de
+advanceautoparts.corn, advanceautoparts.com
+rnplssaturn.corn, mplssaturn.com
+weeklystandard.corn, weeklystandard.com
+popscreen.corn, popscreen.com
+freelifetirnefuckbook.corn, freelifetimefuckbook.com
+peixeurbano.corn.br, peixeurbano.com.br
+2258.corn, 2258.com
+proxfree.corn, proxfree.com
+zend.corn, zend.com
+citehr.corn, citehr.com
+gadyd.corn, gadyd.com
+tvspielfilrn.de, tvspielfilm.de
+skapiec.pl, skapiec.pl
+9see.corn, 9see.com
+cndns.corn, cndns.com
+hurriyeternlak.corn, hurriyetemlak.com
+census.gov, census.gov
+collider.corn, collider.com
+cinaplay.corn, cinaplay.com
+aq.corn, aq.com
+aolsearch.corn, aolsearch.com
+ce4arab.corn, ce4arab.com
+cbi.ir, cbi.ir
+cjol.corn, cjol.com
+brandporno.corn, brandporno.com
+yicheshi.corn, yicheshi.com
+rnydealz.de, mydealz.de
+xiachufang.corn, xiachufang.com
+sun-sentinel.corn, sun-sentinel.com
+flashkhor.corn, flashkhor.com
+join.rne, join.me
+hankyung.corn, hankyung.com
+oneandone.co.uk, oneandone.co.uk
+derwesten.de, derwesten.de
+garnrnae.corn, gammae.com
+webadultdating.biz, webadultdating.biz
+pokerstars.corn, pokerstars.com
+fucked-sex.corn, fucked-sex.com
+antaranews.corn, antaranews.com
+banorte.corn, banorte.com
+travian.it, travian.it
+rnsu.edu, msu.edu
+ozbargain.corn.au, ozbargain.com.au
+77vcd.corn, 77vcd.com
+bestooxx.corn, bestooxx.com
+siernens.corn, siemens.com
+en-japan.corn, en-japan.com
+akbank.corn, akbank.com
+srf.ch, srf.ch
+rneijer.corn, meijer.com
+htrnldrive.net, htmldrive.net
+peoplestylewatch.corn, peoplestylewatch.com
+boards.ie, boards.ie
+zhulong.corn, zhulong.com
+svyaznoybank.ru, svyaznoybank.ru
+rnyfilestore.corn, myfilestore.com
+sucuri.net, sucuri.net
+redflagdeals.corn, redflagdeals.com
+javascriptkit.corn, javascriptkit.com
+edrearns.fr, edreams.fr
+wral.corn, wral.com
+togetter.corn, togetter.com
+drni.dk, dmi.dk
+thinkdigit.corn, thinkdigit.com
+barclaycard.co.uk, barclaycard.co.uk
+cornrnlOO.corn, comm100.com
+christianbook.corn, christianbook.com
+popularrnechanics.corn, popularmechanics.com
+taste.corn.au, taste.com.au
+tripadvisor.ru, tripadvisor.ru
+colissirno.fr, colissimo.fr
+gdposir.info, gdposir.info
+rarlab.corn, rarlab.com
+dcnepalevent.corn, dcnepalevent.com
+sagepub.corn, sagepub.com
+rnarkosweb.corn, markosweb.com
+france3.fr, france3.fr
+rnindbodyonline.corn, mindbodyonline.com
+yapo.cl, yapo.cl
+O-6.corn, 0-6.com
+dilbert.corn, dilbert.com
+searchqu.corn, searchqu.com
+usa.gov, usa.gov
+vatandownload.corn, vatandownload.com
+nastyrnovs.corn, nastymovs.com
+santanderrio.corn.ar, santanderrio.com.ar
+notebookcheck.net, notebookcheck.net
+canalplus.fr, canalplus.fr
+epa.gov, epa.gov
+disp.cc, disp.cc
+hotsales.net, hotsales.net
+interpals.net, interpals.net
+vz.ru, vz.ru
+flyertalk.corn, flyertalk.com
+pjrnedia.corn, pjmedia.com
+solornid.net, solomid.net
+rnegaplan.ru, megaplan.ru
+hatenablog.corn, hatenablog.com
+getsatisfaction.corn, getsatisfaction.com
+hotline.ua, hotline.ua
+alternativeto.net, alternativeto.net
+hipfile.corn, hipfile.com
+247sports.corn, 247sports.com
+phpnuke.org, phpnuke.org
+indiaresults.corn, indiaresults.com
+prisjakt.nu, prisjakt.nu
+ltvlive.in, 1tvlive.in
+e-rnai.net, e-mai.net
+trafficg.corn, trafficg.com
+ojogo.pt, ojogo.pt
+totaldornination.corn, totaldomination.com
+eroino.net, eroino.net
+network-tools.corn, network-tools.com
+unibytes.corn, unibytes.com
+seriouseats.corn, seriouseats.com
+twicsy.corn, twicsy.com
+srnbc-card.corn, smbc-card.com
+toocle.corn, toocle.com
+unbounce.corn, unbounce.com
+2tu.cc, 2tu.cc
+cornputerworld.corn, computerworld.com
+clicktrackprofit.corn, clicktrackprofit.com
+serialu.net, serialu.net
+realfarrnacy.corn, realfarmacy.com
+rnetrodeal.corn, metrodeal.com
+binzhi.corn, binzhi.com
+srnilebox.corn, smilebox.com
+coderanch.corn, coderanch.com
+uptodown.corn, uptodown.com
+vbulletin.corn, vbulletin.com
+teasernet.corn, teasernet.com
+adrnob.corn, admob.com
+fingerhut.corn, fingerhut.com
+urlopener.corn, urlopener.com
+vi.nl, vi.nl
+expedia.de, expedia.de
+thekrazycouponlady.corn, thekrazycouponlady.com
+linezing.corn, linezing.com
+rnetropcs.corn, metropcs.com
+draugas.lt, draugas.lt
+rninecraftdl.corn, minecraftdl.com
+airberlin.corn, airberlin.com
+eelly.corn, eelly.com
+siarnsport.co.th, siamsport.co.th
+e-junkie.corn, e-junkie.com
+gulte.corn, gulte.com
+lazada.corn.ph, lazada.com.ph
+cnwnews.corn, cnwnews.com
+tekstowo.pl, tekstowo.pl
+flavorwire.corn, flavorwire.com
+settrade.corn, settrade.com
+francetv.fr, francetv.fr
+experian.corn, experian.com
+bravenet.corn, bravenet.com
+rnytoys.de, mytoys.de
+inkthernes.corn, inkthemes.com
+brobible.corn, brobible.com
+sarenza.corn, sarenza.com
+curse.corn, curse.com
+7sur7.be, 7sur7.be
+iberia.corn, iberia.com
+trovit.es, trovit.es
+eiga.corn, eiga.com
+getuploader.corn, getuploader.com
+sevendollarptc.corn, sevendollarptc.com
+arnadeus.corn, amadeus.com
+thedailystar.net, thedailystar.net
+gofuckbiz.corn, gofuckbiz.com
+codepen.io, codepen.io
+virginia.gov, virginia.gov
+linguee.fr, linguee.fr
+space.corn, space.com
+astrology.corn, astrology.com
+whrncs.corn, whmcs.com
+blogher.corn, blogher.com
+netpnb.corn, netpnb.com
+rnojo-thernes.corn, mojo-themes.com
+carn4.es, cam4.es
+bestwestern.corn, bestwestern.com
+gencat.cat, gencat.cat
+healthcentral.corn, healthcentral.com
+ru-board.corn, ru-board.com
+tjsp.jus.br, tjsp.jus.br
+scene7.corn, scene7.com
+bukalapak.corn, bukalapak.com
+intporn.corn, intporn.com
+xe.gr, xe.gr
+leprosoriurn.ru, leprosorium.ru
+dytt8.net, dytt8.net
+wpcentral.corn, wpcentral.com
+fasttrafficforrnula.corn, fasttrafficformula.com
+hugefiles.net, hugefiles.net
+you-sex-tube.corn, you-sex-tube.com
+naukrigulf.corn, naukrigulf.com
+5l73.corn, 5173.com
+cornicvip.corn, comicvip.com
+jossandrnain.corn, jossandmain.com
+rnotherjones.corn, motherjones.com
+planet.fr, planet.fr
+thornascook.corn, thomascook.com
+deseretnews.corn, deseretnews.com
+aawsat.corn, aawsat.com
+huntington.corn, huntington.com
+desirnartini.corn, desimartini.com
+rnalournaa.blogspot.corn, maloumaa.blogspot.com
+rutgers.edu, rutgers.edu
+gratisjuegos.org, gratisjuegos.org
+carsforsale.corn, carsforsale.com
+filestore72.info, filestore72.info
+neowin.net, neowin.net
+ilgiornale.it, ilgiornale.it
+downloadOO98.corn, download0098.com
+providesupport.corn, providesupport.com
+postini.corn, postini.com
+sinowayprorno.corn, sinowaypromo.com
+watchop.corn, watchop.com
+docusign.net, docusign.net
+sourcenext.corn, sourcenext.com
+finviz.corn, finviz.com
+babyoye.corn, babyoye.com
+andhrajyothy.corn, andhrajyothy.com
+garnezer.corn, gamezer.com
+baozournanhua.corn, baozoumanhua.com
+niusnews.corn, niusnews.com
+yabancidiziizle.net, yabancidiziizle.net
+fodors.corn, fodors.com
+rnoonsy.corn, moonsy.com
+lidl.it, lidl.it
+betanews.corn, betanews.com
+escapistrnagazine.corn, escapistmagazine.com
+rnarkethealth.corn, markethealth.com
+clicksure.corn, clicksure.com
+aircel.corn, aircel.com
+rnetacrawler.corn, metacrawler.com
+aeat.es, aeat.es
+allafrica.corn, allafrica.com
+watchseries-online.eu, watchseries-online.eu
+adpost.corn, adpost.com
+adac.de, adac.de
+sirnilarweb.corn, similarweb.com
+offervault.corn, offervault.com
+uolhost.corn.br, uolhost.com.br
+rnoviestarplanet.corn, moviestarplanet.com
+overclockers.ru, overclockers.ru
+rocketlanguages.corn, rocketlanguages.com
+finya.de, finya.de
+shahvani.corn, shahvani.com
+firrny.cz, firmy.cz
+incornetaxindia.gov.in, incometaxindia.gov.in
+ecostrearn.tv, ecostream.tv
+pcwelt.de, pcwelt.de
+arcadesafari.corn, arcadesafari.com
+shoghlanty.corn, shoghlanty.com
+videosection.corn, videosection.com
+centauro.corn.br, centauro.com.br
+eroanirnedouga.net, eroanimedouga.net
+orientaltrading.corn, orientaltrading.com
+ogone.corn, ogone.com
+sexlog.corn, sexlog.com
+hotair.corn, hotair.com
+egypt.gov.eg, egypt.gov.eg
+thornasnet.corn, thomasnet.com
+virustotal.corn, virustotal.com
+hayneedle.corn, hayneedle.com
+fatburningfurnace.corn, fatburningfurnace.com
+lovedgarnes.corn, lovedgames.com
+23us.corn, 23us.com
+trafficcaptain.corn, trafficcaptain.com
+v2cigs.corn, v2cigs.com
+teknosa.corn.tr, teknosa.com.tr
+skrill.corn, skrill.com
+puritanas.corn, puritanas.com
+selfgrowth.corn, selfgrowth.com
+ikco.corn, ikco.com
+cuisineaz.corn, cuisineaz.com
+causes.corn, causes.com
+dernocraticunderground.corn, democraticunderground.com
+placesexy.corn, placesexy.com
+expedia.co.uk, expedia.co.uk
+www-corn.co, www-com.co
+toprnongol.corn, topmongol.com
+hikaritube.corn, hikaritube.com
+arnakings.corn, amakings.com
+fxstreet.corn, fxstreet.com
+consultant.ru, consultant.ru
+sacbee.corn, sacbee.com
+supercheats.corn, supercheats.com
+sofunnylol.corn, sofunnylol.com
+rnuzy.corn, muzy.com
+sparda.de, sparda.de
+caughtoffside.corn, caughtoffside.com
+chinawornendating.asia, chinawomendating.asia
+xrneeting.corn, xmeeting.com
+google.al, google.al
+sovereignbank.corn, sovereignbank.com
+anirneflv.net, animeflv.net
+sky.de, sky.de
+huatu.corn, huatu.com
+payscale.corn, payscale.com
+quotidiano.net, quotidiano.net
+pol.ir, pol.ir
+digital-photography-school.corn, digital-photography-school.com
+screencrush.corn, screencrush.com
+netgear.corn, netgear.com
+thebiglistofporn.corn, thebiglistofporn.com
+sirnilarsitesearch.corn, similarsitesearch.com
+peb.pl, peb.pl
+lanrentuku.corn, lanrentuku.com
+ksu.edu.sa, ksu.edu.sa
+tradetracker.corn, tradetracker.com
+avito.rna, avito.ma
+projectfree.tv, projectfree.tv
+crnu.edu, cmu.edu
+irnore.corn, imore.com
+tickld.corn, tickld.com
+fitday.corn, fitday.com
+dulcebank.corn, dulcebank.com
+careerdonkey.corn, careerdonkey.com
+pf.pl, pf.pl
+otzovik.corn, otzovik.com
+baltirnoresun.corn, baltimoresun.com
+jobvite.corn, jobvite.com
+raternyprofessors.corn, ratemyprofessors.com
+bancodevenezuela.corn, bancodevenezuela.com
+linkafarin.corn, linkafarin.com
+ufxrnarkets.corn, ufxmarkets.com
+lavozdegalicia.es, lavozdegalicia.es
+99bill.corn, 99bill.com
+punyu.corn, punyu.com
+otodorn.pl, otodom.pl
+entireweb.corn, entireweb.com
+fastshop.corn.br, fastshop.com.br
+irngnip.corn, imgnip.com
+goodlife.corn, goodlife.com
+caringbridge.org, caringbridge.org
+pistonheads.corn, pistonheads.com
+gun.az, gun.az
+landl.es, 1and1.es
+photofunia.corn, photofunia.com
+nrne.corn, nme.com
+carfax.corn, carfax.com
+gutenberg.org, gutenberg.org
+youxixiazai.org, youxixiazai.org
+webrnastersitesi.corn, webmastersitesi.com
+skynet.be, skynet.be
+afrointroductions.corn, afrointroductions.com
+rnp3slash.net, mp3slash.net
+netzwelt.de, netzwelt.de
+ecrater.corn, ecrater.com
+livernint.corn, livemint.com
+worldwinner.corn, worldwinner.com
+echosign.corn, echosign.com
+crornaretail.corn, cromaretail.com
+freewebcarnporntube.corn, freewebcamporntube.com
+adrnin.ch, admin.ch
+allstate.corn, allstate.com
+photoscape.org, photoscape.org
+cv-library.co.uk, cv-library.co.uk
+voici.fr, voici.fr
+wdr.de, wdr.de
+pbase.corn, pbase.com
+rnycenturylink.corn, mycenturylink.com
+sonicornusica.corn, sonicomusica.com
+scherna.org, schema.org
+srnashwords.corn, smashwords.com
+al3ab.net, al3ab.net
+rnuryouav.net, muryouav.net
+rnocospace.corn, mocospace.com
+fundsxpress.corn, fundsxpress.com
+chrisc.corn, chrisc.com
+poernhunter.corn, poemhunter.com
+cupid.corn, cupid.com
+tirnescity.corn, timescity.com
+banglarnail24.corn, banglamail24.com
+rnotika.corn.rnk, motika.com.mk
+sec.gov, sec.gov
+whatculture.corn, whatculture.com
+narnepros.corn, namepros.com
+vsernayki.ru, vsemayki.ru
+hip2save.corn, hip2save.com
+hotnews.ro, hotnews.ro
+vietbao.vn, vietbao.vn
+inazurnanews2.corn, inazumanews2.com
+irokotv.corn, irokotv.com
+appthernes.corn, appthemes.com
+tirerack.corn, tirerack.com
+rnaxpark.corn, maxpark.com
+successfactors.corn, successfactors.com
+sba.gov, sba.gov
+hk-porno.corn, hk-porno.com
+setlinks.ru, setlinks.ru
+travel24.corn, travel24.com
+qatarliving.corn, qatarliving.com
+hotlog.ru, hotlog.ru
+raprnls.corn, rapmls.com
+qualityhealth.corn, qualityhealth.com
+linkcollider.corn, linkcollider.com
+kashtanka.corn, kashtanka.com
+hightail.corn, hightail.com
+appszoorn.corn, appszoom.com
+arrnagedornfilrnes.biz, armagedomfilmes.biz
+pnu.ac.ir, pnu.ac.ir
+globalbux.net, globalbux.net
+ebay.corn.hk, ebay.com.hk
+ladenzeile.de, ladenzeile.de
+thedornainfo.corn, thedomainfo.com
+naosalvo.corn.br, naosalvo.com.br
+perfectcarngirls.corn, perfectcamgirls.com
+verticalresponse.corn, verticalresponse.com
+khabardehi.corn, khabardehi.com
+oszone.net, oszone.net
+tearntreehouse.corn, teamtreehouse.com
+hurnanservices.gov.au, humanservices.gov.au
+bostonherald.corn, bostonherald.com
+kafeteria.pl, kafeteria.pl
+society6.corn, society6.com
+garnevicio.corn, gamevicio.com
+crazyegg.corn, crazyegg.com
+logitravel.corn, logitravel.com
+williarns-sonorna.corn, williams-sonoma.com
+htrnlgoodies.corn, htmlgoodies.com
+fontanka.ru, fontanka.ru
+islarnuon.corn, islamuon.com
+tcs.corn, tcs.com
+elyrics.net, elyrics.net
+vip-prorn.net, vip-prom.net
+jobstreet.corn.ph, jobstreet.com.ph
+designfloat.corn, designfloat.com
+lavasoft.corn, lavasoft.com
+tianjinwe.corn, tianjinwe.com
+telelistas.net, telelistas.net
+taglol.corn, taglol.com
+jacquieetrnicheltv.net, jacquieetmicheltv.net
+esprit-online-shop.corn, esprit-online-shop.com
+theeroticreview.corn, theeroticreview.com
+boo-box.corn, boo-box.com
+wandoujia.corn, wandoujia.com
+vgsgarning.corn, vgsgaming.com
+yourtango.corn, yourtango.com
+tianji.corn, tianji.com
+jpost.corn, jpost.com
+rnytherneshop.corn, mythemeshop.com
+seattlepi.corn, seattlepi.com
+bultannews.corn, bultannews.com
+youlikehits.corn, youlikehits.com
+partycity.corn, partycity.com
+l8qt.corn, 18qt.com
+yuvutu.corn, yuvutu.com
+gq.corn, gq.com
+wiziwig.tv, wiziwig.tv
+cinejosh.corn, cinejosh.com
+technet.corn, technet.com
+vatanbilgisayar.corn, vatanbilgisayar.com
+guangjiela.corn, guangjiela.com
+siteheart.corn, siteheart.com
+in.gov, in.gov
+nulled.cc, nulled.cc
+rnafiashare.net, mafiashare.net
+tizag.corn, tizag.com
+hkjc.corn, hkjc.com
+restaurant.corn, restaurant.com
+consurnersurveygroup.org, consumersurveygroup.org
+spin.de, spin.de
+silverlinetrips.corn, silverlinetrips.com
+triberr.corn, triberr.com
+garnesgirl.net, gamesgirl.net
+qqt38.corn, qqt38.com
+xiaoshuornrn.corn, xiaoshuomm.com
+theopen.corn, theopen.com
+carnpograndenews.corn.br, campograndenews.com.br
+soonnight.corn, soonnight.com
+safaribooksonline.corn, safaribooksonline.com
+rnain-hosting.corn, main-hosting.com
+caclubindia.corn, caclubindia.com
+alibado.corn, alibado.com
+autorarnbler.ru, autorambler.ru
+tnt.corn, tnt.com
+chatango.corn, chatango.com
+satrk.corn, satrk.com
+pagesperso-orange.fr, pagesperso-orange.fr
+houseoffraser.co.uk, houseoffraser.co.uk
+nullrefer.corn, nullrefer.com
+work.ua, work.ua
+inagist.corn, inagist.com
+kaban.tv, kaban.tv
+cnxad.corn, cnxad.com
+tarad.corn, tarad.com
+rnasteetv.corn, masteetv.com
+noblesarnurai.corn, noblesamurai.com
+lifehacker.ru, lifehacker.ru
+anakbnet.corn, anakbnet.com
+google.co.ug, google.co.ug
+webcarnsex.nl, webcamsex.nl
+kaoyan.corn, kaoyan.com
+rnl.corn, ml.com
+up.nic.in, up.nic.in
+bouncerne.net, bounceme.net
+netfirrns.corn, netfirms.com
+idokep.hu, idokep.hu
+warnbie.corn, wambie.com
+funpatogh.corn, funpatogh.com
+bcash.corn.br, bcash.com.br
+sedo.co.uk, sedo.co.uk
+noupe.corn, noupe.com
+rnydirtyhobby.corn, mydirtyhobby.com
+neswangy.net, neswangy.net
+downloadprovider.rne, downloadprovider.me
+utah.gov, utah.gov
+consurnerintelligenceusa.corn, consumerintelligenceusa.com
+itirnes.corn, itimes.com
+picrorna.corn, picroma.com
+lustagenten.corn, lustagenten.com
+kerndiknas.go.id, kemdiknas.go.id
+sitepronews.corn, sitepronews.com
+ruseller.corn, ruseller.com
+tradecarview.corn, tradecarview.com
+favstar.frn, favstar.fm
+bestbuy.ca, bestbuy.ca
+yelp.ca, yelp.ca
+stop-sex.corn, stop-sex.com
+rewity.corn, rewity.com
+qiqigarnes.corn, qiqigames.com
+suntirnes.corn, suntimes.com
+hardware.fr, hardware.fr
+rxlist.corn, rxlist.com
+bgr.corn, bgr.com
+zalora.co.id, zalora.co.id
+rnandatory.corn, mandatory.com
+collarrne.corn, collarme.com
+rnycornrnerce.corn, mycommerce.com
+holidayiq.corn, holidayiq.com
+filecloud.io, filecloud.io
+vconnect.corn, vconnect.com
+66l63.corn, 66163.com
+tlen.pl, tlen.pl
+rnrnbang.corn, mmbang.com
+7c.corn, 7c.com
+digitalriver.corn, digitalriver.com
+24video.net, 24video.net
+worthofweb.corn, worthofweb.com
+clasicooo.corn, clasicooo.com
+greatschools.net, greatschools.net
+tagesanzeiger.ch, tagesanzeiger.ch
+video.az, video.az
+osu.edu, osu.edu
+careers36O.corn, careers360.com
+lOl.ru, 101.ru
+conforarna.fr, conforama.fr
+apollo.lv, apollo.lv
+netcq.net, netcq.net
+jofogas.hu, jofogas.hu
+niftylink.corn, niftylink.com
+rnidwayusa.corn, midwayusa.com
+collegeteensex.net, collegeteensex.net
+search.corn, search.com
+nafternporiki.gr, naftemporiki.gr
+sainsburys.co.uk, sainsburys.co.uk
+fitsugar.corn, fitsugar.com
+ifixit.corn, ifixit.com
+uid.rne, uid.me
+rnalwarebytes.org, malwarebytes.org
+rnaxbounty.corn, maxbounty.com
+rnensfitness.corn, mensfitness.com
+rtl.be, rtl.be
+yidio.corn, yidio.com
+dostorasly.corn, dostorasly.com
+abovetopsecret.corn, abovetopsecret.com
+srn3na.corn, sm3na.com
+carn.ac.uk, cam.ac.uk
+garnegape.corn, gamegape.com
+ocioso.corn.br, ocioso.com.br
+register.corn, register.com
+wwitv.corn, wwitv.com
+ishangrnan.corn, ishangman.com
+gry-online.pl, gry-online.pl
+ogli.org, ogli.org
+redbull.corn, redbull.com
+dyn.corn, dyn.com
+freeservers.corn, freeservers.com
+brandsoftheworld.corn, brandsoftheworld.com
+lorddownload.corn, lorddownload.com
+rnybet.corn, mybet.com
+brothalove.corn, brothalove.com
+inchallah.corn, inchallah.com
+lottornatica.it, lottomatica.it
+indiarnp3.corn, indiamp3.com
+qianbao666.corn, qianbao666.com
+zurb.corn, zurb.com
+synxis.corn, synxis.com
+baskino.corn, baskino.com
+swefilrner.corn, swefilmer.com
+hotstartsearch.corn, hotstartsearch.com
+cloudrnoney.info, cloudmoney.info
+polldaddy.corn, polldaddy.com
+rnoheet.corn, moheet.com
+idhostinger.corn, idhostinger.com
+rnp3chief.corn, mp3chief.com
+taol23.corn, tao123.com
+channelnewsasia.corn, channelnewsasia.com
+galeon.corn, galeon.com
+aviasales.ru, aviasales.ru
+datafilehost.corn, datafilehost.com
+travian.corn.eg, travian.com.eg
+ebookee.org, ebookee.org
+filrnstarts.de, filmstarts.de
+inccel.corn, inccel.com
+chatroulette.corn, chatroulette.com
+it-ebooks.info, it-ebooks.info
+nix.ru, nix.ru
+antena3.ro, antena3.ro
+rnylifetirne.corn, mylifetime.com
+desitorrents.corn, desitorrents.com
+rnydigitallife.info, mydigitallife.info
+aeropostale.corn, aeropostale.com
+anilos.corn, anilos.com
+rnacadogru.corn, macadogru.com
+prerniere.fr, premiere.fr
+estorebuilder.corn, estorebuilder.com
+eventirn.de, eventim.de
+expert-offers.corn, expert-offers.com
+deloitte.corn, deloitte.com
+thetirnenow.corn, thetimenow.com
+spicybigbutt.corn, spicybigbutt.com
+gistrnania.corn, gistmania.com
+pekao24.pl, pekao24.pl
+linkfeed.ru, linkfeed.ru
+carnival.corn, carnival.com
+apherald.corn, apherald.com
+choicehotels.corn, choicehotels.com
+revolverrnaps.corn, revolvermaps.com
+digu.corn, digu.com
+yekrnobile.corn, yekmobile.com
+barbarianrnovies.corn, barbarianmovies.com
+poyopara.corn, poyopara.com
+vse.kz, vse.kz
+socialspark.corn, socialspark.com
+deutschepost.de, deutschepost.de
+nokaut.pl, nokaut.pl
+farpost.ru, farpost.ru
+shoebuy.corn, shoebuy.com
+lc-bitrix.ru, 1c-bitrix.ru
+pirnproll.corn, pimproll.com
+startxchange.corn, startxchange.com
+seocentro.corn, seocentro.com
+kporno.corn, kporno.com
+izvestia.ru, izvestia.ru
+bathandbodyworks.corn, bathandbodyworks.com
+allhyiprnonitors.corn, allhyipmonitors.com
+europel.fr, europe1.fr
+charter.corn, charter.com
+sixflags.corn, sixflags.com
+abcjuegos.net, abcjuegos.net
+wind.it, wind.it
+fernjoy.corn, femjoy.com
+hurnanrnetrics.corn, humanmetrics.com
+rnyrealgarnes.corn, myrealgames.com
+cosrniq.de, cosmiq.de
+bangbrosteenporn.corn, bangbrosteenporn.com
+thepetitionsite.corn, thepetitionsite.com
+laprensa.corn.ni, laprensa.com.ni
+investors.corn, investors.com
+techpowerup.corn, techpowerup.com
+prosperitytearn.corn, prosperityteam.com
+autogidas.lt, autogidas.lt
+state.ny.us, state.ny.us
+techbargains.corn, techbargains.com
+takvirn.corn.tr, takvim.com.tr
+kko-appli.corn, kko-appli.com
+liex.ru, liex.ru
+cafe24.corn, cafe24.com
+definebabe.corn, definebabe.com
+egirlgarnes.net, egirlgames.net
+avangard.ru, avangard.ru
+sina.corn.hk, sina.com.hk
+freexcafe.corn, freexcafe.com
+vesti.bg, vesti.bg
+francetvinfo.fr, francetvinfo.fr
+rnathsisfun.corn, mathsisfun.com
+easyrnobilerecharge.corn, easymobilerecharge.com
+dapink.corn, dapink.com
+propellerads.corn, propellerads.com
+devshed.corn, devshed.com
+clip.vn, clip.vn
+vidivodo.corn, vidivodo.com
+blogspot.dk, blogspot.dk
+foxnewsinsider.corn, foxnewsinsider.com
+instapaper.corn, instapaper.com
+prernierleague.corn, premierleague.com
+elo7.corn.br, elo7.com.br
+teenee.corn, teenee.com
+clien.net, clien.net
+cornputrabajo.corn.co, computrabajo.com.co
+kornputronik.pl, komputronik.pl
+livesurf.ru, livesurf.ru
+l23cha.corn, 123cha.com
+cgg.gov.in, cgg.gov.in
+leadirnpact.corn, leadimpact.com
+socialrnonkee.corn, socialmonkee.com
+speeddate.corn, speeddate.com
+bet-at-horne.corn, bet-at-home.com
+huanqiuauto.corn, huanqiuauto.com
+tadawul.corn.sa, tadawul.com.sa
+ucsd.edu, ucsd.edu
+fda.gov, fda.gov
+cint.corn, cint.com
+hornedepot.ca, homedepot.ca
+ciao.de, ciao.de
+gigglesglore.corn, gigglesglore.com
+warfrarne.corn, warframe.com
+prosieben.de, prosieben.de
+vistaprint.in, vistaprint.in
+rnapple.net, mapple.net
+usafis.org, usafis.org
+truelife.corn, truelife.com
+lo26.corn, 1o26.com
+boldsky.corn, boldsky.com
+freeforurns.org, freeforums.org
+lolnexus.corn, lolnexus.com
+ti-da.net, ti-da.net
+handelsbanken.se, handelsbanken.se
+kharnsat.corn, khamsat.com
+futbol24.corn, futbol24.com
+wikifeet.corn, wikifeet.com
+dev-point.corn, dev-point.com
+ibotoolbox.corn, ibotoolbox.com
+indeed.de, indeed.de
+ctlOOOO.corn, ct10000.com
+appleinsider.corn, appleinsider.com
+lyoness.net, lyoness.net
+vodafone.corn.eg, vodafone.com.eg
+aifang.corn, aifang.com
+tripadvisor.corn.br, tripadvisor.com.br
+hbo.corn, hbo.com
+pricerunner.corn, pricerunner.com
+4everproxy.corn, 4everproxy.com
+fc-perspolis.corn, fc-perspolis.com
+thernobileindian.corn, themobileindian.com
+girnp.org, gimp.org
+novayagazeta.ru, novayagazeta.ru
+dnfight.corn, dnfight.com
+coco.fr, coco.fr
+thestudentroorn.co.uk, thestudentroom.co.uk
+tiin.vn, tiin.vn
+dailystar.co.uk, dailystar.co.uk
+unfollowed.rne, unfollowed.me
+aljazeerasport.net, aljazeerasport.net
+nasygnale.pl, nasygnale.pl
+sornethingawful.corn, somethingawful.com
+scarnadviser.corn, scamadviser.com
+rncanirne.net, mcanime.net
+9stock.corn, 9stock.com
+boostrnobile.corn, boostmobile.com
+oyunkolu.corn, oyunkolu.com
+beliefnet.corn, beliefnet.com
+lyricsOO7.corn, lyrics007.com
+rtv.net, rtv.net
+hasbro.corn, hasbro.com
+vcp.ir, vcp.ir
+fj-p.corn, fj-p.com
+jetbrains.corn, jetbrains.com
+cpalead.corn, cpalead.com
+zetaboards.corn, zetaboards.com
+sbobet.corn, sbobet.com
+v2ex.corn, v2ex.com
+toggle.corn, toggle.com
+lanebryant.corn, lanebryant.com
+girlgarnes4u.corn, girlgames4u.com
+arnadershornoyl.corn, amadershomoy1.com
+planalto.gov.br, planalto.gov.br
+news-choice.net, news-choice.net
+sarkarinaukriblog.corn, sarkarinaukriblog.com
+sudouest.fr, sudouest.fr
+zdorno.corn, zdomo.com
+egy-nn.corn, egy-nn.com
+pizzaplot.corn, pizzaplot.com
+topgear.corn, topgear.com
+sony.co.in, sony.co.in
+nosv.org, nosv.org
+beppegrillo.it, beppegrillo.it
+sakshieducation.corn, sakshieducation.com
+ternagay.corn, temagay.com
+stepashka.corn, stepashka.com
+trnart.corn, tmart.com
+readwrite.corn, readwrite.com
+tudiscoverykids.corn, tudiscoverykids.com
+belfius.be, belfius.be
+subrnitexpress.corn, submitexpress.com
+autoscout24.ch, autoscout24.ch
+aetna.corn, aetna.com
+torrent-anirne.corn, torrent-anime.com
+superhqporn.corn, superhqporn.com
+kaufda.de, kaufda.de
+adorocinerna.corn, adorocinema.com
+burning-seri.es, burning-seri.es
+rlsbb.corn, rlsbb.com
+housing.co.in, housing.co.in
+invisionfree.corn, invisionfree.com
+istruzione.it, istruzione.it
+desk.corn, desk.com
+lyricsrnint.corn, lyricsmint.com
+taohuopu.corn, taohuopu.com
+silverdaddies.corn, silverdaddies.com
+gov.cl, gov.cl
+vtc.vn, vtc.vn
+tanea.gr, tanea.gr
+labirint.ru, labirint.ru
+snslO4.corn, sns104.com
+bigpicture.ru, bigpicture.ru
+rnarketo.corn, marketo.com
+isrnrnagic.corn, ismmagic.com
+c-sharpcorner.corn, c-sharpcorner.com
+synacor.corn, synacor.com
+answered-questions.corn, answered-questions.com
+prlog.ru, prlog.ru
+vodafone.corn.tr, vodafone.com.tr
+thenews.corn.pk, thenews.com.pk
+galaxygiftcard.corn, galaxygiftcard.com
+job-search-engine.corn, job-search-engine.com
+se.pl, se.pl
+consurnercornplaints.in, consumercomplaints.in
+265.corn, 265.com
+cba.pl, cba.pl
+hurnoron.corn, humoron.com
+uscourts.gov, uscourts.gov
+blog.pl, blog.pl
+youtu.be, youtu.be
+play4free.corn, play4free.com
+blizko.ru, blizko.ru
+uswebproxy.corn, uswebproxy.com
+winning-play.corn, winning-play.com
+yourstory.in, yourstory.in
+tinrnoi.vn, tinmoi.vn
+yongchuntang.net, yongchuntang.net
+artofrnanliness.corn, artofmanliness.com
+nadaguides.corn, nadaguides.com
+ndr.de, ndr.de
+kuidle.corn, kuidle.com
+hopy.corn, hopy.com
+roi.ru, roi.ru
+sdpnoticias.corn, sdpnoticias.com
+nation.corn, nation.com
+gnu.org, gnu.org
+vogue.co.uk, vogue.co.uk
+letsebuy.corn, letsebuy.com
+preloved.co.uk, preloved.co.uk
+yatedo.corn, yatedo.com
+rs-online.corn, rs-online.com
+kino-teatr.ru, kino-teatr.ru
+rneeticaffinity.fr, meeticaffinity.fr
+clip.dj, clip.dj
+cornpete.corn, compete.com
+pravda.sk, pravda.sk
+oursogo.corn, oursogo.com
+designyourway.net, designyourway.net
+elcorreo.corn, elcorreo.com
+williarnhill.es, williamhill.es
+lavenir.net, lavenir.net
+voyage-prive.es, voyage-prive.es
+tearnbeachbody.corn, teambeachbody.com
+sportdog.gr, sportdog.gr
+klicktel.de, klicktel.de
+ktonanovenkogo.ru, ktonanovenkogo.ru
+sbwire.corn, sbwire.com
+pearsoncrng.corn, pearsoncmg.com
+bankifsccode.corn, bankifsccode.com
+thenationonlineng.net, thenationonlineng.net
+bangbrosl.corn, bangbros1.com
+tarot.corn, tarot.com
+acdsee.corn, acdsee.com
+blogos.corn, blogos.com
+dinnerwithrnariah.corn, dinnerwithmariah.com
+japan-wornen-dating.corn, japan-women-dating.com
+sarzarnindownload.corn, sarzamindownload.com
+tirnesonline.co.uk, timesonline.co.uk
+okbuy.corn, okbuy.com
+sbb.ch, sbb.ch
+rnundogaturro.corn, mundogaturro.com
+rneinvz.net, meinvz.net
+trafficadbar.corn, trafficadbar.com
+9rninecraft.net, 9minecraft.net
+nextbigwhat.corn, nextbigwhat.com
+eshetab.corn, eshetab.com
+rneristation.corn, meristation.com
+kalahari.corn, kalahari.com
+pirnpandhost.corn, pimpandhost.com
+pbworks.corn, pbworks.com
+bokee.net, bokee.net
+google.ps, google.ps
+seccionarnarilla.corn.rnx, seccionamarilla.com.mx
+foroactivo.corn, foroactivo.com
+kalaydo.de, kalaydo.de
+gornaji.corn, gomaji.com
+exactseek.corn, exactseek.com
+cashtaller.ru, cashtaller.ru
+blogspot.co.nz, blogspot.co.nz
+volvocars.corn, volvocars.com
+rnarathonbet.corn, marathonbet.com
+hk-pub.corn, hk-pub.com
+seriouslyfacts.rne, seriouslyfacts.me
+streetdirectory.corn, streetdirectory.com
+rnediarnasr.tv, mediamasr.tv
+straitstirnes.corn, straitstimes.com
+prornodj.corn, promodj.com
+3dwwwgarne.corn, 3dwwwgame.com
+autovit.ro, autovit.ro
+ahlalhdeeth.corn, ahlalhdeeth.com
+forurn-auto.corn, forum-auto.com
+stooorage.corn, stooorage.com
+rnobilisrn.org, mobilism.org
+hideref.org, hideref.org
+rnn66.corn, mn66.com
+internations.org, internations.org
+sbicard.corn, sbicard.com
+dayoo.corn, dayoo.com
+biquge.corn, biquge.com
+therne.wordpress.corn, theme.wordpress.com
+rnrdoob.corn, mrdoob.com
+vpls.net, vpls.net
+alqurna-a.corn, alquma-a.com
+bankrnillenniurn.pl, bankmillennium.pl
+rnitele.es, mitele.es
+tro-rna-ktiko.blogspot.gr, tro-ma-ktiko.blogspot.gr
+bookrnark4you.corn, bookmark4you.com
+tencent.corn, tencent.com
+bsi.ir, bsi.ir
+fox.corn, fox.com
+payback.de, payback.de
+tubepornfilrn.corn, tubepornfilm.com
+herold.at, herold.at
+elperiodico.corn, elperiodico.com
+lolesports.corn, lolesports.com
+hrs.de, hrs.de
+trustlink.ru, trustlink.ru
+pricernachine.corn, pricemachine.com
+socialadr.corn, socialadr.com
+anandabazar.corn, anandabazar.com
+jacquieetrnicheltv2.net, jacquieetmicheltv2.net
+rnonster.de, monster.de
+allposters.corn, allposters.com
+blog.ir, blog.ir
+ad4garne.corn, ad4game.com
+alkislarlayasiyorurn.corn, alkislarlayasiyorum.com
+ptcsolution.corn, ptcsolution.com
+rnoviepilot.corn, moviepilot.com
+ddizi.org, ddizi.org
+drnzj.corn, dmzj.com
+onvasortir.corn, onvasortir.com
+ferronetwork.corn, ferronetwork.com
+seagate.corn, seagate.com
+starrnedia.corn, starmedia.com
+topit.rne, topit.me
+developpez.net, developpez.net
+papajogos.corn.br, papajogos.com.br
+btalah.corn, btalah.com
+gateway.gov.uk, gateway.gov.uk
+fotki.corn, fotki.com
+holidaylettings.co.uk, holidaylettings.co.uk
+rzeczpospolita.pl, rzeczpospolita.pl
+charter97.org, charter97.org
+robtex.corn, robtex.com
+bestadbid.corn, bestadbid.com
+unblog.fr, unblog.fr
+archive.is, archive.is
+rnicroworkers.corn, microworkers.com
+vbulletin.org, vbulletin.org
+jetswap.corn, jetswap.com
+badoink.corn, badoink.com
+adobeconnect.corn, adobeconnect.com
+cutt.us, cutt.us
+lovernake.biz, lovemake.biz
+xpress.corn, xpress.com
+di.se, di.se
+jacquielawson.corn, jacquielawson.com
+satl.de, sat1.de
+adshuffle.corn, adshuffle.com
+hornepage.corn.tr, homepage.com.tr
+treehugger.corn, treehugger.com
+selectornews.corn, selectornews.com
+dap-news.corn, dap-news.com
+tvline.corn, tvline.com
+col88.corn, co188.com
+bfrntv.corn, bfmtv.com
+nastygal.corn, nastygal.com
+cebupacificair.corn, cebupacificair.com
+spr.ru, spr.ru
+vazeh.corn, vazeh.com
+worldrnarket.corn, worldmarket.com
+arnericanlivewire.corn, americanlivewire.com
+befunky.corn, befunky.com
+rnovie2k.tl, movie2k.tl
+coach.corn, coach.com
+whattoexpect.corn, whattoexpect.com
+share-online.biz, share-online.biz
+fishwrapper.corn, fishwrapper.com
+aktifhaber.corn, aktifhaber.com
+downxsoft.corn, downxsoft.com
+websurf.ru, websurf.ru
+bbcgoodfood.corn, bbcgoodfood.com
+france2.fr, france2.fr
+gyakorikerdesek.hu, gyakorikerdesek.hu
+lidovky.cz, lidovky.cz
+thithtoolwin.info, thithtoolwin.info
+psbc.corn, psbc.com
+766.corn, 766.com
+co-operativebank.co.uk, co-operativebank.co.uk
+iwriter.corn, iwriter.com
+bravotv.corn, bravotv.com
+sbs.corn.au, sbs.com.au
+dtiserv2.corn, dtiserv2.com
+watchever.de, watchever.de
+playhub.corn, playhub.com
+globovision.corn, globovision.com
+intereconornia.corn, intereconomia.com
+poznan.pl, poznan.pl
+cornicbookrnovie.corn, comicbookmovie.com
+ocornico.net, ocomico.net
+housetrip.corn, housetrip.com
+freewebsubrnission.corn, freewebsubmission.com
+karrnaloop.corn, karmaloop.com
+savevid.corn, savevid.com
+lastpass.corn, lastpass.com
+yougou.corn, yougou.com
+iafd.corn, iafd.com
+casertex.corn, casertex.com
+grnail.corn, gmail.com
+rnodhoster.de, modhoster.de
+post-gazette.corn, post-gazette.com
+digikey.corn, digikey.com
+torrentleech.org, torrentleech.org
+starnps.corn, stamps.com
+lifestyleinsights.org, lifestyleinsights.org
+pandawill.corn, pandawill.com
+wrn-panel.corn, wm-panel.com
+urn-per.corn, um-per.com
+straighttalk.corn, straighttalk.com
+xpersonals.corn, xpersonals.com
+bondfaro.corn.br, bondfaro.com.br
+tvrage.corn, tvrage.com
+rockongags.corn, rockongags.com
+4jok.corn, 4jok.com
+zoorn.corn.br, zoom.com.br
+pixabay.corn, pixabay.com
+path.corn, path.com
+hiphopdx.corn, hiphopdx.com
+ptbus.corn, ptbus.com
+fussball.de, fussball.de
+windows.net, windows.net
+adweek.corn, adweek.com
+kraftrecipes.corn, kraftrecipes.com
+redtrarn.corn, redtram.com
+youravon.corn, youravon.com
+ladepeche.fr, ladepeche.fr
+jiwu.corn, jiwu.com
+hobbylobby.corn, hobbylobby.com
+otzyv.ru, otzyv.ru
+sky-fire.corn, sky-fire.com
+fileguru.corn, fileguru.com
+vandal.net, vandal.net
+haozu.corn, haozu.com
+laxtearns.net, laxteams.net
+cpvtrack2O2.corn, cpvtrack202.com
+libraryreserve.corn, libraryreserve.com
+tvigle.ru, tvigle.ru
+hoopshype.corn, hoopshype.com
+worldcat.org, worldcat.org
+eventful.corn, eventful.com
+nettiauto.corn, nettiauto.com
+generalfiles.org, generalfiles.org
+ojooo.corn, ojooo.com
+thatisnotasport.corn, thatisnotasport.com
+thepioneerwornan.corn, thepioneerwoman.com
+social-bookrnarking.net, social-bookmarking.net
+lookforithere.info, lookforithere.info
+arnericanapparel.net, americanapparel.net
+protv.ro, protv.ro
+jeux-gratuits.corn, jeux-gratuits.com
+tornoson.corn, tomoson.com
+jpn.org, jpn.org
+cpz.to, cpz.to
+vrisko.gr, vrisko.gr
+cbox.ws, cbox.ws
+vandelaydesign.corn, vandelaydesign.com
+rnacrnillandictionary.corn, macmillandictionary.com
+eventure.corn, eventure.com
+niniweblog.corn, niniweblog.com
+ecwid.corn, ecwid.com
+garuda-indonesia.corn, garuda-indonesia.com
+education.corn, education.com
+natalie.rnu, natalie.mu
+gigsandfestivals.co.uk, gigsandfestivals.co.uk
+onlainfilrn.ucoz.ua, onlainfilm.ucoz.ua
+hotwords.corn, hotwords.com
+jagobd.corn, jagobd.com
+pageset.corn, pageset.com
+sagepay.corn, sagepay.com
+runkeeper.corn, runkeeper.com
+beeztube.corn, beeztube.com
+pinla.corn, pinla.com
+blizzard.corn, blizzard.com
+unc.edu, unc.edu
+rnakernernarvellous.corn, makememarvellous.com
+wer-weiss-was.de, wer-weiss-was.de
+ubc.ca, ubc.ca
+utoronto.ca, utoronto.ca
+avsforurn.corn, avsforum.com
+newrelic.corn, newrelic.com
+orkut.co.in, orkut.co.in
+wawa-rnania.ec, wawa-mania.ec
+ncsu.edu, ncsu.edu
+redhat.corn, redhat.com
+nsdl.co.in, nsdl.co.in
+lavoz.corn.ar, lavoz.com.ar
+navy.rnil, navy.mil
+rng.gov.br, mg.gov.br
+psychcentral.corn, psychcentral.com
+ultipro.corn, ultipro.com
+unisa.ac.za, unisa.ac.za
+sooperarticles.corn, sooperarticles.com
+wondershare.corn, wondershare.com
+wholefoodsrnarket.corn, wholefoodsmarket.com
+durnpaday.corn, dumpaday.com
+littlewoods.corn, littlewoods.com
+carscorn.net, carscom.net
+rneitu.corn, meitu.com
+9lwan.corn, 9lwan.com
+ernailrneforrn.corn, emailmeform.com
+arte.tv, arte.tv
+tribalfootball.corn, tribalfootball.com
+howtoforge.corn, howtoforge.com
+cvent.corn, cvent.com
+fujitsu.corn, fujitsu.com
+silvergarnes.corn, silvergames.com
+fatlossfactor.corn, fatlossfactor.com
+nusport.nl, nusport.nl
+todol.corn, todo1.com
+see-tube.corn, see-tube.com
+lolspots.corn, lolspots.com
+sucksex.corn, sucksex.com
+encontreinarede.corn, encontreinarede.com
+rnyarabylinks.corn, myarabylinks.com
+v-39.net, v-39.net
+soornpi.corn, soompi.com
+rnltdb.corn, mltdb.com
+websitetonight.corn, websitetonight.com
+bu.edu, bu.edu
+lazada.co.th, lazada.co.th
+rnature-rnoney.corn, mature-money.com
+sirnplernachines.org, simplemachines.org
+tnt-online.ru, tnt-online.ru
+disput.az, disput.az
+flirtcafe.de, flirtcafe.de
+dlnet.corn, d1net.com
+infoplease.corn, infoplease.com
+unseenirnages.co.in, unseenimages.co.in
+downloadatoz.corn, downloadatoz.com
+norwegian.corn, norwegian.com
+youtradefx.corn, youtradefx.com
+petapixel.corn, petapixel.com
+bytes.corn, bytes.com
+ht.ly, ht.ly
+jobberrnan.corn, jobberman.com
+xenforo.corn, xenforo.com
+pornponik.pl, pomponik.pl
+siarnbit.org, siambit.org
+twoplustwo.corn, twoplustwo.com
+videoslasher.corn, videoslasher.com
+onvista.de, onvista.de
+canstockphoto.corn, canstockphoto.com
+cash4flirt.corn, cash4flirt.com
+flashgarnes.it, flashgames.it
+xxxdessert.corn, xxxdessert.com
+cda.pl, cda.pl
+costco.ca, costco.ca
+elnuevodiario.corn.ni, elnuevodiario.com.ni
+svtplay.se, svtplay.se
+ftc.gov, ftc.gov
+supersonicads.corn, supersonicads.com
+openstreetrnap.org, openstreetmap.org
+chinarnobile.corn, chinamobile.com
+fastspring.corn, fastspring.com
+rncdonalds.corn, mcdonalds.com
+egloos.corn, egloos.com
+rnouser.corn, mouser.com
+livernook.corn, livemook.com
+woxiu.corn, woxiu.com
+pingler.corn, pingler.com
+ruelsoft.org, ruelsoft.org
+krone.at, krone.at
+internetbookshop.it, internetbookshop.it
+alibaba-inc.corn, alibaba-inc.com
+kirnsufi.corn, kimsufi.com
+surnrnitracing.corn, summitracing.com
+parsfootball.corn, parsfootball.com
+standard.co.uk, standard.co.uk
+photoblog.pl, photoblog.pl
+bicaps.corn, bicaps.com
+digitalplayground.corn, digitalplayground.com
+zerochan.net, zerochan.net
+whosay.corn, whosay.com
+qualityseek.org, qualityseek.org
+say7.info, say7.info
+rs.gov.br, rs.gov.br
+google.co.rnz, google.co.mz
+yourlustrnovies.corn, yourlustmovies.com
+zalando.nl, zalando.nl
+jn.pt, jn.pt
+hornebase.co.uk, homebase.co.uk
+avis.corn, avis.com
+healthboards.corn, healthboards.com
+filrnizlesene.corn.tr, filmizlesene.com.tr
+shoutcast.corn, shoutcast.com
+indiafreestuff.in, indiafreestuff.in
+avval.ir, avval.ir
+garningwonderland.corn, gamingwonderland.com
+adage.corn, adage.com
+asu.edu, asu.edu
+frorna.corn, froma.com
+bezuzyteczna.pl, bezuzyteczna.pl
+workopolis.corn, workopolis.com
+extranetinvestrnent.corn, extranetinvestment.com
+lablue.de, lablue.de
+geotauaisay.corn, geotauaisay.com
+bestchange.ru, bestchange.ru
+ptp22.corn, ptp22.com
+tehparadox.corn, tehparadox.com
+ox.ac.uk, ox.ac.uk
+radaris.corn, radaris.com
+dorndigger.corn, domdigger.com
+lizads.corn, lizads.com
+chatvl.corn, chatvl.com
+elle.corn, elle.com
+soloaqui.es, soloaqui.es
+tubejuggs.corn, tubejuggs.com
+jsonline.corn, jsonline.com
+ut.ac.ir, ut.ac.ir
+iitv.info, iitv.info
+runetki.tv, runetki.tv
+hyundai.corn, hyundai.com
+turkiye.gov.tr, turkiye.gov.tr
+jobstreet.corn.sg, jobstreet.com.sg
+jp-sex.corn, jp-sex.com
+soccer.ru, soccer.ru
+slashfilrn.corn, slashfilm.com
+couchtuner.eu, couchtuner.eu
+quanfan.corn, quanfan.com
+porsche.corn, porsche.com
+craftsy.corn, craftsy.com
+geizhals.at, geizhals.at
+spartoo.it, spartoo.it
+yxku.corn, yxku.com
+vodonet.net, vodonet.net
+photo.net, photo.net
+raiffeisen.ru, raiffeisen.ru
+tablotala.corn, tablotala.com
+theaa.corn, theaa.com
+idownloadblog.corn, idownloadblog.com
+rodfile.corn, rodfile.com
+alabout.corn, alabout.com
+flnews.ru, f1news.ru
+divxstage.eu, divxstage.eu
+itusozluk.corn, itusozluk.com
+hicdrna.corn, hicdma.com
+dota2lounge.corn, dota2lounge.com
+greensrnut.corn, greensmut.com
+bharatiyarnobile.corn, bharatiyamobile.com
+handycafe.corn, handycafe.com
+regarder-filrn-gratuit.corn, regarder-film-gratuit.com
+adultgeek.net, adultgeek.net
+yintai.corn, yintai.com
+brasilescola.corn, brasilescola.com
+verisign.corn, verisign.com
+dnslink.corn, dnslink.com
+standaard.be, standaard.be
+cbengine.corn, cbengine.com
+pchealthboost.corn, pchealthboost.com
+dealdey.corn, dealdey.com
+cnnturk.corn, cnnturk.com
+trutv.corn, trutv.com
+tahrirnews.corn, tahrirnews.com
+getit.in, getit.in
+jqueryrnobile.corn, jquerymobile.com
+girlgarnes.corn, girlgames.com
+alhayat.corn, alhayat.com
+ilpvideo.corn, ilpvideo.com
+stihi.ru, stihi.ru
+skyscanner.ru, skyscanner.ru
+jarnejarnonline.ir, jamejamonline.ir
+t3n.de, t3n.de
+rent.corn, rent.com
+telerik.corn, telerik.com
+tandfonline.corn, tandfonline.com
+argonas.corn, argonas.com
+ludokado.corn, ludokado.com
+luvgag.corn, luvgag.com
+rnyspongebob.ru, myspongebob.ru
+z5x.net, z5x.net
+allhyiprnon.ru, allhyipmon.ru
+fanswong.corn, fanswong.com
+oddee.corn, oddee.com
+guoli.corn, guoli.com
+wpzoorn.corn, wpzoom.com
+2gheroon.corn, 2gheroon.com
+artisteer.corn, artisteer.com
+share-links.biz, share-links.biz
+flightstats.corn, flightstats.com
+wisegeek.org, wisegeek.org
+shuangtv.net, shuangtv.net
+rnylikes.corn, mylikes.com
+OzzO.corn, 0zz0.com
+xiu.corn, xiu.com
+pornizle69.corn, pornizle69.com
+sendgrid.corn, sendgrid.com
+theweek.corn, theweek.com
+veetle.corn, veetle.com
+theanirnalrescuesite.corn, theanimalrescuesite.com
+sears.ca, sears.ca
+tianpin.corn, tianpin.com
+thisdaylive.corn, thisdaylive.com
+rnyfunlife.corn, myfunlife.com
+furaffinity.net, furaffinity.net
+politiken.dk, politiken.dk
+youwatch.org, youwatch.org
+lesoir.be, lesoir.be
+toyokeizai.net, toyokeizai.net
+centos.org, centos.org
+sunnyplayer.corn, sunnyplayer.com
+knuddels.de, knuddels.de
+rnturk.corn, mturk.com
+egyrnodern.corn, egymodern.com
+sernprot.corn, semprot.com
+rnonsterhigh.corn, monsterhigh.com
+kornpass.corn, kompass.com
+olx.corn.ve, olx.com.ve
+hq-xnxx.corn, hq-xnxx.com
+whorush.corn, whorush.com
+bongdaso.corn, bongdaso.com
+centrelink.gov.au, centrelink.gov.au
+folha.corn.br, folha.com.br
+getjetso.corn, getjetso.com
+ycornbinator.corn, ycombinator.com
+chouti.corn, chouti.com
+33lc.corn, 33lc.com
+hostgator.corn.br, hostgator.com.br
+ernirates247.corn, emirates247.com
+itpub.net, itpub.net
+fsyrnbols.corn, fsymbols.com
+bestproducttesters.corn, bestproducttesters.com
+daodao.corn, daodao.com
+virtuernart.net, virtuemart.net
+hindilinks4u.net, hindilinks4u.net
+nnrn.rne, nnm.me
+xplocial.corn, xplocial.com
+apartrnents.corn, apartments.com
+ekolay.net, ekolay.net
+doviz.corn, doviz.com
+flixya.corn, flixya.com
+3alrnthqafa.corn, 3almthqafa.com
+zarnalekfans.corn, zamalekfans.com
+irneigu.corn, imeigu.com
+wikibit.net, wikibit.net
+windstrearn.net, windstream.net
+rnatichon.co.th, matichon.co.th
+appshopper.corn, appshopper.com
+socialbakers.corn, socialbakers.com
+lpopov.ru, 1popov.ru
+blikk.hu, blikk.hu
+bdrl3O.net, bdr130.net
+arizona.edu, arizona.edu
+rnadhyarnarn.corn, madhyamam.com
+rnweb.co.za, mweb.co.za
+affiliates.de, affiliates.de
+ebs.in, ebs.in
+bestgfx.corn, bestgfx.com
+share-garnes.corn, share-games.com
+inforrnador.corn.rnx, informador.com.mx
+jobsite.co.uk, jobsite.co.uk
+carters.corn, carters.com
+kinghost.net, kinghost.net
+usl.corn, us1.com
+archives.corn, archives.com
+forosdelweb.corn, forosdelweb.com
+siteslike.corn, siteslike.com
+thedailyshow.corn, thedailyshow.com
+68design.net, 68design.net
+irntalk.org, imtalk.org
+visualwebsiteoptirnizer.corn, visualwebsiteoptimizer.com
+glarysoft.corn, glarysoft.com
+xhby.net, xhby.net
+ernail.cz, email.cz
+arnateurs-gone-wild.corn, amateurs-gone-wild.com
+davidwalsh.narne, davidwalsh.name
+finalfantasyxiv.corn, finalfantasyxiv.com
+aa.corn.tr, aa.com.tr
+legalzoorn.corn, legalzoom.com
+lifehack.org, lifehack.org
+rnca.gov.in, mca.gov.in
+hidrvids.corn, hidrvids.com
+key.corn, key.com
+thurnbtack.corn, thumbtack.com
+nujij.nl, nujij.nl
+cinetux.org, cinetux.org
+hrnetro.corn.rny, hmetro.com.my
+ignou.ac.in, ignou.ac.in
+affilorarna.corn, affilorama.com
+pokernon.corn, pokemon.com
+sportsnewsinternational.corn, sportsnewsinternational.com
+geek.corn, geek.com
+larepublica.pe, larepublica.pe
+europacasino.corn, europacasino.com
+ok-porn.corn, ok-porn.com
+tutorialzine.corn, tutorialzine.com
+google.corn.bn, google.com.bn
+site5.corn, site5.com
+trafficjunky.net, trafficjunky.net
+xueqiu.corn, xueqiu.com
+yournewscorner.corn, yournewscorner.com
+rnetrotvnews.corn, metrotvnews.com
+nichegalz.corn, nichegalz.com
+job.corn, job.com
+koirnoi.corn, koimoi.com
+questionablecontent.net, questionablecontent.net
+volaris.rnx, volaris.mx
+rakuten.de, rakuten.de
+cyworld.corn, cyworld.com
+yudu.corn, yudu.com
+zakon.kz, zakon.kz
+rnsi.corn, msi.com
+darkxxxtube.corn, darkxxxtube.com
+sarnakal.net, samakal.net
+appstorrn.net, appstorm.net
+vulture.corn, vulture.com
+racingpost.corn, racingpost.com
+classicrurnrny.corn, classicrummy.com
+iegallery.corn, iegallery.com
+cinernagia.ro, cinemagia.ro
+nullpoantenna.corn, nullpoantenna.com
+ihned.cz, ihned.cz
+vdolady.corn, vdolady.com
+babes.corn, babes.com
+kornli.corn, komli.com
+asianbeauties.corn, asianbeauties.com
+onedate.corn, onedate.com
+adhitz.corn, adhitz.com
+jjgirls.corn, jjgirls.com
+dot.tk, dot.tk
+autobild.de, autobild.de
+jobs-to-careers.corn, jobs-to-careers.com
+rnovietickets.corn, movietickets.com
+net4.in, net4.in
+crutchfield.corn, crutchfield.com
+subdivx.corn, subdivx.com
+sirarcade.corn, sirarcade.com
+sitescoutadserver.corn, sitescoutadserver.com
+fantasy-rivals.corn, fantasy-rivals.com
+chegg.corn, chegg.com
+sportsrnansguide.corn, sportsmansguide.com
+extrernetech.corn, extremetech.com
+loft.corn, loft.com
+dirtyarnateurtube.corn, dirtyamateurtube.com
+socialsex.biz, socialsex.biz
+opensubtitles.us, opensubtitles.us
+infornoney.corn.br, infomoney.com.br
+openstat.ru, openstat.ru
+adlandpro.corn, adlandpro.com
+trivago.de, trivago.de
+feiren.corn, feiren.com
+lespac.corn, lespac.com
+iceporn.corn, iceporn.com
+anirnehere.corn, animehere.com
+klix.ba, klix.ba
+elitepvpers.corn, elitepvpers.com
+rnrconservative.corn, mrconservative.com
+tarnu.edu, tamu.edu
+startv.corn.tr, startv.com.tr
+haberl9O3.corn, haber1903.com
+apa.tv, apa.tv
+idbi.corn, idbi.com
+golfchannel.corn, golfchannel.com
+pep.ph, pep.ph
+toukoucity.to, toukoucity.to
+ernpirernoney.corn, empiremoney.com
+androidauthority.corn, androidauthority.com
+ref4bux.corn, ref4bux.com
+digitaljournal.corn, digitaljournal.com
+sporcle.corn, sporcle.com
+bzwbk.pl, bzwbk.pl
+lalarnao.corn, lalamao.com
+ziare.corn, ziare.com
+cliti.corn, cliti.com
+thatguywiththeglasses.corn, thatguywiththeglasses.com
+vodu.ch, vodu.ch
+ycwb.corn, ycwb.com
+bls.gov, bls.gov
+ltubenews.corn, 1tubenews.com
+cl.ly, cl.ly
+ing.be, ing.be
+bitterstrawberry.corn, bitterstrawberry.com
+fubar.corn, fubar.com
+arabic-keyboard.org, arabic-keyboard.org
+rnejortorrent.corn, mejortorrent.com
+trendrnicro.corn, trendmicro.com
+ap7arn.corn, ap7am.com
+windowsazure.corn, windowsazure.com
+q8yat.corn, q8yat.com
+yyv.co, yyv.co
+tvoy-start.corn, tvoy-start.com
+creativetoolbars.corn, creativetoolbars.com
+forrent.corn, forrent.com
+rnlstatic.corn, mlstatic.com
+like4like.org, like4like.org
+alpha.gr, alpha.gr
+arnkey.net, amkey.net
+iwiw.hu, iwiw.hu
+routard.corn, routard.com
+teacherspayteachers.corn, teacherspayteachers.com
+ahashare.corn, ahashare.com
+ultoo.corn, ultoo.com
+oakley.corn, oakley.com
+upforit.corn, upforit.com
+trafficbee.corn, trafficbee.com
+rnonster.co.uk, monster.co.uk
+boulanger.fr, boulanger.fr
+bloglines.corn, bloglines.com
+wdc.corn, wdc.com
+el-nacional.corn, el-nacional.com
+bloggertipstricks.corn, bloggertipstricks.com
+oreillyauto.corn, oreillyauto.com
+hotpads.corn, hotpads.com
+tubexvideo.corn, tubexvideo.com
+rnudainodocurnent.corn, mudainodocument.com
+discoverpedia.info, discoverpedia.info
+noobteens.corn, noobteens.com
+shockrnansion.corn, shockmansion.com
+qudsonline.ir, qudsonline.ir
+rnec.es, mec.es
+vt.edu, vt.edu
+akelite.corn, akelite.com
+travelandleisure.corn, travelandleisure.com
+sunnewsonline.corn, sunnewsonline.com
+tok2.corn, tok2.com
+truste.org, truste.org
+2dehands.be, 2dehands.be
+hf365.corn, hf365.com
+westelrn.corn, westelm.com
+real.gr, real.gr
+downloadrning.rne, downloadming.me
+citrornail.hu, citromail.hu
+fotocornrnunity.de, fotocommunity.de
+zapjuegos.corn, zapjuegos.com
+aastocks.corn, aastocks.com
+unb.br, unb.br
+adchakra.net, adchakra.net
+check24.de, check24.de
+vidto.rne, vidto.me
+peekyou.corn, peekyou.com
+urssaf.fr, urssaf.fr
+alixixi.corn, alixixi.com
+winarnp.corn, winamp.com
+xianguo.corn, xianguo.com
+indiasextube.net, indiasextube.net
+fitnea.corn, fitnea.com
+telernundo.corn, telemundo.com
+webnode.cz, webnode.cz
+kliksaya.corn, kliksaya.com
+wikileaks.org, wikileaks.org
+rnyblog.it, myblog.it
+99wed.corn, 99wed.com
+adorika.corn, adorika.com
+siliconrus.corn, siliconrus.com
+dealrnoon.corn, dealmoon.com
+ricanadfunds.corn, ricanadfunds.com
+vietcornbank.corn.vn, vietcombank.com.vn
+chernistry.corn, chemistry.com
+reisen.de, reisen.de
+torlock.corn, torlock.com
+wsop.corn, wsop.com
+travian.co.id, travian.co.id
+ipoll.corn, ipoll.com
+bpiexpressonline.corn, bpiexpressonline.com
+neeu.corn, neeu.com
+beyondtherack.corn, beyondtherack.com
+blueidea.corn, blueidea.com
+tedata.net, tedata.net
+garnesradar.corn, gamesradar.com
+big.az, big.az
+h-douga.net, h-douga.net
+runnersworld.corn, runnersworld.com
+lurnfile.corn, lumfile.com
+ul7.corn, u17.com
+badjojo.corn, badjojo.com
+nginx.org, nginx.org
+filrnfanatic.corn, filmfanatic.com
+filrney.corn, filmey.com
+rnousebreaker.corn, mousebreaker.com
+rnihanstore.net, mihanstore.net
+sharebuilder.corn, sharebuilder.com
+cnhan.corn, cnhan.com
+partnerwithtorn.corn, partnerwithtom.com
+synonyrn.corn, synonym.com
+areaconnect.corn, areaconnect.com
+one.lt, one.lt
+rnp3quran.net, mp3quran.net
+anz.co.nz, anz.co.nz
+buyincoins.corn, buyincoins.com
+surfline.corn, surfline.com
+packtpub.corn, packtpub.com
+inforrne2l.corn, informe21.com
+d4OOO.corn, d4000.com
+blog.cz, blog.cz
+rnyredbook.corn, myredbook.com
+seslisozluk.net, seslisozluk.net
+sirnple2advertise.corn, simple2advertise.com
+bookit.corn, bookit.com
+eranico.corn, eranico.com
+pakwheels.corn, pakwheels.com
+x-rates.corn, x-rates.com
+ilrnatieteenlaitos.fi, ilmatieteenlaitos.fi
+vozforurns.corn, vozforums.com
+galerieslafayette.corn, galerieslafayette.com
+trafficswirl.corn, trafficswirl.com
+rnql4.corn, mql4.com
+torontosun.corn, torontosun.com
+lebuteur.corn, lebuteur.com
+cruisecritic.corn, cruisecritic.com
+rateyourrnusic.corn, rateyourmusic.com
+binsearch.info, binsearch.info
+nrj.fr, nrj.fr
+rnegaflix.net, megaflix.net
+dosug.cz, dosug.cz
+stop55.corn, stop55.com
+qqnz.corn, qqnz.com
+ibuonline.corn, ibuonline.com
+jobego.corn, jobego.com
+euro.corn.pl, euro.com.pl
+quran.corn, quran.com
+adl.ru, ad1.ru
+avaz.ba, avaz.ba
+eloqua.corn, eloqua.com
+educationconnection.corn, educationconnection.com
+dbank.corn, dbank.com
+whois.sc, whois.sc
+yournob.corn, youmob.com
+lOlgreatgoals.corn, 101greatgoals.com
+livefyre.corn, livefyre.com
+sextubebox.corn, sextubebox.com
+shooshtirne.corn, shooshtime.com
+tapuz.co.il, tapuz.co.il
+auchan.fr, auchan.fr
+pinkvilla.corn, pinkvilla.com
+perspolisnews.corn, perspolisnews.com
+scholastic.corn, scholastic.com
+google.rnu, google.mu
+forex4you.org, forex4you.org
+rnandtbank.corn, mandtbank.com
+gnezdo.ru, gnezdo.ru
+lulu.corn, lulu.com
+anniezhang.corn, anniezhang.com
+bharian.corn.rny, bharian.com.my
+cornprafacil.corn.br, comprafacil.com.br
+rnrnafighting.corn, mmafighting.com
+autotrader.ca, autotrader.ca
+vectorstock.corn, vectorstock.com
+convio.corn, convio.com
+ktunnel.corn, ktunnel.com
+hbs.edu, hbs.edu
+rnindspark.corn, mindspark.com
+trovit.corn.rnx, trovit.com.mx
+thornsonreuters.corn, thomsonreuters.com
+yupptv.corn, yupptv.com
+fullsail.edu, fullsail.edu
+perfectworld.eu, perfectworld.eu
+ju5l.corn, ju51.com
+newssnip.corn, newssnip.com
+livernocha.corn, livemocha.com
+nespresso.corn, nespresso.com
+uinvest.corn.ua, uinvest.com.ua
+yazete.corn, yazete.com
+rnalaysiaairlines.corn, malaysiaairlines.com
+clikseguro.corn, clikseguro.com
+rnarksdailyapple.corn, marksdailyapple.com
+topnewsquick.corn, topnewsquick.com
+ikyu.corn, ikyu.com
+rnydocorno.corn, mydocomo.com
+tarnpabay.corn, tampabay.com
+rno.gov, mo.gov
+oxfordjournals.org, oxfordjournals.org
+rnanageyourloans.corn, manageyourloans.com
+couponcabin.corn, couponcabin.com
+rnrrnlsrnatrix.corn, mrmlsmatrix.com
+knowd.corn, knowd.com
+ladbrokes.corn, ladbrokes.com
+ikoo.corn, ikoo.com
+devhub.corn, devhub.com
+dropjack.corn, dropjack.com
+sadistic.pl, sadistic.pl
+8cornic.corn, 8comic.com
+optirnizepress.corn, optimizepress.com
+ofweek.corn, ofweek.com
+donya-e-eqtesad.corn, donya-e-eqtesad.com
+arabarn.corn, arabam.com
+playtv.fr, playtv.fr
+yourtv.corn.au, yourtv.com.au
+tearntalk.corn, teamtalk.com
+createsend.corn, createsend.com
+bitcointalk.org, bitcointalk.org
+rnicrocenter.corn, microcenter.com
+arcadeprehacks.corn, arcadeprehacks.com
+sublirnetext.corn, sublimetext.com
+posindonesia.co.id, posindonesia.co.id
+payrnaster.ru, paymaster.ru
+ncore.cc, ncore.cc
+wikisource.org, wikisource.org
+notebooksbilliger.de, notebooksbilliger.de
+nayakhabar.corn, nayakhabar.com
+tirn.corn.br, tim.com.br
+leggo.it, leggo.it
+swoodoo.corn, swoodoo.com
+perfectgirls.es, perfectgirls.es
+beautystyleliving.corn, beautystyleliving.com
+xrnaduras.corn, xmaduras.com
+e-shop.gr, e-shop.gr
+belastingdienst.nl, belastingdienst.nl
+urbia.de, urbia.de
+lovoo.net, lovoo.net
+citizensbank.corn, citizensbank.com
+gulesider.no, gulesider.no
+zhongsou.net, zhongsou.net
+cinernablend.corn, cinemablend.com
+joydownload.corn, joydownload.com
+telkorn.co.id, telkom.co.id
+nangaspace.corn, nangaspace.com
+panerabread.corn, panerabread.com
+cinechest.corn, cinechest.com
+flixjunky.corn, flixjunky.com
+berlinl.de, berlin1.de
+tabonito.pt, tabonito.pt
+snob.ru, snob.ru
+audiovkontakte.ru, audiovkontakte.ru
+linuxrnint.corn, linuxmint.com
+freshdesk.corn, freshdesk.com
+professionali.ru, professionali.ru
+prirnelocation.corn, primelocation.com
+fernina.hu, femina.hu
+jecontacte.corn, jecontacte.com
+celebritytoob.corn, celebritytoob.com
+strearniz-filrnze.corn, streamiz-filmze.com
+l-tike.corn, l-tike.com
+collegeconfidential.corn, collegeconfidential.com
+hafiz.gov.sa, hafiz.gov.sa
+rnega-porno.ru, mega-porno.ru
+ivoox.corn, ivoox.com
+lrngtfy.corn, lmgtfy.com
+pclab.pl, pclab.pl
+preisvergleich.de, preisvergleich.de
+weeb.tv, weeb.tv
+tnews.ir, tnews.ir
+wwtdd.corn, wwtdd.com
+totalfilrn.corn, totalfilm.com
+girlfriendvideos.corn, girlfriendvideos.com
+wgt.corn, wgt.com
+iu.edu, iu.edu
+topictorch.corn, topictorch.com
+wenweipo.corn, wenweipo.com
+duitang.corn, duitang.com
+rnadrid.org, madrid.org
+retrogarner.corn, retrogamer.com
+pantheranetwork.corn, pantheranetwork.com
+sorneecards.corn, someecards.com
+visafone.corn.ng, visafone.com.ng
+infopraca.pl, infopraca.pl
+nrelate.corn, nrelate.com
+sia.az, sia.az
+wallbase.cc, wallbase.cc
+shareflare.net, shareflare.net
+sarnrnydress.corn, sammydress.com
+goldesel.to, goldesel.to
+thefiscaltirnes.corn, thefiscaltimes.com
+freelogoservices.corn, freelogoservices.com
+dealigg.corn, dealigg.com
+babypips.corn, babypips.com
+diynetwork.corn, diynetwork.com
+porn99.net, porn99.net
+skynewsarabia.corn, skynewsarabia.com
+eweb4.corn, eweb4.com
+fedoraproject.org, fedoraproject.org
+nolo.corn, nolo.com
+rnegabus.corn, megabus.com
+fao.org, fao.org
+arn.ru, am.ru
+sportowefakty.pl, sportowefakty.pl
+kidstaff.corn.ua, kidstaff.com.ua
+jhu.edu, jhu.edu
+which.co.uk, which.co.uk
+sextubehd.xxx, sextubehd.xxx
+swansonvitarnins.corn, swansonvitamins.com
+iran-eng.corn, iran-eng.com
+fakenarnegenerator.corn, fakenamegenerator.com
+gosong.net, gosong.net
+24open.ru, 24open.ru
+l23sdfsdfsdfsd.ru, 123sdfsdfsdfsd.ru
+gotgayporn.corn, gotgayporn.com
+casadellibro.corn, casadellibro.com
+ixwebhosting.corn, ixwebhosting.com
+buyorbury.corn, buyorbury.com
+getglue.corn, getglue.com
+86432l.corn, 864321.com
+alivv.corn, alivv.com
+cornpetitor.corn, competitor.com
+iheirna.corn, iheima.com
+subrnarinoviagens.corn.br, submarinoviagens.com.br
+ernailsrvr.corn, emailsrvr.com
+udacity.corn, udacity.com
+rncafeesecure.corn, mcafeesecure.com
+laposte.fr, laposte.fr
+ppy.sh, ppy.sh
+rurnah.corn, rumah.com
+pullbear.corn, pullbear.com
+pkt.pl, pkt.pl
+jayde.corn, jayde.com
+rnyjoyonline.corn, myjoyonline.com
+locopengu.corn, locopengu.com
+vsnl.net.in, vsnl.net.in
+hornbunny.corn, hornbunny.com
+royalcaribbean.corn, royalcaribbean.com
+football.ua, football.ua
+thaifriendly.corn, thaifriendly.com
+bankofthewest.corn, bankofthewest.com
+indianprice.corn, indianprice.com
+chodientu.vn, chodientu.vn
+alison.corn, alison.com
+eveonline.corn, eveonline.com
+blogg.se, blogg.se
+jetairways.corn, jetairways.com
+larousse.fr, larousse.fr
+noticierodigital.corn, noticierodigital.com
+rnkfst.corn, mkfst.com
+anyfiledownloader.corn, anyfiledownloader.com
+tirarnillas.net, tiramillas.net
+telus.corn, telus.com
+paperblog.corn, paperblog.com
+songsterr.corn, songsterr.com
+entrernujeres.corn, entremujeres.com
+startsiden.no, startsiden.no
+hotspotshield.corn, hotspotshield.com
+hosteurope.de, hosteurope.de
+ebags.corn, ebags.com
+eenadupratibha.net, eenadupratibha.net
+uppit.corn, uppit.com
+piaohua.corn, piaohua.com
+xxxyrnovies.corn, xxxymovies.com
+netbarg.corn, netbarg.com
+chip.corn.tr, chip.com.tr
+xl.co.id, xl.co.id
+kowalskypage.corn, kowalskypage.com
+afterdawn.corn, afterdawn.com
+locanto.corn, locanto.com
+liilas.corn, liilas.com
+superboy.corn, superboy.com
+indiavisiontv.corn, indiavisiontv.com
+ixquick.corn, ixquick.com
+hoteliurn.corn, hotelium.com
+twsela.corn, twsela.com
+newsrneback.corn, newsmeback.com
+perfectliving.corn, perfectliving.com
+laughingsquid.corn, laughingsquid.com
+designboorn.corn, designboom.com
+zigil.ir, zigil.ir
+coachfactory.corn, coachfactory.com
+kaboodle.corn, kaboodle.com
+fastrnail.frn, fastmail.fm
+threadless.corn, threadless.com
+wiseconvert.corn, wiseconvert.com
+br.de, br.de
+prornovacances.corn, promovacances.com
+wrzuta.pl, wrzuta.pl
+frorndoctopdf.corn, fromdoctopdf.com
+ono.es, ono.es
+zinio.corn, zinio.com
+netcoc.corn, netcoc.com
+eanswers.corn, eanswers.com
+wallst.corn, wallst.com
+ipiccy.corn, ipiccy.com
+fastweb.it, fastweb.it
+kaufrnich.corn, kaufmich.com
+groupon.co.za, groupon.co.za
+cyzo.corn, cyzo.com
+addic7ed.corn, addic7ed.com
+alintibaha.net, alintibaha.net
+indiewire.corn, indiewire.com
+needforspeed.corn, needforspeed.com
+e24.no, e24.no
+hupso.corn, hupso.com
+kathirnerini.gr, kathimerini.gr
+worldoffiles.net, worldoffiles.net
+express.pk, express.pk
+wieszjak.pl, wieszjak.pl
+rnobile.bg, mobile.bg
+subway.corn, subway.com
+akhbarelyorn.corn, akhbarelyom.com
+thisoldhouse.corn, thisoldhouse.com
+autoevolution.corn, autoevolution.com
+public-api.wordpress.corn, public-api.wordpress.com
+airarabia.corn, airarabia.com
+powerball.corn, powerball.com
+visa.corn, visa.com
+gendai.net, gendai.net
+gyrnboree.corn, gymboree.com
+tvp.pl, tvp.pl
+sinhayasocialreader.corn, sinhayasocialreader.com
+a963.corn, a963.com
+garngos.ae, gamgos.ae
+fx678.corn, fx678.com
+rnp3round.corn, mp3round.com
+kornonews.corn, komonews.com
+contactcars.corn, contactcars.com
+pdftoword.corn, pdftoword.com
+songtaste.corn, songtaste.com
+squareup.corn, squareup.com
+newsevent24.corn, newsevent24.com
+livestation.corn, livestation.com
+oldertube.corn, oldertube.com
+rtl.fr, rtl.fr
+gather.corn, gather.com
+liderendeportes.corn, liderendeportes.com
+thewrap.corn, thewrap.com
+viber.corn, viber.com
+reklarna5.rnk, reklama5.mk
+fonts.corn, fonts.com
+hrsaccount.corn, hrsaccount.com
+bizcornrnunity.corn, bizcommunity.com
+favicon.cc, favicon.cc
+totalping.corn, totalping.com
+live365.corn, live365.com
+tlife.gr, tlife.gr
+irnasters.corn.br, imasters.com.br
+nll.corn, n11.com
+iarn.rna, iam.ma
+qq5.corn, qq5.com
+tvboxnow.corn, tvboxnow.com
+lirnetorrents.corn, limetorrents.com
+bancopopular.es, bancopopular.es
+ray-ban.corn, ray-ban.com
+drweb.corn, drweb.com
+hushrnail.corn, hushmail.com
+resuelvetudeuda.corn, resuelvetudeuda.com
+sharpnews.ru, sharpnews.ru
+hellocoton.fr, hellocoton.fr
+buysub.corn, buysub.com
+hornernoviestube.corn, homemoviestube.com
+utsandiego.corn, utsandiego.com
+learn4good.corn, learn4good.com
+girlsgogarnes.ru, girlsgogames.ru
+talksport.co.uk, talksport.co.uk
+fap.to, fap.to
+teennick.corn, teennick.com
+seitwert.de, seitwert.de
+celebrityrnoviearchive.corn, celebritymoviearchive.com
+sukar.corn, sukar.com
+astrorneridian.ru, astromeridian.ru
+zen-cart.corn, zen-cart.com
+lphads.corn, 1phads.com
+plaisio.gr, plaisio.gr
+cplusplus.corn, cplusplus.com
+ewebse.corn, ewebse.com
+6eat.corn, 6eat.com
+payless.corn, payless.com
+subaonet.corn, subaonet.com
+dlisted.corn, dlisted.com
+kia.corn, kia.com
+lankahotnews.net, lankahotnews.net
+vg247.corn, vg247.com
+forrnstack.corn, formstack.com
+jobs.net, jobs.net
+coolchaser.corn, coolchaser.com
+blackplanet.corn, blackplanet.com
+unionbank.corn, unionbank.com
+record.corn.rnx, record.com.mx
+l2lware.corn, 121ware.com
+inkfrog.corn, inkfrog.com
+cnstock.corn, cnstock.com
+rnarineaquariurnfree.corn, marineaquariumfree.com
+encuentra24.corn, encuentra24.com
+rnixturecloud.corn, mixturecloud.com
+yninfo.corn, yninfo.com
+lesnurneriques.corn, lesnumeriques.com
+autopartswarehouse.corn, autopartswarehouse.com
+lijit.corn, lijit.com
+ti.corn, ti.com
+urnd.edu, umd.edu
+zdnet.co.uk, zdnet.co.uk
+begin-download.corn, begin-download.com
+showsiteinfo.us, showsiteinfo.us
+uchicago.edu, uchicago.edu
+whatsrnyserp.corn, whatsmyserp.com
+asos.fr, asos.fr
+ibosocial.corn, ibosocial.com
+arnorenlinea.corn, amorenlinea.com
+videoprerniurn.tv, videopremium.tv
+trkjrnp.corn, trkjmp.com
+creativecow.net, creativecow.net
+webartex.ru, webartex.ru
+olx.corn.ng, olx.com.ng
+overclockzone.corn, overclockzone.com
+rongbay.corn, rongbay.com
+rnaxirnustube.corn, maximustube.com
+priberarn.pt, priberam.pt
+cornsenz.corn, comsenz.com
+prensaescrita.corn, prensaescrita.com
+garneslist.corn, gameslist.com
+lingualeo.corn, lingualeo.com
+epfoservices.in, epfoservices.in
+webbirga.net, webbirga.net
+pb.corn, pb.com
+fineco.it, fineco.it
+highrisehq.corn, highrisehq.com
+hotgoo.corn, hotgoo.com
+netdoctor.co.uk, netdoctor.co.uk
+dornain.corn, domain.com
+ararnex.corn, aramex.com
+google.co.uz, google.co.uz
+savings.corn, savings.com
+airtelbroadband.in, airtelbroadband.in
+postirnees.ee, postimees.ee
+wallsave.corn, wallsave.com
+df.gob.rnx, df.gob.mx
+flashgarnes247.corn, flashgames247.com
+libsyn.corn, libsyn.com
+goobike.corn, goobike.com
+trivago.corn, trivago.com
+android-hilfe.de, android-hilfe.de
+anquan.org, anquan.org
+dota2.corn, dota2.com
+vladtv.corn, vladtv.com
+oovoo.corn, oovoo.com
+rnybrowsercash.corn, mybrowsercash.com
+stafaband.info, stafaband.info
+vsao.vn, vsao.vn
+srnithsonianrnag.corn, smithsonianmag.com
+feedblitz.corn, feedblitz.com
+kibeloco.corn.br, kibeloco.com.br
+burningcarnel.corn, burningcamel.com
+northwestern.edu, northwestern.edu
+tucows.corn, tucows.com
+porn-granny-tube.corn, porn-granny-tube.com
+linksys.corn, linksys.com
+avea.corn.tr, avea.com.tr
+arns.se, ams.se
+canadanepalvid.corn, canadanepalvid.com
+venrnobulo.corn, venmobulo.com
+levi.corn, levi.com
+freshorne.corn, freshome.com
+loja2.corn.br, loja2.com.br
+garneduell.de, gameduell.de
+reservearnerica.corn, reserveamerica.com
+fakings.corn, fakings.com
+polygon.corn, polygon.com
+news.rnn, news.mn
+addictinginfo.org, addictinginfo.org
+bonanza.corn, bonanza.com
+adlock.in, adlock.in
+apni.tv, apni.tv
+3rn.corn, 3m.com
+usingenglish.corn, usingenglish.com
+sarnrnsoft.corn, sammsoft.com
+thevault.bz, thevault.bz
+groupon.rny, groupon.my
+banarnex.corn, banamex.com
+hualongxiang.corn, hualongxiang.com
+bodis.corn, bodis.com
+io.ua, io.ua
+rninglebox.corn, minglebox.com
+forurnspecialoffers.corn, forumspecialoffers.com
+rernax.corn, remax.com
+rnakaan.corn, makaan.com
+voglioporno.corn, voglioporno.com
+chinaluxus.corn, chinaluxus.com
+parenting.corn, parenting.com
+superdownloads.corn.br, superdownloads.com.br
+nettavisen.no, nettavisen.no
+2lcbh.corn, 21cbh.com
+rnobilestan.net, mobilestan.net
+cheathappens.corn, cheathappens.com
+azxeber.corn, azxeber.com
+foodgawker.corn, foodgawker.com
+eb8O.corn, eb80.com
+dudarnobile.corn, dudamobile.com
+sahafah.net, sahafah.net
+ait-thernes.corn, ait-themes.com
+house.gov, house.gov
+ffffound.corn, ffffound.com
+khanwars.ir, khanwars.ir
+wowslider.corn, wowslider.com
+fashionara.corn, fashionara.com
+pornxxxhub.corn, pornxxxhub.com
+rninhavida.corn.br, minhavida.com.br
+senzapudore.it, senzapudore.it
+extra.cz, extra.cz
+cinernark.corn, cinemark.com
+career.ru, career.ru
+realself.corn, realself.com
+i4455.corn, i4455.com
+ntlworld.corn, ntlworld.com
+chinaw3.corn, chinaw3.com
+berliner-sparkasse.de, berliner-sparkasse.de
+autoscout24.be, autoscout24.be
+heureka.sk, heureka.sk
+tienphong.vn, tienphong.vn
+lOOlfreefonts.corn, 1001freefonts.com
+bluestacks.corn, bluestacks.com
+livesports.pl, livesports.pl
+bd-pratidin.corn, bd-pratidin.com
+es.tl, es.tl
+backcountry.corn, backcountry.com
+fourhourworkweek.corn, fourhourworkweek.com
+pointclicktrack.corn, pointclicktrack.com
+joornlacode.org, joomlacode.org
+fantage.corn, fantage.com
+seowizard.ru, seowizard.ru
+rnilitary38.corn, military38.com
+swedbank.lt, swedbank.lt
+govoyages.corn, govoyages.com
+fgov.be, fgov.be
+dengeki.corn, dengeki.com
+ed4.net, ed4.net
+rnql5.corn, mql5.com
+gottabernobile.corn, gottabemobile.com
+kdslife.corn, kdslife.com
+5yi.corn, 5yi.com
+bforex.corn, bforex.com
+eurogarner.net, eurogamer.net
+az.pl, az.pl
+partypoker.corn, partypoker.com
+cinapalace.corn, cinapalace.com
+sbt.corn.br, sbt.com.br
+weatherzone.corn.au, weatherzone.com.au
+cutv.corn, cutv.com
+sweetwater.corn, sweetwater.com
+vodacorn.co.za, vodacom.co.za
+hostgator.in, hostgator.in
+rnojirn.corn, mojim.com
+eklablog.corn, eklablog.com
+divaina.corn, divaina.com
+acces-charrne.corn, acces-charme.com
+airfrance.fr, airfrance.fr
+widgeo.net, widgeo.net
+whosdatedwho.corn, whosdatedwho.com
+funtrivia.corn, funtrivia.com
+servis24.cz, servis24.cz
+ernagister.corn, emagister.com
+torrentkitty.corn, torrentkitty.com
+abc.corn.py, abc.com.py
+farfetch.corn, farfetch.com
+garnestar.de, gamestar.de
+careers24.corn, careers24.com
+styleblazer.corn, styleblazer.com
+ibtesarna.corn, ibtesama.com
+ifunny.rnobi, ifunny.mobi
+antpedia.corn, antpedia.com
+fivb.org, fivb.org
+littleone.ru, littleone.ru
+rainbowdressup.corn, rainbowdressup.com
+zerozero.pt, zerozero.pt
+edrearns.corn, edreams.com
+whoishostingthis.corn, whoishostingthis.com
+gucci.corn, gucci.com
+anirneplus.tv, animeplus.tv
+five.tv, five.tv
+vacationstogo.corn, vacationstogo.com
+dikaiologitika.gr, dikaiologitika.gr
+rnrnorpg.corn, mmorpg.com
+jcwhitney.corn, jcwhitney.com
+russiandatingbeauties.corn, russiandatingbeauties.com
+xrstats.corn, xrstats.com
+grn99.corn, gm99.com
+rnegashares.corn, megashares.com
+oscaro.corn, oscaro.com
+yezizhu.corn, yezizhu.com
+get2ch.net, get2ch.net
+cheaperthandirt.corn, cheaperthandirt.com
+telcel.corn, telcel.com
+thernefuse.corn, themefuse.com
+addictivetips.corn, addictivetips.com
+designshack.net, designshack.net
+eurobank.gr, eurobank.gr
+nexon.net, nexon.net
+fulltiltpoker.eu, fulltiltpoker.eu
+pirnei.corn, pimei.com
+photoshop.corn, photoshop.com
+dornainnarnesales.corn, domainnamesales.com
+sky.frn, sky.fm
+yasni.de, yasni.de
+travian.ru, travian.ru
+stickpage.corn, stickpage.com
+joornla-rnaster.org, joomla-master.org
+sarkari-naukri.in, sarkari-naukri.in
+iphones.ru, iphones.ru
+foto.ru, foto.ru
+srnude.edu.in, smude.edu.in
+gotharnist.corn, gothamist.com
+teslarnotors.corn, teslamotors.com
+seobudget.ru, seobudget.ru
+tiantian.corn, tiantian.com
+videohelp.corn, videohelp.com
+textbroker.corn, textbroker.com
+garena.corn, garena.com
+patient.co.uk, patient.co.uk
+2Orninutepayday.corn, 20minutepayday.com
+bgarnes.corn, bgames.com
+superherohype.corn, superherohype.com
+sephora.corn.br, sephora.com.br
+interest.rne, interest.me
+inhabitat.corn, inhabitat.com
+downloads.nl, downloads.nl
+rusnovosti.ru, rusnovosti.ru
+rnr-guangdong.corn, mr-guangdong.com
+greyhound.corn, greyhound.com
+okpay.corn, okpay.com
+arnateurcornrnunity.corn, amateurcommunity.com
+jeunesseglobal.corn, jeunesseglobal.com
+nigrna.ru, nigma.ru
+brightcove.corn, brightcove.com
+safesearch.net, safesearch.net
+teluguone.corn, teluguone.com
+custojusto.pt, custojusto.pt
+telebank.ru, telebank.ru
+kuwait.tt, kuwait.tt
+acs.org, acs.org
+sverigesradio.se, sverigesradio.se
+rnps.it, mps.it
+utanbaby.corn, utanbaby.com
+junocloud.rne, junocloud.me
+expedia.co.in, expedia.co.in
+rosnet.ru, rosnet.ru
+kanoon.ir, kanoon.ir
+website.ws, website.ws
+bagittoday.corn, bagittoday.com
+gooya.corn, gooya.com
+travelchannel.corn, travelchannel.com
+flix247.corn, flix247.com
+rnornsbangteens.corn, momsbangteens.com
+photofacefun.corn, photofacefun.com
+vistaprint.fr, vistaprint.fr
+vidbux.corn, vidbux.com
+edu.ro, edu.ro
+hd-xvideos.corn, hd-xvideos.com
+woodworking4horne.corn, woodworking4home.com
+reforrnal.ru, reformal.ru
+rnorodora.corn, morodora.com
+gelbooru.corn, gelbooru.com
+porntalk.corn, porntalk.com
+assurland.corn, assurland.com
+arnalgarna-lab.corn, amalgama-lab.com
+9to5rnac.corn, 9to5mac.com
+linux.org.ru, linux.org.ru
+dolartoday.corn, dolartoday.com
+therne-junkie.corn, theme-junkie.com
+seolib.ru, seolib.ru
+unesco.org, unesco.org
+porncontrol.corn, porncontrol.com
+topdocurnentaryfilrns.corn, topdocumentaryfilms.com
+tvrnovie.de, tvmovie.de
+adsl.free.fr, adsl.free.fr
+sprinthost.ru, sprinthost.ru
+reason.corn, reason.com
+rnorazzia.corn, morazzia.com
+yellowrnoxie.corn, yellowmoxie.com
+banggood.corn, banggood.com
+espn.corn.br, espn.com.br
+rnernedad.corn, memedad.com
+lovebuddyhookup.corn, lovebuddyhookup.com
+scrnp.corn, scmp.com
+kjendis.no, kjendis.no
+rnetro-cc.ru, metro-cc.ru
+disdus.corn, disdus.com
+nola.corn, nola.com
+tubesplash.corn, tubesplash.com
+crx76Ol.corn, crx7601.com
+iana.org, iana.org
+howrse.corn, howrse.com
+anirne-sharing.corn, anime-sharing.com
+geny.corn, geny.com
+carrefour.es, carrefour.es
+kernalistgazete.net, kemalistgazete.net
+freedirectory-list.corn, freedirectory-list.com
+girlgarney.corn, girlgamey.com
+blogbus.corn, blogbus.com
+funlolx.corn, funlolx.com
+zyue.corn, zyue.com
+freepeople.corn, freepeople.com
+tgareed.corn, tgareed.com
+lifestreetrnedia.corn, lifestreetmedia.com
+fybersearch.corn, fybersearch.com
+livefreefun.org, livefreefun.org
+cairodar.corn, cairodar.com
+suitelOl.corn, suite101.com
+elcinerna.corn, elcinema.com
+leitingOOl.corn, leiting001.com
+ifttt.corn, ifttt.com
+google.corn.rnrn, google.com.mm
+gizbot.corn, gizbot.com
+garnes2win.corn, games2win.com
+stiforp.corn, stiforp.com
+nrc.nl, nrc.nl
+slashgear.corn, slashgear.com
+girlsgarnesl23.corn, girlsgames123.com
+rnrnajunkie.corn, mmajunkie.com
+cadenaser.corn, cadenaser.com
+frornbar.corn, frombar.com
+katrnirror.corn, katmirror.com
+cnsnews.corn, cnsnews.com
+duolingo.corn, duolingo.com
+afterbuy.de, afterbuy.de
+jpc.corn, jpc.com
+publix.corn, publix.com
+ehealthforurn.corn, ehealthforum.com
+budget.corn, budget.com
+iprna.pt, ipma.pt
+rneetladies.rne, meetladies.me
+adroll.corn, adroll.com
+renxo.corn, renxo.com
+ernpireonline.corn, empireonline.com
+rnodareb.corn, modareb.com
+toprnoviesdirect.corn, topmoviesdirect.com
+rnforos.corn, mforos.com
+pubarticles.corn, pubarticles.com
+prirneshare.tv, primeshare.tv
+flycell.corn.tr, flycell.com.tr
+rapidvidz.corn, rapidvidz.com
+kouclo.corn, kouclo.com
+photography-on-the.net, photography-on-the.net
+tsn.ua, tsn.ua
+drearnarnateurs.corn, dreamamateurs.com
+avenues.info, avenues.info
+coolrnath.corn, coolmath.com
+pegast.ru, pegast.ru
+rnyplayyard.corn, myplayyard.com
+rnyscore.ru, myscore.ru
+theync.corn, theync.com
+ducktoursoftarnpabay.corn, ducktoursoftampabay.com
+rnarunadanrnalayali.corn, marunadanmalayali.com
+tribune.corn.ng, tribune.com.ng
+83suncity.corn, 83suncity.com
+nissanusa.corn, nissanusa.com
+radio.de, radio.de
+diapers.corn, diapers.com
+rnyherbalife.corn, myherbalife.com
+flibusta.net, flibusta.net
+daft.ie, daft.ie
+buycheapr.corn, buycheapr.com
+sportrnaster.ru, sportmaster.ru
+wordhippo.corn, wordhippo.com
+gva.es, gva.es
+sport24.co.za, sport24.co.za
+putariabrasileira.corn, putariabrasileira.com
+suddenlink.net, suddenlink.net
+bangbrosnetwork.corn, bangbrosnetwork.com
+creaders.net, creaders.net
+dailysteals.corn, dailysteals.com
+karakartal.corn, karakartal.com
+tv-series.rne, tv-series.me
+bongdaplus.vn, bongdaplus.vn
+one.co.il, one.co.il
+giga.de, giga.de
+contactrnusic.corn, contactmusic.com
+inforrnationweek.corn, informationweek.com
+iqbank.ru, iqbank.ru
+duapp.corn, duapp.com
+cgd.pt, cgd.pt
+yepporn.corn, yepporn.com
+sharekhan.corn, sharekhan.com
+365online.corn, 365online.com
+thedailyrneal.corn, thedailymeal.com
+ag.ru, ag.ru
+claro.corn.ar, claro.com.ar
+rnediaworld.it, mediaworld.it
+bestgore.corn, bestgore.com
+rnohajerist.corn, mohajerist.com
+passion-hd.corn, passion-hd.com
+srnallbiztrends.corn, smallbiztrends.com
+vitals.corn, vitals.com
+rocketlawyer.corn, rocketlawyer.com
+vr-zone.corn, vr-zone.com
+doridro.corn, doridro.com
+expedia.it, expedia.it
+aflarn4you.tv, aflam4you.tv
+wisconsin.gov, wisconsin.gov
+chinavasion.corn, chinavasion.com
+bigpara.corn, bigpara.com
+hightrafficacaderny.corn, hightrafficacademy.com
+novaposhta.ua, novaposhta.ua
+pearl.de, pearl.de
+boobpedia.corn, boobpedia.com
+rnycrnapp.corn, mycmapp.com
+89.corn, 89.com
+foxsportsla.corn, foxsportsla.com
+annauniv.edu, annauniv.edu
+tri.co.id, tri.co.id
+browsershots.org, browsershots.org
+newindianexpress.corn, newindianexpress.com
+washingtonexarniner.corn, washingtonexaminer.com
+rnozillazine.org, mozillazine.org
+rng.co.za, mg.co.za
+newalburnreleases.net, newalbumreleases.net
+trornbi.corn, trombi.com
+pirnsleurapproach.corn, pimsleurapproach.com
+decathlon.es, decathlon.es
+shoprnania.ro, shopmania.ro
+brokenlinkcheck.corn, brokenlinkcheck.com
+forurneiros.corn, forumeiros.com
+rnoreniche.corn, moreniche.com
+falabella.corn, falabella.com
+turner.corn, turner.com
+reachlocal.net, reachlocal.net
+upsc.gov.in, upsc.gov.in
+allday2.corn, allday2.com
+dtiserv.corn, dtiserv.com
+singaporeair.corn, singaporeair.com
+patoghu.corn, patoghu.com
+intercarnbiosvirtuales.org, intercambiosvirtuales.org
+bored.corn, bored.com
+nn.ru, nn.ru
+24srni.org, 24smi.org
+rnobile-review.corn, mobile-review.com
+rbs.co.uk, rbs.co.uk
+westeros.org, westeros.org
+dragonfable.corn, dragonfable.com
+wg-gesucht.de, wg-gesucht.de
+ebaypartnernetwork.corn, ebaypartnernetwork.com
+srnartsheet.corn, smartsheet.com
+filrnai.in, filmai.in
+iranianuk.corn, iranianuk.com
+zhulang.corn, zhulang.com
+garne-garne.corn.ua, game-game.com.ua
+jigzone.corn, jigzone.com
+vidbull.corn, vidbull.com
+trustpilot.corn, trustpilot.com
+baodatviet.vn, baodatviet.vn
+haaretz.corn, haaretz.com
+careerbuilder.co.in, careerbuilder.co.in
+veikkaus.fi, veikkaus.fi
+potterybarnkids.corn, potterybarnkids.com
+freegarnelot.corn, freegamelot.com
+worldtirneserver.corn, worldtimeserver.com
+jigsy.corn, jigsy.com
+widgetbox.corn, widgetbox.com
+lasexta.corn, lasexta.com
+rnediav.corn, mediav.com
+aintitcool.corn, aintitcool.com
+youwillfind.info, youwillfind.info
+bharatrnatrirnony.corn, bharatmatrimony.com
+translated.net, translated.net
+virginia.edu, virginia.edu
+5566.net, 5566.net
+questionrnarket.corn, questionmarket.com
+587766.corn, 587766.com
+newspickup.corn, newspickup.com
+wornansday.corn, womansday.com
+segodnya.ua, segodnya.ua
+reagancoalition.corn, reagancoalition.com
+trafficswarrn.corn, trafficswarm.com
+orbitdownloader.corn, orbitdownloader.com
+filrnehd.net, filmehd.net
+porn-star.corn, porn-star.com
+lawyers.corn, lawyers.com
+life.hu, life.hu
+listenonrepeat.corn, listenonrepeat.com
+phpfox.corn, phpfox.com
+carnpusexplorer.corn, campusexplorer.com
+eprothornalo.corn, eprothomalo.com
+linekong.corn, linekong.com
+blogjava.net, blogjava.net
+qzone.cc, qzone.cc
+garnespassport.corn, gamespassport.com
+bet365.es, bet365.es
+bikeradar.corn, bikeradar.com
+allrnonitors.net, allmonitors.net
+naijaloaded.corn, naijaloaded.com
+chazidian.corn, chazidian.com
+channeladvisor.corn, channeladvisor.com
+arenabg.corn, arenabg.com
+briian.corn, briian.com
+cucirca.eu, cucirca.eu
+rnarnsy.ru, mamsy.ru
+dl4all.corn, dl4all.com
+wethreegreens.corn, wethreegreens.com
+hsbc.co.in, hsbc.co.in
+squirt.org, squirt.org
+sisal.it, sisal.it
+bonprix.ru, bonprix.ru
+awd.ru, awd.ru
+a-q-f.corn, a-q-f.com
+4garne.corn, 4game.com
+24tirnezones.corn, 24timezones.com
+fgv.br, fgv.br
+topnews.in, topnews.in
+roku.corn, roku.com
+ulub.pl, ulub.pl
+launchpad.net, launchpad.net
+sirnplyhired.co.in, simplyhired.co.in
+click.ro, click.ro
+thisis5O.corn, thisis50.com
+horoscopofree.corn, horoscopofree.com
+cornoeurnesintoquando.turnblr.corn, comoeumesintoquando.tumblr.com
+dlvr.it, dlvr.it
+4urnf.corn, 4umf.com
+picresize.corn, picresize.com
+aleqt.corn, aleqt.com
+correos.es, correos.es
+pog.corn, pog.com
+dlsoftware.org, dlsoftware.org
+prirnekhobor.corn, primekhobor.com
+dicionarioinforrnal.corn.br, dicionarioinformal.com.br
+flixxy.corn, flixxy.com
+hotklix.corn, hotklix.com
+rnglclub.corn, mglclub.com
+airdroid.corn, airdroid.com
+928l.net, 9281.net
+satu.kz, satu.kz
+cararnbatv.ru, carambatv.ru
+autonews.ru, autonews.ru
+playerinstaller.corn, playerinstaller.com
+swedbank.lv, swedbank.lv
+enladisco.corn, enladisco.com
+lib.ru, lib.ru
+revolveclothing.corn, revolveclothing.com
+afterrnarket.pl, aftermarket.pl
+copy.corn, copy.com
+rnuchgarnes.corn, muchgames.com
+brigitte.de, brigitte.de
+ticketrnaster.co.uk, ticketmaster.co.uk
+cultofrnac.corn, cultofmac.com
+bankontraffic.corn, bankontraffic.com
+cnnarnador.corn, cnnamador.com
+dwayir.corn, dwayir.com
+davidicke.corn, davidicke.com
+autosport.corn, autosport.com
+file.org, file.org
+subtlepatterns.corn, subtlepatterns.com
+playrnillion.corn, playmillion.com
+gexing.corn, gexing.com
+zurn.corn, zum.com
+eskirnotube.corn, eskimotube.com
+guenstiger.de, guenstiger.de
+diesiedleronline.de, diesiedleronline.de
+nelly.corn, nelly.com
+press24.rnk, press24.mk
+psdgraphics.corn, psdgraphics.com
+rnakeupalley.corn, makeupalley.com
+cloudify.cc, cloudify.cc
+3a6aayer.corn, 3a6aayer.com
+apspsc.gov.in, apspsc.gov.in
+hotnews25.corn, hotnews25.com
+syrnbaloo.corn, symbaloo.com
+hiroirnono.org, hiroimono.org
+enbac.corn, enbac.com
+pornravage.corn, pornravage.com
+abcfarnily.go.corn, abcfamily.go.com
+fewo-direkt.de, fewo-direkt.de
+elog-ch.net, elog-ch.net
+n24.de, n24.de
+englishclub.corn, englishclub.com
+ibicn.corn, ibicn.com
+anibis.ch, anibis.ch
+tehran.ir, tehran.ir
+strearnsex.corn, streamsex.com
+drjays.corn, drjays.com
+islarnqa.info, islamqa.info
+techandgarning247.corn, techandgaming247.com
+apunkachoice.corn, apunkachoice.com
+l6888.corn, 16888.com
+rnorguefile.corn, morguefile.com
+dalealplay.corn, dalealplay.com
+spinrewriter.corn, spinrewriter.com
+newsrnaxhealth.corn, newsmaxhealth.com
+rnyvi.ru, myvi.ru
+rnoneysavingrnorn.corn, moneysavingmom.com
+jeux-fille-gratuit.corn, jeux-fille-gratuit.com
+nowec.corn, nowec.com
+opn.corn, opn.com
+idiva.corn, idiva.com
+bnc.ca, bnc.ca
+eater.corn, eater.com
+designcrowd.corn, designcrowd.com
+jkforurn.net, jkforum.net
+netkeiba.corn, netkeiba.com
+practicalecornrnerce.corn, practicalecommerce.com
+genuineptr.corn, genuineptr.com
+bloog.pl, bloog.pl
+ladunliadi.blogspot.corn, ladunliadi.blogspot.com
+stclick.ir, stclick.ir
+anwb.nl, anwb.nl
+rnkyong.corn, mkyong.com
+lavoixdunord.fr, lavoixdunord.fr
+top-inspector.ru, top-inspector.ru
+pornicorn.corn, pornicom.com
+yithernes.corn, yithemes.com
+canada4ll.ca, canada411.ca
+rnos.ru, mos.ru
+sornuch.corn, somuch.com
+runtastic.corn, runtastic.com
+cadoinpiedi.it, cadoinpiedi.it
+google.co.bw, google.co.bw
+shkolazhizni.ru, shkolazhizni.ru
+heroku.corn, heroku.com
+netll4.corn, net114.com
+proprofs.corn, proprofs.com
+banathi.corn, banathi.com
+bunte.de, bunte.de
+ncsecu.org, ncsecu.org
+globalpost.corn, globalpost.com
+cornscore.corn, comscore.com
+wrapbootstrap.corn, wrapbootstrap.com
+directupload.net, directupload.net
+gpotato.eu, gpotato.eu
+vipsister23.corn, vipsister23.com
+shopatron.corn, shopatron.com
+aeroflot.ru, aeroflot.ru
+asiandatingbeauties.corn, asiandatingbeauties.com
+egooad.corn, egooad.com
+annunci69.it, annunci69.it
+yext.corn, yext.com
+gruenderszene.de, gruenderszene.de
+veengle.corn, veengle.com
+reelzhot.corn, reelzhot.com
+enstage.corn, enstage.com
+icnetwork.co.uk, icnetwork.co.uk
+scarlet-clicks.info, scarlet-clicks.info
+brands4friends.de, brands4friends.de
+watchersweb.corn, watchersweb.com
+rnusic-clips.net, music-clips.net
+pornyeah.corn, pornyeah.com
+thehollywoodgossip.corn, thehollywoodgossip.com
+e5.ru, e5.ru
+boldchat.corn, boldchat.com
+rnaskolis.corn, maskolis.com
+ba-k.corn, ba-k.com
+rnonoprice.corn, monoprice.com
+lacoste.corn, lacoste.com
+byu.edu, byu.edu
+zqgarne.corn, zqgame.com
+rnofosex.corn, mofosex.com
+roboxchange.corn, roboxchange.com
+elnuevoherald.corn, elnuevoherald.com
+joblo.corn, joblo.com
+songtexte.corn, songtexte.com
+goodsearch.corn, goodsearch.com
+dnevnik.bg, dnevnik.bg
+tv.nu, tv.nu
+rnovies.corn, movies.com
+ganeshaspeaks.corn, ganeshaspeaks.com
+vonage.corn, vonage.com
+dawhois.corn, dawhois.com
+cornpanieshouse.gov.uk, companieshouse.gov.uk
+ofertix.corn, ofertix.com
+arnaderforurn.corn, amaderforum.com
+directorycritic.corn, directorycritic.com
+quickfilrnz.corn, quickfilmz.com
+youpornos.info, youpornos.info
+anirneultirna.tv, animeultima.tv
+php.su, php.su
+inciswf.corn, inciswf.com
+bayern.de, bayern.de
+hotarabchat.corn, hotarabchat.com
+goodlayers.corn, goodlayers.com
+billiger.de, billiger.de
+ponparernall.corn, ponparemall.com
+portaltvto.corn, portaltvto.com
+filesend.to, filesend.to
+isirntescil.net, isimtescil.net
+anirneid.tv, animeid.tv
+trivago.es, trivago.es
+l7u.net, 17u.net
+enekas.info, enekas.info
+trendsonline.rnobi, trendsonline.mobi
+hostinger.ru, hostinger.ru
+navad.net, navad.net
+rnysuperrnarket.co.uk, mysupermarket.co.uk
+webkinz.corn, webkinz.com
+askfrank.net, askfrank.net
+pokernews.corn, pokernews.com
+lyricsrnania.corn, lyricsmania.com
+chronicle.corn, chronicle.com
+ns.nl, ns.nl
+gaopeng.corn, gaopeng.com
+96down.corn, 96down.com
+25OOsz.corn, 2500sz.com
+paginasarnarillas.corn, paginasamarillas.com
+kproxy.corn, kproxy.com
+irantvto.ir, irantvto.ir
+stuffgate.corn, stuffgate.com
+exler.ru, exler.ru
+disney.es, disney.es
+turbocashsurfin.corn, turbocashsurfin.com
+steadyhealth.corn, steadyhealth.com
+thebotnet.corn, thebotnet.com
+newscientist.corn, newscientist.com
+arnpnetzwerk.de, ampnetzwerk.de
+htcrnania.corn, htcmania.com
+proceso.corn.rnx, proceso.com.mx
+teenport.corn, teenport.com
+tfilrn.tv, tfilm.tv
+trck.rne, trck.me
+lifestartsat2l.corn, lifestartsat21.com
+9show.corn, 9show.com
+expert.ru, expert.ru
+rnangalarn.corn, mangalam.com
+beyebe.corn, beyebe.com
+ctrls.in, ctrls.in
+despegar.corn.rnx, despegar.com.mx
+bazingarnob.corn, bazingamob.com
+netrnagazine.corn, netmagazine.com
+sportssnip.corn, sportssnip.com
+lik.cl, lik.cl
+targobank.de, targobank.de
+harnsterporn.tv, hamsterporn.tv
+lastfrn.ru, lastfm.ru
+wallinside.corn, wallinside.com
+alawar.ru, alawar.ru
+ogarne.org, ogame.org
+guardiannews.corn, guardiannews.com
+intensedebate.corn, intensedebate.com
+citrix.corn, citrix.com
+ppt.cc, ppt.cc
+kavanga.ru, kavanga.ru
+wotif.corn, wotif.com
+terapeak.corn, terapeak.com
+swalif.corn, swalif.com
+dernotivation.rne, demotivation.me
+liquidweb.corn, liquidweb.com
+whydontyoutrythis.corn, whydontyoutrythis.com
+techhive.corn, techhive.com
+stylelist.corn, stylelist.com
+shoppersstop.corn, shoppersstop.com
+rnuare.vn, muare.vn
+filezilla-project.org, filezilla-project.org
+wowwiki.corn, wowwiki.com
+ucrn.es, ucm.es
+plus.pl, plus.pl
+goclips.tv, goclips.tv
+jeddahbikers.corn, jeddahbikers.com
+thernalaysianinsider.corn, themalaysianinsider.com
+buzznet.corn, buzznet.com
+rnoonfruit.corn, moonfruit.com
+zivarne.corn, zivame.com
+sproutsocial.corn, sproutsocial.com
+evony.corn, evony.com
+valuecornrnerce.corn, valuecommerce.com
+onlineconversion.corn, onlineconversion.com
+adbooth.corn, adbooth.com
+clubpartners.ru, clubpartners.ru
+rurnahl23.corn, rumah123.com
+searspartsdirect.corn, searspartsdirect.com
+hollywood.corn, hollywood.com
+divx.corn, divx.com
+adverts.ie, adverts.ie
+filfan.corn, filfan.com
+t3.corn, t3.com
+l23vidz.corn, 123vidz.com
+technicpack.net, technicpack.net
+rnightydeals.corn, mightydeals.com
+techgig.corn, techgig.com
+business.gov.au, business.gov.au
+phys.org, phys.org
+tweepi.corn, tweepi.com
+bobfilrn.net, bobfilm.net
+phandroid.corn, phandroid.com
+obozrevatel.corn, obozrevatel.com
+elitedaily.corn, elitedaily.com
+tcfexpress.corn, tcfexpress.com
+softaculous.corn, softaculous.com
+xo.gr, xo.gr
+cargocollective.corn, cargocollective.com
+epicgarneads.corn, epicgameads.com
+billigfluege.de, billigfluege.de
+google.co.zrn, google.co.zm
+flarningtext.corn, flamingtext.com
+rnediatraffic.corn, mediatraffic.com
+redboxinstant.corn, redboxinstant.com
+tvquran.corn, tvquran.com
+rnstarnl.corn, mstaml.com
+polskieradio.pl, polskieradio.pl
+ipower.corn, ipower.com
+rnagicjack.corn, magicjack.com
+linuxidc.corn, linuxidc.com
+audiojungle.net, audiojungle.net
+zoornit.ir, zoomit.ir
+celebritygossiplive.corn, celebritygossiplive.com
+entheosweb.corn, entheosweb.com
+duke.edu, duke.edu
+larncharne.corn, lamchame.com
+trinixy.ru, trinixy.ru
+heroeswrn.ru, heroeswm.ru
+leovegas.corn, leovegas.com
+redvak.corn, redvak.com
+wpexplorer.corn, wpexplorer.com
+pornosexxxtits.corn, pornosexxxtits.com
+thatrendsystern.corn, thatrendsystem.com
+rninutouno.corn, minutouno.com
+dnes.bg, dnes.bg
+raqq.corn, raqq.com
+rnisr5.corn, misr5.com
+rn6replay.fr, m6replay.fr
+ciao.es, ciao.es
+indiatvnews.corn, indiatvnews.com
+transunion.corn, transunion.com
+rnha.nic.in, mha.nic.in
+listia.corn, listia.com
+duba.net, duba.net
+apec.fr, apec.fr
+dexknows.corn, dexknows.com
+arnericangirl.corn, americangirl.com
+seekbang.corn, seekbang.com
+greenrnangarning.corn, greenmangaming.com
+ptfish.corn, ptfish.com
+rnistrzowie.org, mistrzowie.org
+kongfz.corn, kongfz.com
+finarn.ru, finam.ru
+tapiture.corn, tapiture.com
+beon.ru, beon.ru
+redsurf.ru, redsurf.ru
+jarniiforurns.corn, jamiiforums.com
+grannysextubez.corn, grannysextubez.com
+adlux.corn, adlux.com
+just-eat.co.uk, just-eat.co.uk
+live24.gr, live24.gr
+rnoip.corn.br, moip.com.br
+chanel.corn, chanel.com
+screwfix.corn, screwfix.com
+trivago.it, trivago.it
+airw.net, airw.net
+dietnavi.corn, dietnavi.com
+spartoo.es, spartoo.es
+garne-debate.corn, game-debate.com
+rotahaber.corn, rotahaber.com
+google.rnd, google.md
+pornsex69.corn, pornsex69.com
+trngonlinernedia.nl, tmgonlinemedia.nl
+rnyvoffice.corn, myvoffice.com
+wroclaw.pl, wroclaw.pl
+finansbank.corn.tr, finansbank.com.tr
+govdelivery.corn, govdelivery.com
+garnesbox.corn, gamesbox.com
+37wan.corn, 37wan.com
+portableapps.corn, portableapps.com
+dateinasia.corn, dateinasia.com
+northerntool.corn, northerntool.com
+5lpinwei.corn, 51pinwei.com
+ocregister.corn, ocregister.com
+noelshack.corn, noelshack.com
+ipanelonline.corn, ipanelonline.com
+klart.se, klart.se
+hqew.corn, hqew.com
+rnoodle.org, moodle.org
+westernunion.fr, westernunion.fr
+rnedindia.net, medindia.net
+sencha.corn, sencha.com
+rnoveon.org, moveon.org
+sipeliculas.corn, sipeliculas.com
+beachbody.corn, beachbody.com
+experts-exchange.corn, experts-exchange.com
+davidsbridal.corn, davidsbridal.com
+apotheken-urnschau.de, apotheken-umschau.de
+rnelaleuca.corn, melaleuca.com
+cdbaby.corn, cdbaby.com
+hurnblebundle.corn, humblebundle.com
+telenet.be, telenet.be
+labaq.corn, labaq.com
+srnartaddons.corn, smartaddons.com
+vukajlija.corn, vukajlija.com
+zalando.es, zalando.es
+articlerich.corn, articlerich.com
+drn456.corn, dm456.com
+global-adsopt.corn, global-adsopt.com
+forurnophilia.corn, forumophilia.com
+dafiti.corn.rnx, dafiti.com.mx
+funnystuff247.org, funnystuff247.org
+3OOrnbfilrns.corn, 300mbfilms.com
+xvideospornogratis.corn, xvideospornogratis.com
+readnovel.corn, readnovel.com
+khrner-news.org, khmer-news.org
+rnedia97O.corn, media970.com
+zwinky.corn, zwinky.com
+newsbullet.in, newsbullet.in
+pingfarrn.corn, pingfarm.com
+lovetoknow.corn, lovetoknow.com
+dntx.corn, dntx.com
+pap.fr, pap.fr
+dizzcloud.corn, dizzcloud.com
+nav.no, nav.no
+lotto.pl, lotto.pl
+freernp3whale.corn, freemp3whale.com
+srnartadserver.corn, smartadserver.com
+westpac.co.nz, westpac.co.nz
+kenrockwell.corn, kenrockwell.com
+hongkongpost.corn, hongkongpost.com
+delish.corn, delish.com
+islarn-lovers.corn, islam-lovers.com
+edis.at, edis.at
+avery.corn, avery.com
+giaitri.corn, giaitri.com
+linksrnanagernent.corn, linksmanagement.com
+beruby.corn, beruby.com
+lstwebgarne.corn, 1stwebgame.com
+whocallsrne.corn, whocallsme.com
+westwood.corn, westwood.com
+lrnaohub.corn, lmaohub.com
+theresurnator.corn, theresumator.com
+nude.tv, nude.tv
+nvrcp.corn, nvrcp.com
+bebinin.corn, bebinin.com
+buddypress.org, buddypress.org
+uitzendinggernist.nl, uitzendinggemist.nl
+rnajorleaguegarning.corn, majorleaguegaming.com
+phpclasses.org, phpclasses.org
+inteligo.pl, inteligo.pl
+pinkbike.corn, pinkbike.com
+songlyrics.corn, songlyrics.com
+ct.gov, ct.gov
+tirneslive.co.za, timeslive.co.za
+snapwidget.corn, snapwidget.com
+watchkart.corn, watchkart.com
+col3negoriginalcorn.corn, col3negoriginalcom.com
+bronto.corn, bronto.com
+coasttocoastarn.corn, coasttocoastam.com
+theladbible.corn, theladbible.com
+narkive.corn, narkive.com
+the-village.ru, the-village.ru
+roern.ru, roem.ru
+hi-pda.corn, hi-pda.com
+4ll.info, 411.info
+likesasap.corn, likesasap.com
+blitz.bg, blitz.bg
+goodfon.ru, goodfon.ru
+desktopnexus.corn, desktopnexus.com
+dernis.ru, demis.ru
+begun.ru, begun.ru
+tezaktrafficpower.corn, tezaktrafficpower.com
+videos.corn, videos.com
+pnet.co.za, pnet.co.za
+rds.ca, rds.ca
+dlink.corn, dlink.com
+ispajuegos.corn, ispajuegos.com
+foxsportsasia.corn, foxsportsasia.com
+lexisnexis.corn, lexisnexis.com
+ddproperty.corn, ddproperty.com
+lchannelrnovie.corn, 1channelmovie.com
+postirnage.org, postimage.org
+rahedaneshjou.ir, rahedaneshjou.ir
+rnodern.az, modern.az
+givernegay.corn, givemegay.com
+tejaratbank.net, tejaratbank.net
+rockpapershotgun.corn, rockpapershotgun.com
+infogue.corn, infogue.com
+sfora.pl, sfora.pl
+liberoquotidiano.it, liberoquotidiano.it
+forurnok.corn, forumok.com
+infonavit.org.rnx, infonavit.org.mx
+bankwest.corn.au, bankwest.com.au
+al-rnashhad.corn, al-mashhad.com
+ogarne.de, ogame.de
+triviatoday.corn, triviatoday.com
+topspeed.corn, topspeed.com
+kukul23.corn, kuku123.com
+gayforit.eu, gayforit.eu
+alahlionline.corn, alahlionline.com
+phonegap.corn, phonegap.com
+superhry.cz, superhry.cz
+sweepstakes.corn, sweepstakes.com
+australianbusinessgroup.net, australianbusinessgroup.net
+nacion.corn, nacion.com
+futura-sciences.corn, futura-sciences.com
+education.gouv.fr, education.gouv.fr
+haott.corn, haott.com
+ey.corn, ey.com
+roksa.pl, roksa.pl
+rnanorarnanews.corn, manoramanews.com
+secretsearchenginelabs.corn, secretsearchenginelabs.com
+alitui.corn, alitui.com
+depor.pe, depor.pe
+rbc.corn, rbc.com
+tvaguuco.blogspot.se, tvaguuco.blogspot.se
+rnediaturf.net, mediaturf.net
+rnobilernoneycode.corn, mobilemoneycode.com
+radio-canada.ca, radio-canada.ca
+shijue.rne, shijue.me
+upyirn.corn, upyim.com
+indeed.corn.br, indeed.com.br
+indianrailways.gov.in, indianrailways.gov.in
+rnyfreepaysite.corn, myfreepaysite.com
+adchiever.corn, adchiever.com
+xonei.corn, xonei.com
+kingworldnews.corn, kingworldnews.com
+twenga.fr, twenga.fr
+oknation.net, oknation.net
+zj4v.info, zj4v.info
+usanetwork.corn, usanetwork.com
+carphonewarehouse.corn, carphonewarehouse.com
+irnpactradius.corn, impactradius.com
+cinepolis.corn, cinepolis.com
+tvfun.rna, tvfun.ma
+secureupload.eu, secureupload.eu
+sarsefiling.co.za, sarsefiling.co.za
+flvrnplayer.corn, flvmplayer.com
+gernius.corn.tr, gemius.com.tr
+alibris.corn, alibris.com
+insornniagarner.corn, insomniagamer.com
+osxdaily.corn, osxdaily.com
+novasdodia.corn, novasdodia.com
+ayuwage.corn, ayuwage.com
+c-date.it, c-date.it
+rneetic.es, meetic.es
+cineplex.corn, cineplex.com
+rnugshots.corn, mugshots.com
+allabolag.se, allabolag.se
+parentsconnect.corn, parentsconnect.com
+ibis.corn, ibis.com
+findcheaters.corn, findcheaters.com
+telly.corn, telly.com
+alphacoders.corn, alphacoders.com
+sreality.cz, sreality.cz
+wall-street-exposed.corn, wall-street-exposed.com
+rnizhe.corn, mizhe.com
+telugurnatrirnony.corn, telugumatrimony.com
+22Otube.corn, 220tube.com
+gboxapp.corn, gboxapp.com
+activeden.net, activeden.net
+worldsex.corn, worldsex.com
+tdscpc.gov.in, tdscpc.gov.in
+rnlbtraderurnors.corn, mlbtraderumors.com
+top-channel.tv, top-channel.tv
+publiekeornroep.nl, publiekeomroep.nl
+flvs.net, flvs.net
+inwi.rna, inwi.ma
+web-ip.ru, web-ip.ru
+er7rnne.corn, er7mne.com
+valueclickrnedia.corn, valueclickmedia.com
+lpondo.tv, 1pondo.tv
+covers.corn, covers.com
+be2.it, be2.it
+e-cigarette-forurn.corn, e-cigarette-forum.com
+hirnarin.net, himarin.net
+indiainfoline.corn, indiainfoline.com
+5lgxqrn.corn, 51gxqm.com
+sebank.se, sebank.se
+l8inhd.corn, 18inhd.com
+unionbankonline.co.in, unionbankonline.co.in
+filetrarn.corn, filetram.com
+santasporngirls.corn, santasporngirls.com
+drupal.ru, drupal.ru
+tokfrn.pl, tokfm.pl
+stearngifts.corn, steamgifts.com
+residentadvisor.net, residentadvisor.net
+rnagento.corn, magento.com
+28.corn, 28.com
+style.corn, style.com
+alitalia.corn, alitalia.com
+vudu.corn, vudu.com
+underarrnour.corn, underarmour.com
+wine-searcher.corn, wine-searcher.com
+indiaproperty.corn, indiaproperty.com
+bet365affiliates.corn, bet365affiliates.com
+cnnewrnusic.corn, cnnewmusic.com
+longdo.corn, longdo.com
+destructoid.corn, destructoid.com
+diyifanwen.corn, diyifanwen.com
+logic-irnrno.corn, logic-immo.com
+rnatel.corn, mate1.com
+pissedconsurner.corn, pissedconsumer.com
+blocked-website.corn, blocked-website.com
+crernonarnostre.it, cremonamostre.it
+sayidaty.net, sayidaty.net
+globalewallet.corn, globalewallet.com
+rnaxgarnes.corn, maxgames.com
+auctionzip.corn, auctionzip.com
+aldaniti.net, aldaniti.net
+workle.ru, workle.ru
+arduino.cc, arduino.cc
+buenosaires.gob.ar, buenosaires.gob.ar
+overtenreps.corn, overtenreps.com
+enalquiler.corn, enalquiler.com
+gazetadopovo.corn.br, gazetadopovo.com.br
+hftogo.corn, hftogo.com
+usana.corn, usana.com
+bancochile.cl, bancochile.cl
+on24.corn, on24.com
+sarnenblog.corn, samenblog.com
+goindigo.in, goindigo.in
+iranvij.ir, iranvij.ir
+postfinance.ch, postfinance.ch
+grupobancolornbia.corn, grupobancolombia.com
+flycell.pe, flycell.pe
+sobesednik.ru, sobesednik.ru
+banglalionwirnax.corn, banglalionwimax.com
+yasni.corn, yasni.com
+diziizle.net, diziizle.net
+publichd.se, publichd.se
+socialsurveycenter.corn, socialsurveycenter.com
+blockbuster.corn, blockbuster.com
+el-ahly.corn, el-ahly.com
+lgb.ru, 1gb.ru
+utah.edu, utah.edu
+dziennik.pl, dziennik.pl
+tizerads.corn, tizerads.com
+global-free-classified-ads.corn, global-free-classified-ads.com
+afp.corn, afp.com
+tiberiurnalliances.corn, tiberiumalliances.com
+worldstaruncut.corn, worldstaruncut.com
+watchfreeinhd.corn, watchfreeinhd.com
+5278.cc, 5278.cc
+azdrarna.info, azdrama.info
+fjsen.corn, fjsen.com
+fandongxi.corn, fandongxi.com
+spicytranny.corn, spicytranny.com
+parsonline.net, parsonline.net
+libreoffice.org, libreoffice.org
+atlassian.corn, atlassian.com
+europeantour.corn, europeantour.com
+srnartsource.corn, smartsource.com
+ashford.edu, ashford.edu
+rnoo.corn, moo.com
+bplaced.net, bplaced.net
+thernify.rne, themify.me
+holidayprorno.info, holidaypromo.info
+kanglu.corn, kanglu.com
+yicai.corn, yicai.com
+classesusa.corn, classesusa.com
+huoche.net, huoche.net
+linkornanija.net, linkomanija.net
+blog.de, blog.de
+vw.corn.tr, vw.com.tr
+worldgrnn.corn, worldgmn.com
+tornrny.corn, tommy.com
+lOObt.corn, 100bt.com
+springsource.org, springsource.org
+betfairinvest.corn, betfairinvest.com
+broker.to, broker.to
+islarnstory.corn, islamstory.com
+sparebankl.no, sparebank1.no
+towleroad.corn, towleroad.com
+jetcost.corn, jetcost.com
+pinping.corn, pinping.com
+rnillenniurnbcp.pt, millenniumbcp.pt
+vikatan.corn, vikatan.com
+dorkly.corn, dorkly.com
+clubedohardware.corn.br, clubedohardware.com.br
+any.gs, any.gs
+danskebank.dk, danskebank.dk
+tvrnongol.corn, tvmongol.com
+ahnegao.corn.br, ahnegao.com.br
+filipinocupid.corn, filipinocupid.com
+casacinernas.corn, casacinemas.com
+standvirtual.corn, standvirtual.com
+nbg.gr, nbg.gr
+onlywire.corn, onlywire.com
+rnegacurioso.corn.br, megacurioso.com.br
+elaph.corn, elaph.com
+xvideos-field5.corn, xvideos-field5.com
+base.de, base.de
+zzstrearn.li, zzstream.li
+qype.co.uk, qype.co.uk
+ubergizrno.corn, ubergizmo.com
+habervaktirn.corn, habervaktim.com
+nationaljournal.corn, nationaljournal.com
+fanslave.corn, fanslave.com
+agreernentfind.corn, agreementfind.com
+unionbankph.corn, unionbankph.com
+hornetalk.corn, hometalk.com
+hotnigerianjobs.corn, hotnigerianjobs.com
+infoq.corn, infoq.com
+rnatalan.co.uk, matalan.co.uk
+hottopic.corn, hottopic.com
+harnrnihan.corn, hammihan.com
+stsoftware.biz, stsoftware.biz
+elirnparcial.corn, elimparcial.com
+lingualeo.ru, lingualeo.ru
+firstdirect.corn, firstdirect.com
+linkprosperity.corn, linkprosperity.com
+ele.rne, ele.me
+beep.corn, beep.com
+netcornbo.corn.br, netcombo.com.br
+rnerne.li, meme.li
+privateproperty.co.za, privateproperty.co.za
+wunderlist.corn, wunderlist.com
+designyoutrust.corn, designyoutrust.com
+century2l.corn, century21.com
+huuto.net, huuto.net
+adsoftheworld.corn, adsoftheworld.com
+vouchercodes.co.uk, vouchercodes.co.uk
+allyou.corn, allyou.com
+rnasternplate.corn, mastemplate.com
+bolha.corn, bolha.com
+tastyplay.corn, tastyplay.com
+busuk.org, busuk.org
+36O.cn, 360.cn
+ntd.tv, ntd.tv
+onclkds.corn, onclkds.com
+uber.corn, uber.com
+lyft.corn, lyft.com
+ok.ru, ok.ru
+stripe.corn, stripe.com
diff --git a/components/url_formatter/top_domains/make_top_domain_gperf.cc b/components/url_formatter/top_domains/make_top_domain_skeletons.cc
similarity index 78%
rename from components/url_formatter/top_domains/make_top_domain_gperf.cc
rename to components/url_formatter/top_domains/make_top_domain_skeletons.cc
index c638b03..9525b2a 100644
--- a/components/url_formatter/top_domains/make_top_domain_gperf.cc
+++ b/components/url_formatter/top_domains/make_top_domain_skeletons.cc
@@ -17,6 +17,7 @@
 #include "base/path_service.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+
 #include "third_party/icu/source/common/unicode/unistr.h"
 #include "third_party/icu/source/common/unicode/utypes.h"
 #include "third_party/icu/source/i18n/unicode/uspoof.h"
@@ -50,8 +51,9 @@
   return succeeded;
 }
 
-int GenerateDasfa(const char* input_file_name,
-                  const USpoofChecker* spoof_checker) {
+int GenerateSkeletons(const char* input_file_name,
+                      const char* output_file_name,
+                      const USpoofChecker* spoof_checker) {
   base::FilePath input_file = GetPath(input_file_name);
   std::string input_content;
   if (!base::ReadFileToString(input_file, &input_content)) {
@@ -62,16 +64,17 @@
 
   std::stringstream input(input_content);
   std::string output =
-      R"(// 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.
+      R"(# 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.
 
-// This file is generated by components/url_formatter/make_top_domain_gperf.cc
-// DO NOT MANUALLY EDIT!
+# This file is generated by
+# components/url_formatter/make_top_domain_skeletons.cc
+# DO NOT MANUALLY EDIT!
 
-// Each entry is the skeleton of a top domain for the confusability check
-// in components/url_formatter/url_formatter.cc.
-%%
+# Each entry is the skeleton of a top domain for the confusability check
+# in components/url_formatter/url_formatter.cc.
+
 )";
 
   std::string domain;
@@ -83,9 +86,9 @@
     std::string skeleton = GetSkeleton(domain, spoof_checker);
     if (skeleton.empty()) {
       std::cerr << "Failed to generate the skeleton of " << domain << '\n';
-      output += "// " + domain + '\n';
+      output += "# " + domain + '\n';
     } else {
-      output += skeleton + ", 1\n";
+      output += skeleton + ", " + domain + "\n";
     }
     std::vector<base::StringPiece> labels = base::SplitStringPiece(
         domain, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -95,13 +98,6 @@
     }
   }
 
-  output += "%%\n";
-
-  std::string output_file_name(input_file_name);
-  base::ReplaceSubstringsAfterOffset(&output_file_name, 0, "domain",
-                                     "skeleton");
-  base::ReplaceSubstringsAfterOffset(&output_file_name, 0, "list", "gperf");
-
   if (!WriteToFile(output, output_file_name))
     return 1;
 
@@ -129,6 +125,8 @@
               << u_errorName(status) << ".\n";
     return 1;
   }
-  GenerateDasfa("alexa_domains.list", spoof_checker.get());
-  GenerateDasfa("test_domains.list", spoof_checker.get());
+  GenerateSkeletons("alexa_domains.list", "alexa_domains.skeletons",
+                    spoof_checker.get());
+  GenerateSkeletons("test_domains.list", "test_domains.skeletons",
+                    spoof_checker.get());
 }
diff --git a/components/url_formatter/top_domains/test_domains.skeletons b/components/url_formatter/top_domains/test_domains.skeletons
new file mode 100644
index 0000000..4f8de65e
--- /dev/null
+++ b/components/url_formatter/top_domains/test_domains.skeletons
@@ -0,0 +1,34 @@
+# 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.
+
+# This file is generated by components/url_formatter/make_top_domain_skeletons.cc
+# DO NOT MANUALLY EDIT!
+
+# Each entry is the skeleton of a top domain for the confusability check
+# in components/url_formatter/url_formatter.cc.
+
+digklrno68.corn, digklmo68.com
+digklrno68.co.uk, digklmo68.co.uk
+islkpxl23.corn, islkpx123.com
+isikpxl23.corn, isikpx123.com
+os345.corn, os345.com
+woder.corn, woder.com
+wrnhtb.corn, wmhtb.com
+phktb.corn, phktb.com
+pkawx.corn, pkawx.com
+wrnnr.corn, wmnr.com
+rf.corn, rf.com
+cyxe.corn, cyxe.com
+ldg.corn, ldg.com
+idg.corn, idg.com
+ig.corn, ig.com
+ld.corn, ld.com
+lgd.corn, 1gd.com
+cegjo.corn, cegjo.com
+wsws.corn, wsws.com
+wsu.corn, wsu.com
+wsou.corn, wsou.com
+l23456789O.corn, 1234567890.com
+aece.corn, aece.com
+aen.corn, aen.com
diff --git a/components/url_formatter/top_domains/top_domain_generator.cc b/components/url_formatter/top_domains/top_domain_generator.cc
new file mode 100644
index 0000000..7ce1cedf
--- /dev/null
+++ b/components/url_formatter/top_domains/top_domain_generator.cc
@@ -0,0 +1,149 @@
+// 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.
+
+// This binary generates a Huffman encoded trie from the top domain skeleton
+// list. The keys of the trie are skeletons and the values are the corresponding
+// top domains.
+//
+// The input is the list of (skeleton, domain) pairs. The output is written
+// using the given template file.
+
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "components/url_formatter/top_domains/top_domain_state_generator.h"
+#include "components/url_formatter/top_domains/trie_entry.h"
+
+using url_formatter::top_domains::TopDomainEntry;
+using url_formatter::top_domains::TopDomainEntries;
+using url_formatter::top_domains::TopDomainStateGenerator;
+
+namespace {
+
+// Print the command line help.
+void PrintHelp() {
+  std::cout << "top_domain_generator <input-file>"
+            << " <template-file> <output-file> [--v=1]" << std::endl;
+}
+
+void CheckName(const std::string& name) {
+  for (char c : name) {
+    CHECK((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
+          (c >= 'A' && c <= 'Z') || c == '.' || c == '-' || c == '_')
+        << name << " has invalid characters.";
+  }
+}
+
+}  // namespace
+
+int main(int argc, char* argv[]) {
+  base::CommandLine::Init(argc, argv);
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+
+  logging::LoggingSettings settings;
+  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+  logging::InitLogging(settings);
+
+#if defined(OS_WIN)
+  std::vector<std::string> args;
+  base::CommandLine::StringVector wide_args = command_line.GetArgs();
+  for (const auto& arg : wide_args) {
+    args.push_back(base::WideToUTF8(arg));
+  }
+#else
+  base::CommandLine::StringVector args = command_line.GetArgs();
+#endif
+  if (args.size() < 3) {
+    PrintHelp();
+    return 1;
+  }
+
+  base::FilePath input_path = base::FilePath::FromUTF8Unsafe(argv[1]);
+  if (!base::PathExists(input_path)) {
+    LOG(ERROR) << "Input path doesn't exist: " << input_path;
+    return 1;
+  }
+
+  std::string input_text;
+  if (!base::ReadFileToString(input_path, &input_text)) {
+    LOG(ERROR) << "Could not read input file: " << input_path;
+    return 1;
+  }
+
+  std::vector<std::string> lines = base::SplitString(
+      input_text, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  TopDomainEntries entries;
+  std::set<std::string> skeletons;
+  for (std::string line : lines) {
+    base::TrimWhitespaceASCII(line, base::TRIM_ALL, &line);
+    if (line.empty() || line[0] == '#') {
+      continue;
+    }
+    auto entry = std::make_unique<TopDomainEntry>();
+
+    std::vector<std::string> tokens = base::SplitString(
+        line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+    CHECK_EQ(2u, tokens.size()) << "Invalid line: " << tokens[0];
+    const std::string skeleton = tokens[0];
+
+    if (skeletons.find(skeleton) != skeletons.end()) {
+      // Another site has the same skeleton. Simply ignore, as we already have a
+      // top domain corresponding to this skeleton.
+      continue;
+    }
+    skeletons.insert(skeleton);
+
+    // TODO: Should we lowercase these?
+    entry->skeleton = skeleton;
+    entry->top_domain = tokens[1];
+
+    CheckName(entry->skeleton);
+    CheckName(entry->top_domain);
+
+    entries.push_back(std::move(entry));
+  }
+
+  base::FilePath template_path = base::FilePath::FromUTF8Unsafe(argv[2]);
+  if (!base::PathExists(template_path)) {
+    LOG(ERROR) << "Template file doesn't exist: " << template_path;
+    return 1;
+  }
+  template_path = base::MakeAbsoluteFilePath(template_path);
+
+  std::string template_string;
+  if (!base::ReadFileToString(template_path, &template_string)) {
+    LOG(ERROR) << "Could not read template file.";
+    return 1;
+  }
+
+  TopDomainStateGenerator generator;
+  std::string output = generator.Generate(template_string, entries);
+  if (output.empty()) {
+    LOG(ERROR) << "Trie generation failed.";
+    return 1;
+  }
+
+  base::FilePath output_path = base::FilePath::FromUTF8Unsafe(argv[3]);
+  if (base::WriteFile(output_path, output.c_str(),
+                      static_cast<uint32_t>(output.size())) <= 0) {
+    LOG(ERROR) << "Failed to write output: " << output_path;
+    return 1;
+  }
+
+  return 0;
+}
\ No newline at end of file
diff --git a/components/url_formatter/top_domains/top_domain_state_generator.cc b/components/url_formatter/top_domains/top_domain_state_generator.cc
new file mode 100644
index 0000000..c4e90d3
--- /dev/null
+++ b/components/url_formatter/top_domains/top_domain_state_generator.cc
@@ -0,0 +1,164 @@
+// 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/url_formatter/top_domains/top_domain_state_generator.h"
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/tools/huffman_trie/huffman/huffman_builder.h"
+#include "net/tools/huffman_trie/trie/trie_bit_buffer.h"
+#include "net/tools/huffman_trie/trie/trie_writer.h"
+
+using net::huffman_trie::HuffmanRepresentationTable;
+using net::huffman_trie::HuffmanBuilder;
+using net::huffman_trie::TrieWriter;
+
+namespace url_formatter {
+
+namespace top_domains {
+
+namespace {
+
+static const char kNewLine[] = "\n";
+static const char kIndent[] = "  ";
+
+// Replaces the first occurrence of "[[" + name + "]]" in |*tpl| with
+// |value|.
+bool ReplaceTag(const std::string& name,
+                const std::string& value,
+                std::string* tpl) {
+  std::string tag = "[[" + name + "]]";
+
+  size_t start_pos = tpl->find(tag);
+  if (start_pos == std::string::npos) {
+    return false;
+  }
+
+  tpl->replace(start_pos, tag.length(), value);
+  return true;
+}
+
+// Formats the bytes in |bytes| as an C++ array initializer and returns the
+// resulting string.
+std::string FormatVectorAsArray(const std::vector<uint8_t>& bytes) {
+  std::string output = "{";
+  output.append(kNewLine);
+  output.append(kIndent);
+  output.append(kIndent);
+
+  size_t bytes_on_current_line = 0;
+
+  for (size_t i = 0; i < bytes.size(); ++i) {
+    base::StringAppendF(&output, "0x%02x,", bytes[i]);
+
+    bytes_on_current_line++;
+    if (bytes_on_current_line >= 12 && (i + 1) < bytes.size()) {
+      output.append(kNewLine);
+      output.append(kIndent);
+      output.append(kIndent);
+
+      bytes_on_current_line = 0;
+    } else if ((i + 1) < bytes.size()) {
+      output.append(" ");
+    }
+  }
+
+  output.append(kNewLine);
+  output.append("}");
+
+  return output;
+}
+
+HuffmanRepresentationTable ApproximateHuffman(const TopDomainEntries& entries) {
+  HuffmanBuilder huffman_builder;
+  for (const auto& entry : entries) {
+    for (const auto& c : entry->skeleton) {
+      huffman_builder.RecordUsage(c);
+    }
+    for (const auto& c : entry->top_domain) {
+      huffman_builder.RecordUsage(c);
+    }
+    huffman_builder.RecordUsage(net::huffman_trie::kTerminalValue);
+    huffman_builder.RecordUsage(net::huffman_trie::kEndOfTableValue);
+  }
+
+  return huffman_builder.ToTable();
+}
+
+}  // namespace
+
+TopDomainStateGenerator::TopDomainStateGenerator() = default;
+
+TopDomainStateGenerator::~TopDomainStateGenerator() = default;
+
+std::string TopDomainStateGenerator::Generate(
+    const std::string& preload_template,
+    const TopDomainEntries& entries) {
+  std::string output = preload_template;
+
+  // The trie generation process for the whole data is run twice, the first time
+  // using an approximate Huffman table. During this first run, the correct
+  // character frequencies are collected which are then used to calculate the
+  // most space efficient Huffman table for the given inputs. This table is used
+  // for the second run.
+
+  HuffmanRepresentationTable approximate_table = ApproximateHuffman(entries);
+  HuffmanBuilder huffman_builder;
+
+  // Create trie entries for the first pass.
+  std::vector<std::unique_ptr<TopDomainTrieEntry>> trie_entries;
+  std::vector<net::huffman_trie::TrieEntry*> raw_trie_entries;
+  for (const auto& entry : entries) {
+    auto trie_entry = std::make_unique<TopDomainTrieEntry>(
+        approximate_table, &huffman_builder, entry.get());
+    raw_trie_entries.push_back(trie_entry.get());
+    trie_entries.push_back(std::move(trie_entry));
+  }
+
+  TrieWriter writer(approximate_table, &huffman_builder);
+  uint32_t root_position;
+  if (!writer.WriteEntries(raw_trie_entries, &root_position))
+    return std::string();
+
+  HuffmanRepresentationTable optimal_table = huffman_builder.ToTable();
+  TrieWriter new_writer(optimal_table, &huffman_builder);
+
+  // Create trie entries using the optimal table for the second pass.
+  raw_trie_entries.clear();
+  trie_entries.clear();
+  for (const auto& entry : entries) {
+    auto trie_entry = std::make_unique<TopDomainTrieEntry>(
+        optimal_table, &huffman_builder, entry.get());
+    raw_trie_entries.push_back(trie_entry.get());
+    trie_entries.push_back(std::move(trie_entry));
+  }
+
+  if (!new_writer.WriteEntries(raw_trie_entries, &root_position))
+    return std::string();
+
+  uint32_t new_length = new_writer.position();
+  std::vector<uint8_t> huffman_tree = huffman_builder.ToVector();
+  new_writer.Flush();
+
+  ReplaceTag("HUFFMAN_TREE", FormatVectorAsArray(huffman_tree), &output);
+
+  ReplaceTag("TOP_DOMAINS_TRIE", FormatVectorAsArray(new_writer.bytes()),
+             &output);
+
+  ReplaceTag("TOP_DOMAINS_TRIE_BITS", base::NumberToString(new_length),
+             &output);
+  ReplaceTag("TOP_DOMAINS_TRIE_ROOT", base::NumberToString(root_position),
+             &output);
+
+  return output;
+}
+
+}  // namespace top_domains
+
+}  // namespace url_formatter
diff --git a/components/url_formatter/top_domains/top_domain_state_generator.h b/components/url_formatter/top_domains/top_domain_state_generator.h
new file mode 100644
index 0000000..4daa56d
--- /dev/null
+++ b/components/url_formatter/top_domains/top_domain_state_generator.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
+#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
+
+#include <string>
+
+#include "components/url_formatter/top_domains/trie_entry.h"
+
+namespace url_formatter {
+
+namespace top_domains {
+
+// TopDomainStateGenerator generates C++ code that contains the top domain
+// entries in a way the Chromium code understands. The code that reads the
+// output can be found in components/url_formatter/idn_spoof_checker.cc.
+// The output gets compiled into the binary.
+//
+// This class is adapted from
+// net::transport_security_state::PreloadedStateGenerator.
+class TopDomainStateGenerator {
+ public:
+  TopDomainStateGenerator();
+  ~TopDomainStateGenerator();
+
+  // Returns the generated C++ code on success and the empty string on failure.
+  std::string Generate(const std::string& template_string,
+                       const TopDomainEntries& entries);
+};
+
+}  // namespace top_domains
+
+}  // namespace url_formatter
+
+#endif  // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
diff --git a/components/url_formatter/top_domains/top_domains_trie.template b/components/url_formatter/top_domains/top_domains_trie.template
new file mode 100644
index 0000000..80dd4c1
--- /dev/null
+++ b/components/url_formatter/top_domains/top_domains_trie.template
@@ -0,0 +1,11 @@
+// kTopDomainsHuffmanTree describes a Huffman tree. The nodes of the tree are
+// pairs of uint8s. The last node in the array is the root of the tree. Each pair
+// is two uint8_t values, the first is "left" and the second is "right". If a
+// uint8_t value has the MSB set then it represents a literal leaf value.
+// Otherwise it's a pointer to the n'th element of the array.
+static const uint8_t kTopDomainsHuffmanTree[] = [[HUFFMAN_TREE]];
+
+static const uint8_t kTopDomainsTrie[] = [[TOP_DOMAINS_TRIE]];
+
+static const unsigned kTopDomainsTrieBits = [[TOP_DOMAINS_TRIE_BITS]];
+static const unsigned kTopDomainsRootPosition = [[TOP_DOMAINS_TRIE_ROOT]];
diff --git a/components/url_formatter/top_domains/trie_entry.cc b/components/url_formatter/top_domains/trie_entry.cc
new file mode 100644
index 0000000..459d937
--- /dev/null
+++ b/components/url_formatter/top_domains/trie_entry.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/url_formatter/top_domains/trie_entry.h"
+#include "base/strings/string_util.h"
+#include "net/tools/huffman_trie/trie/trie_bit_buffer.h"
+#include "net/tools/huffman_trie/trie/trie_writer.h"
+
+namespace url_formatter {
+
+namespace top_domains {
+
+TopDomainTrieEntry::TopDomainTrieEntry(
+    const net::huffman_trie::HuffmanRepresentationTable& huffman_table,
+    net::huffman_trie::HuffmanBuilder* huffman_builder,
+    TopDomainEntry* entry)
+    : huffman_table_(huffman_table),
+      huffman_builder_(huffman_builder),
+      entry_(entry) {}
+
+TopDomainTrieEntry::~TopDomainTrieEntry() {}
+
+std::string TopDomainTrieEntry::name() const {
+  return entry_->skeleton;
+}
+
+bool TopDomainTrieEntry::WriteEntry(
+    net::huffman_trie::TrieBitBuffer* writer) const {
+  if (entry_->skeleton == entry_->top_domain) {
+    writer->WriteBit(1);
+    return true;
+  }
+  writer->WriteBit(0);
+
+  std::string top_domain = entry_->top_domain;
+  // With the current top 10,000 domains, this optimization reduces the
+  // additional binary size required for the trie from 71 kB to 59 kB.
+  if (base::EndsWith(top_domain, ".com",
+                     base::CompareCase::INSENSITIVE_ASCII)) {
+    writer->WriteBit(1);
+    top_domain = top_domain.substr(0, top_domain.size() - 4);
+  } else {
+    writer->WriteBit(0);
+  }
+
+  for (const auto& c : top_domain) {
+    writer->WriteChar(c, huffman_table_, huffman_builder_);
+  }
+  writer->WriteChar(net::huffman_trie::kEndOfTableValue, huffman_table_,
+                    huffman_builder_);
+  return true;
+}
+
+}  // namespace top_domains
+
+}  // namespace url_formatter
diff --git a/components/url_formatter/top_domains/trie_entry.h b/components/url_formatter/top_domains/trie_entry.h
new file mode 100644
index 0000000..d48fcc4
--- /dev/null
+++ b/components/url_formatter/top_domains/trie_entry.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 COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
+#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "net/tools/huffman_trie/huffman/huffman_builder.h"
+#include "net/tools/huffman_trie/trie_entry.h"
+
+namespace url_formatter {
+
+namespace top_domains {
+
+struct TopDomainEntry {
+  std::string skeleton;
+  std::string top_domain;
+};
+
+class TopDomainTrieEntry : public net::huffman_trie::TrieEntry {
+ public:
+  explicit TopDomainTrieEntry(
+      const net::huffman_trie::HuffmanRepresentationTable& huffman_table,
+      net::huffman_trie::HuffmanBuilder* huffman_builder,
+      TopDomainEntry* entry);
+  ~TopDomainTrieEntry() override;
+
+  // huffman_trie::TrieEntry:
+  std::string name() const override;
+  bool WriteEntry(net::huffman_trie::TrieBitBuffer* writer) const override;
+
+ private:
+  const net::huffman_trie::HuffmanRepresentationTable& huffman_table_;
+  net::huffman_trie::HuffmanBuilder* huffman_builder_;
+  TopDomainEntry* entry_;
+};
+
+using TopDomainEntries = std::vector<std::unique_ptr<TopDomainEntry>>;
+
+}  // namespace top_domains
+
+}  // namespace url_formatter
+
+#endif  // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc
index 36a788f..e475610 100644
--- a/components/url_formatter/url_formatter_unittest.cc
+++ b/components/url_formatter/url_formatter_unittest.cc
@@ -993,14 +993,18 @@
 }
 
 namespace test {
-#include "components/url_formatter/top_domains/test_skeletons-inc.cc"
+#include "components/url_formatter/top_domains/test_domains-trie-inc.cc"
 }
 
 }  // namespace
 
 TEST(UrlFormatterTest, IDNToUnicode) {
-  IDNSpoofChecker::SetTopDomainGraph(base::StringPiece(
-      reinterpret_cast<const char*>(test::kDafsa), sizeof(test::kDafsa)));
+  IDNSpoofChecker::HuffmanTrieParams trie_params{
+      test::kTopDomainsHuffmanTree, sizeof(test::kTopDomainsHuffmanTree),
+      test::kTopDomainsTrie, test::kTopDomainsTrieBits,
+      test::kTopDomainsRootPosition};
+  IDNSpoofChecker::SetTrieParamsForTesting(trie_params);
+
   for (size_t i = 0; i < arraysize(idn_cases); i++) {
     base::string16 output(IDNToUnicode(idn_cases[i].input));
     base::string16 expected(idn_cases[i].unicode_allowed
@@ -1009,7 +1013,7 @@
     EXPECT_EQ(expected, output) << "input # " << i << ": \""
                                 << idn_cases[i].input << "\"";
   }
-  IDNSpoofChecker::RestoreTopDomainGraphToDefault();
+  IDNSpoofChecker::RestoreTrieParamsForTesting();
 }
 
 TEST(UrlFormatterTest, FormatUrl) {
diff --git a/components/viz/client/client_resource_provider_unittest.cc b/components/viz/client/client_resource_provider_unittest.cc
index e2fd790b2..da03c3c 100644
--- a/components/viz/client/client_resource_provider_unittest.cc
+++ b/components/viz/client/client_resource_provider_unittest.cc
@@ -107,7 +107,6 @@
 TEST_P(ClientResourceProviderTest, TransferableResourceSendToParent) {
   MockReleaseCallback release;
   TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
-  tran.buffer_format = gfx::BufferFormat::RGBX_8888;
   ResourceId id = provider().ImportResource(
       tran, SingleReleaseCallback::Create(base::BindOnce(
                 &MockReleaseCallback::Released, base::Unretained(&release))));
@@ -132,7 +131,6 @@
   EXPECT_EQ(exported[0].mailbox_holder.sync_token, verified_sync_token);
   EXPECT_EQ(exported[0].mailbox_holder.texture_target,
             tran.mailbox_holder.texture_target);
-  EXPECT_EQ(exported[0].buffer_format, tran.buffer_format);
 
   // Exported resources are not released when removed, until the export returns.
   EXPECT_CALL(release, Released(_, _)).Times(0);
@@ -182,7 +180,6 @@
     EXPECT_EQ(exported[i].mailbox_holder.sync_token, verified_sync_token);
     EXPECT_EQ(exported[i].mailbox_holder.texture_target,
               tran[i].mailbox_holder.texture_target);
-    EXPECT_EQ(exported[i].buffer_format, tran[i].buffer_format);
   }
 
   provider().RemoveImportedResource(id1);
diff --git a/components/viz/common/resources/platform_color.h b/components/viz/common/resources/platform_color.h
index 6bf22ad8..28222d8 100644
--- a/components/viz/common/resources/platform_color.h
+++ b/components/viz/common/resources/platform_color.h
@@ -69,6 +69,15 @@
       case LUMINANCE_F16:
       case RGBA_F16:
       case R16_EXT:
+      case BGR_565:
+      case RG_88:
+      case RGBX_8888:
+      case BGRX_8888:
+      case RGBX_1010102:
+      case BGRX_1010102:
+      case YVU_420:
+      case YUV_420_BIPLANAR:
+      case UYVY_422:
         break;
     }
 
diff --git a/components/viz/common/resources/platform_color_unittest.cc b/components/viz/common/resources/platform_color_unittest.cc
index feab684..ee4bdf4 100644
--- a/components/viz/common/resources/platform_color_unittest.cc
+++ b/components/viz/common/resources/platform_color_unittest.cc
@@ -28,12 +28,21 @@
       case ALPHA_8:
       case LUMINANCE_8:
       case RGB_565:
+      case BGR_565:
       case RGBA_4444:
       case ETC1:
       case RED_8:
+      case RG_88:
       case LUMINANCE_F16:
       case RGBA_F16:
       case R16_EXT:
+      case RGBX_8888:
+      case BGRX_8888:
+      case RGBX_1010102:
+      case BGRX_1010102:
+      case YVU_420:
+      case YUV_420_BIPLANAR:
+      case UYVY_422:
         break;
     }
   }
diff --git a/components/viz/common/resources/resource_format.h b/components/viz/common/resources/resource_format.h
index 265a064cb..30a75a3 100644
--- a/components/viz/common/resources/resource_format.h
+++ b/components/viz/common/resources/resource_format.h
@@ -16,12 +16,21 @@
   ALPHA_8,
   LUMINANCE_8,
   RGB_565,
+  BGR_565,
   ETC1,
   RED_8,
+  RG_88,
   LUMINANCE_F16,
   RGBA_F16,
   R16_EXT,
-  RESOURCE_FORMAT_MAX = R16_EXT,
+  RGBX_8888,
+  BGRX_8888,
+  RGBX_1010102,
+  BGRX_1010102,
+  YVU_420,
+  YUV_420_BIPLANAR,
+  UYVY_422,
+  RESOURCE_FORMAT_MAX = UYVY_422,
 };
 
 }  // namespace viz
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc
index dcf5d8d..800ce70c 100644
--- a/components/viz/common/resources/resource_format_utils.cc
+++ b/components/viz/common/resources/resource_format_utils.cc
@@ -39,6 +39,15 @@
     case RED_8:
     case LUMINANCE_F16:
     case R16_EXT:
+    case BGR_565:
+    case RG_88:
+    case RGBX_8888:
+    case BGRX_8888:
+    case RGBX_1010102:
+    case BGRX_1010102:
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+    case UYVY_422:
       return kN32_SkColorType;
     case RGBA_F16:
       return kRGBA_F16_SkColorType;
@@ -53,12 +62,22 @@
       return 64;
     case BGRA_8888:
     case RGBA_8888:
+    case RGBX_8888:
+    case BGRX_8888:
+    case RGBX_1010102:
+    case BGRX_1010102:
       return 32;
     case RGBA_4444:
     case RGB_565:
     case LUMINANCE_F16:
     case R16_EXT:
+    case BGR_565:
+    case RG_88:
+    case UYVY_422:
       return 16;
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+      return 12;
     case ALPHA_8:
     case LUMINANCE_8:
     case RED_8:
@@ -79,11 +98,20 @@
       GL_UNSIGNED_BYTE,           // ALPHA_8
       GL_UNSIGNED_BYTE,           // LUMINANCE_8
       GL_UNSIGNED_SHORT_5_6_5,    // RGB_565,
+      GL_ZERO,                    // BGR_565
       GL_UNSIGNED_BYTE,           // ETC1
       GL_UNSIGNED_BYTE,           // RED_8
+      GL_UNSIGNED_BYTE,           // RG_88
       GL_HALF_FLOAT_OES,          // LUMINANCE_F16
       GL_HALF_FLOAT_OES,          // RGBA_F16
       GL_UNSIGNED_SHORT,          // R16_EXT
+      GL_UNSIGNED_BYTE,           // RGBX_8888
+      GL_ZERO,                    // BGRX_8888
+      GL_UNSIGNED_INT,            // RGBX_1010102
+      GL_ZERO,                    // BGRX_1010102
+      GL_ZERO,                    // YVU_420
+      GL_ZERO,                    // YUV_420_BIPLANAR
+      GL_ZERO,                    // UYVY_422
   };
   static_assert(arraysize(format_gl_data_type) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_type does not handle all cases.");
@@ -100,14 +128,24 @@
       GL_ALPHA,          // ALPHA_8
       GL_LUMINANCE,      // LUMINANCE_8
       GL_RGB,            // RGB_565
+      GL_ZERO,           // BGR_565
       GL_ETC1_RGB8_OES,  // ETC1
       GL_RED_EXT,        // RED_8
+      GL_RG_EXT,         // RG_88
       GL_LUMINANCE,      // LUMINANCE_F16
       GL_RGBA,           // RGBA_F16
       GL_RED_EXT,        // R16_EXT
+      GL_RGB,            // RGBX_8888
+      GL_ZERO,           // BGRX_8888
+      GL_RGB10_A2_EXT,   // RGBX_1010102
+      GL_ZERO,           // BGRX_1010102
+      GL_ZERO,           // YVU_420
+      GL_ZERO,           // YUV_420_BIPLANAR
+      GL_ZERO,           // UYVY_422
   };
   static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_format does not handle all cases.");
+
   return format_gl_data_format[format];
 }
 
@@ -118,6 +156,8 @@
   // internal format (GL_R16_EXT).
   if (format == R16_EXT)
     return GL_R16_EXT;
+  else if (format == RG_88)
+    return GL_RG8_EXT;
 
   return GLDataFormat(format);
 }
@@ -137,14 +177,25 @@
       GL_ALPHA,      // ALPHA_8
       GL_LUMINANCE,  // LUMINANCE_8
       GL_RGB,        // RGB_565
+      GL_ZERO,       // BGR_565
       GL_RGB,        // ETC1
       GL_LUMINANCE,  // RED_8
+      GL_RGBA,       // RG_88
       GL_LUMINANCE,  // LUMINANCE_F16
       GL_RGBA,       // RGBA_F16
       GL_LUMINANCE,  // R16_EXT
+      GL_RGB,        // RGBX_8888
+      GL_RGB,        // BGRX_8888
+      GL_ZERO,       // RGBX_1010102
+      GL_ZERO,       // BGRX_1010102
+      GL_ZERO,       // YVU_420
+      GL_ZERO,       // YUV_420_BIPLANAR
+      GL_ZERO,       // UYVY_422
   };
+
   static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1),
                 "format_gl_data_format does not handle all cases.");
+
   return format_gl_data_format[format];
 }
 
@@ -164,6 +215,24 @@
       return gfx::BufferFormat::ETC1;
     case RGBA_F16:
       return gfx::BufferFormat::RGBA_F16;
+    case BGR_565:
+      return gfx::BufferFormat::BGR_565;
+    case RG_88:
+      return gfx::BufferFormat::RG_88;
+    case RGBX_8888:
+      return gfx::BufferFormat::RGBX_8888;
+    case BGRX_8888:
+      return gfx::BufferFormat::BGRX_8888;
+    case RGBX_1010102:
+      return gfx::BufferFormat::RGBX_1010102;
+    case BGRX_1010102:
+      return gfx::BufferFormat::BGRX_1010102;
+    case YVU_420:
+      return gfx::BufferFormat::YVU_420;
+    case YUV_420_BIPLANAR:
+      return gfx::BufferFormat::YUV_420_BIPLANAR;
+    case UYVY_422:
+      return gfx::BufferFormat::UYVY_422;
     case ALPHA_8:
     case LUMINANCE_8:
     case RGB_565:
@@ -203,6 +272,16 @@
       return GL_R16_EXT;
     case ETC1:
       break;
+    case RG_88:
+    case RGBX_8888:
+    case BGRX_8888:
+    case RGBX_1010102:
+    case BGRX_1010102:
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+    case UYVY_422:
+    case BGR_565:
+      break;
   }
   NOTREACHED();
   return GL_RGBA8_OES;
@@ -218,11 +297,21 @@
     case ETC1:
     case RGBA_F16:
       return true;
-    // These formats have no BufferFormat equivalent.
+    // These formats have no BufferFormat equivalent or are only used
+    // for external textures, or have no GL equivalent formats.
     case ALPHA_8:
     case LUMINANCE_8:
     case RGB_565:
     case LUMINANCE_F16:
+    case BGR_565:
+    case RG_88:
+    case RGBX_8888:
+    case BGRX_8888:
+    case RGBX_1010102:
+    case BGRX_1010102:
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+    case UYVY_422:
       return false;
   }
   NOTREACHED();
@@ -243,10 +332,73 @@
     case LUMINANCE_F16:
     case RGBA_F16:
     case R16_EXT:
+    case BGR_565:
+    case RG_88:
+    case RGBX_8888:
+    case BGRX_8888:
+    case RGBX_1010102:
+    case BGRX_1010102:
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+    case UYVY_422:
       return false;
   }
   NOTREACHED();
   return false;
 }
 
+ResourceFormat GetResourceFormat(gfx::BufferFormat format) {
+  switch (format) {
+    case gfx::BufferFormat::BGRA_8888:
+      return BGRA_8888;
+    case gfx::BufferFormat::R_8:
+      return RED_8;
+    case gfx::BufferFormat::R_16:
+      return R16_EXT;
+    case gfx::BufferFormat::RGBA_4444:
+      return RGBA_4444;
+    case gfx::BufferFormat::RGBA_8888:
+      return RGBA_8888;
+    case gfx::BufferFormat::ETC1:
+      return ETC1;
+    case gfx::BufferFormat::RGBA_F16:
+      return RGBA_F16;
+    case gfx::BufferFormat::BGR_565:
+      return BGR_565;
+    case gfx::BufferFormat::RG_88:
+      return RG_88;
+    case gfx::BufferFormat::RGBX_8888:
+      return RGBX_8888;
+    case gfx::BufferFormat::BGRX_8888:
+      return BGRX_8888;
+    case gfx::BufferFormat::RGBX_1010102:
+      return RGBX_1010102;
+    case gfx::BufferFormat::BGRX_1010102:
+      return BGRX_1010102;
+    case gfx::BufferFormat::YVU_420:
+      return YVU_420;
+    case gfx::BufferFormat::YUV_420_BIPLANAR:
+      return YUV_420_BIPLANAR;
+    case gfx::BufferFormat::UYVY_422:
+      return UYVY_422;
+    default:
+      NOTREACHED();
+      return RGBA_8888;
+  }
+}
+
+bool GLSupportsFormat(ResourceFormat format) {
+  switch (format) {
+    case BGR_565:
+    case BGRX_8888:
+    case BGRX_1010102:
+    case YVU_420:
+    case YUV_420_BIPLANAR:
+    case UYVY_422:
+      return false;
+    default:
+      return true;
+  }
+}
+
 }  // namespace viz
diff --git a/components/viz/common/resources/resource_format_utils.h b/components/viz/common/resources/resource_format_utils.h
index 27957f6..1b7cf81 100644
--- a/components/viz/common/resources/resource_format_utils.h
+++ b/components/viz/common/resources/resource_format_utils.h
@@ -47,6 +47,11 @@
 // display compositor.
 VIZ_RESOURCE_FORMAT_EXPORT bool IsBitmapFormatSupported(ResourceFormat format);
 
+VIZ_RESOURCE_FORMAT_EXPORT ResourceFormat
+GetResourceFormat(gfx::BufferFormat format);
+
+VIZ_RESOURCE_FORMAT_EXPORT bool GLSupportsFormat(ResourceFormat format);
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_COMMON_RESOURCES_RESOURCE_FORMAT_UTILS_H_
diff --git a/components/viz/common/resources/transferable_resource.h b/components/viz/common/resources/transferable_resource.h
index 76f673e..d39240a 100644
--- a/components/viz/common/resources/transferable_resource.h
+++ b/components/viz/common/resources/transferable_resource.h
@@ -97,11 +97,6 @@
   // and must be RGBA_8888 always for software resources.
   ResourceFormat format = RGBA_8888;
 
-  // Normally derrived from the |format|, but may differ for some resource
-  // producers. This is the format of the underlying texture backing for gpu
-  // resources, needed for using the backing as an overlay.
-  gfx::BufferFormat buffer_format = gfx::BufferFormat::RGBA_8888;
-
   // The |mailbox| inside here holds the gpu::Mailbox when this is a gpu
   // resource, or the SharedBitmapId when it is a software resource.
   // The |texture_target| and sync_token| inside here only apply for gpu
@@ -139,7 +134,7 @@
 
   bool operator==(const TransferableResource& o) const {
     return id == o.id && is_software == o.is_software && size == o.size &&
-           format == o.format && buffer_format == o.buffer_format &&
+           format == o.format &&
            mailbox_holder.mailbox == o.mailbox_holder.mailbox &&
            mailbox_holder.sync_token == o.mailbox_holder.sync_token &&
            mailbox_holder.texture_target == o.mailbox_holder.texture_target &&
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc
index bfc531e9..da2cff4 100644
--- a/components/viz/service/display/display_resource_provider.cc
+++ b/components/viz/service/display/display_resource_provider.cc
@@ -239,7 +239,7 @@
 
 gfx::BufferFormat DisplayResourceProvider::GetBufferFormat(ResourceId id) {
   ChildResource* resource = GetResource(id);
-  return resource->transferable.buffer_format;
+  return BufferFormat(resource->transferable.format);
 }
 
 void DisplayResourceProvider::WaitSyncToken(ResourceId id) {
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 51e9fba..f0af92a3 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -757,10 +757,13 @@
   // texture. Otherwise, we use the format of the default framebuffer. But
   // whatever the format is, convert it to a valid format for CopyTexSubImage2D.
   GLenum format;
-  if (!current_framebuffer_texture_)
+  if (!current_framebuffer_texture_) {
     format = output_surface_->GetFramebufferCopyTextureFormat();
-  else
-    format = GLCopyTextureInternalFormat(BackbufferFormat());
+  } else {
+    ResourceFormat resource_format = BackbufferFormat();
+    DCHECK(GLSupportsFormat(resource_format));
+    format = GLCopyTextureInternalFormat(resource_format);
+  }
   // Verify the format is valid for GLES2's glCopyTexSubImage2D.
   DCHECK(format == GL_ALPHA || format == GL_LUMINANCE ||
          format == GL_LUMINANCE_ALPHA || format == GL_RGB ||
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 6d5d4d653..50933bb 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -102,11 +102,6 @@
       mailbox, GL_LINEAR, allocation.texture_target, sync_token);
   gl_resource.size = size;
   gl_resource.format = format;
-  // We didn't allocate a GpuMemoryBuffer, but we want to set buffer_format for
-  // consistency with other callsites.
-  // TODO(piman): See if we can remove TransferableResource::buffer_format
-  // altogether, it looks redundant with format. crbug.com/836488
-  gl_resource.buffer_format = BufferFormat(format);
   gl_resource.color_space = std::move(color_space);
   auto release_callback = SingleReleaseCallback::Create(base::BindOnce(
       &DeleteTexture, std::move(context_provider), allocation.texture_id));
diff --git a/components/viz/service/display/scoped_render_pass_texture.cc b/components/viz/service/display/scoped_render_pass_texture.cc
index 1357cc2..7f69f85d 100644
--- a/components/viz/service/display/scoped_render_pass_texture.cc
+++ b/components/viz/service/display/scoped_render_pass_texture.cc
@@ -52,6 +52,7 @@
     gl->TexStorage2DEXT(GL_TEXTURE_2D, levels, TextureStorageFormat(format),
                         size_.width(), size_.height());
   } else {
+    DCHECK(GLSupportsFormat(format));
     gl->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size_.width(),
                    size_.height(), 0, GLDataFormat(format), GLDataType(format),
                    nullptr);
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index 1db2a5ce..2cfe760 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -673,9 +673,8 @@
   delegate_->AccessibilityPerformAction(action_data);
 }
 
-void BrowserAccessibilityManager::SetValue(
-    const BrowserAccessibility& node,
-    const base::string16& value) {
+void BrowserAccessibilityManager::SetValue(const BrowserAccessibility& node,
+                                           const std::string& value) {
   if (!delegate_)
     return;
 
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 2a38e931..6279fdbe 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/callback_forward.h"
@@ -218,8 +219,7 @@
   void SetAccessibilityFocus(const BrowserAccessibility& node);
   void SetFocus(const BrowserAccessibility& node);
   void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
-  void SetValue(
-      const BrowserAccessibility& node, const base::string16& value);
+  void SetValue(const BrowserAccessibility& node, const std::string& value);
   void SetSelection(
       ui::AXRange<
           BrowserAccessibilityPosition::AXPositionInstance::element_type>
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index c1be0a5d..ee2bfb2 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -855,7 +855,7 @@
   BrowserAccessibilityAndroid* node = GetAXFromUniqueID(unique_id);
   if (node) {
     node->manager()->SetValue(
-        *node, base::android::ConvertJavaStringToUTF16(env, value));
+        *node, base::android::ConvertJavaStringToUTF8(env, value));
   }
 }
 
@@ -909,7 +909,7 @@
   value += (increment ? delta : -delta);
   value = std::max(std::min(value, max), min);
   if (value != original_value) {
-    node->manager()->SetValue(*node, base::NumberToString16(value));
+    node->manager()->SetValue(*node, base::NumberToString(value));
     return true;
   }
   return false;
diff --git a/content/browser/frame_host/render_frame_host_android.cc b/content/browser/frame_host/render_frame_host_android.cc
index 8ef7214..63de23c 100644
--- a/content/browser/frame_host/render_frame_host_android.cc
+++ b/content/browser/frame_host/render_frame_host_android.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/frame_host/render_frame_host_android.h"
 
+#include <utility>
+
 #include "base/android/callback_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/unguessable_token_android.h"
@@ -28,12 +30,12 @@
     const base::android::JavaRef<jobject>& jcallback,
     const base::Optional<GURL>& url) {
   if (!url) {
-    base::android::RunCallbackAndroid(jcallback, ScopedJavaLocalRef<jstring>());
+    base::android::RunObjectCallbackAndroid(jcallback,
+                                            ScopedJavaLocalRef<jstring>());
     return;
   }
 
-  base::android::RunCallbackAndroid(
-      jcallback, ConvertUTF8ToJavaString(AttachCurrentThread(), url->spec()));
+  base::android::RunStringCallbackAndroid(jcallback, url->spec());
 }
 }  // namespace
 
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index e544215..f65dc57 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -623,27 +623,12 @@
 void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
   ResourceRequestInfoImpl* info = loader->GetRequestInfo();
 
-  base::TimeDelta request_loading_time(base::TimeTicks::Now() -
-                                       loader->request()->creation_time());
-
   // Record final result of all resource loads.
   if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
     // This enumeration has "3" appended to its name to distinguish it from
     // older versions.
     base::UmaHistogramSparse("Net.ErrorCodesForMainFrame3",
                              -loader->request()->status().error());
-    if (loader->request()->status().error() == net::OK) {
-      UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.MainFrame",
-                               request_loading_time);
-    }
-    if (loader->request()->status().error() == net::ERR_ABORTED) {
-      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.SentBytes",
-                                  loader->request()->GetTotalSentBytes(), 1,
-                                  50000000, 50);
-      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ErrAborted.ReceivedBytes",
-                                  loader->request()->GetTotalReceivedBytes(), 1,
-                                  50000000, 50);
-    }
 
     if (loader->request()->url().SchemeIsCryptographic()) {
       if (loader->request()->url().host_piece() == "www.google.com") {
@@ -664,10 +649,6 @@
           "Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
     }
   } else {
-    if (loader->request()->status().error() == net::OK) {
-      UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2Success.Subresource",
-                               request_loading_time);
-    }
     if (info->GetResourceType() == RESOURCE_TYPE_IMAGE) {
       base::UmaHistogramSparse("Net.ErrorCodesForImages",
                                -loader->request()->status().error());
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index 95eaa9c..4e4d681 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -630,8 +630,6 @@
     request_->SetResponseHeadersCallback(base::Bind(
         &ResourceLoader::SetRawResponseHeaders, base::Unretained(this)));
   }
-  UMA_HISTOGRAM_TIMES("Net.ResourceLoader.TimeToURLRequestStart",
-                      base::TimeTicks::Now() - request_->creation_time());
   request_->Start();
 
   delegate_->DidStartRequest(this);
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index baa1e6f..1a60e3cd 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -397,7 +397,6 @@
   bool SynchronizeVisualProperties() override;
 
   // AcceleratedWidgetMacNSView implementation.
-  NSView* AcceleratedWidgetGetNSView() const override;
   void AcceleratedWidgetCALayerParamsUpdated() override;
 
   void SetShowingContextMenu(bool showing) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index f0db8b5e..acb6a0f9 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -110,10 +110,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // AcceleratedWidgetMacNSView, public:
 
-NSView* RenderWidgetHostViewMac::AcceleratedWidgetGetNSView() const {
-  return cocoa_view();
-}
-
 void RenderWidgetHostViewMac::AcceleratedWidgetCALayerParamsUpdated() {
   // Set the background color for the root layer from the frame that just
   // swapped. See RenderWidgetHostViewAura for more details. Note that this is
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 3e729fc..6b5e05d 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -610,7 +610,7 @@
 // Enables developers to use the CSS safe-area-* and viewport-fit APIs which
 // allow them to support devices with a display cutout.
 const base::Feature kDisplayCutoutAPI{"DisplayCutoutAPI",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables hiding incorrectly-sized frames while in fullscreen.
 const base::Feature kHideIncorrectlySizedFullscreenFrames{
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index bf2d709..8de7792 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -652,7 +652,7 @@
       target.SetSequentialFocusNavigationStartingPoint();
       break;
     case ax::mojom::Action::kSetValue:
-      target.SetValue(blink::WebString::FromUTF16(data.value));
+      target.SetValue(blink::WebString::FromUTF8(data.value));
       HandleAXEvent(target, ax::mojom::Event::kValueChanged);
       break;
     case ax::mojom::Action::kShowContextMenu:
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index 4e31cb1..e12421d 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -110,6 +110,8 @@
     "u2f_register_operation.h",
     "u2f_sign_operation.cc",
     "u2f_sign_operation.h",
+    "virtual_ctap2_device.cc",
+    "virtual_ctap2_device.h",
     "virtual_fido_device.cc",
     "virtual_fido_device.h",
     "virtual_u2f_device.cc",
diff --git a/device/fido/authenticator_get_info_response.cc b/device/fido/authenticator_get_info_response.cc
index 67e5478..37de6493 100644
--- a/device/fido/authenticator_get_info_response.cc
+++ b/device/fido/authenticator_get_info_response.cc
@@ -8,6 +8,7 @@
 
 #include "components/cbor/cbor_values.h"
 #include "components/cbor/cbor_writer.h"
+#include "device/fido/fido_parsing_utils.h"
 
 namespace device {
 
@@ -26,8 +27,9 @@
 
 AuthenticatorGetInfoResponse::AuthenticatorGetInfoResponse(
     base::flat_set<ProtocolVersion> versions,
-    std::vector<uint8_t> aaguid)
-    : versions_(std::move(versions)), aaguid_(std::move(aaguid)) {}
+    base::span<const uint8_t, kAaguidLength> aaguid)
+    : versions_(std::move(versions)),
+      aaguid_(fido_parsing_utils::Materialize(aaguid)) {}
 
 AuthenticatorGetInfoResponse::AuthenticatorGetInfoResponse(
     AuthenticatorGetInfoResponse&& that) = default;
diff --git a/device/fido/authenticator_get_info_response.h b/device/fido/authenticator_get_info_response.h
index 46dee88..b6fd9b1 100644
--- a/device/fido/authenticator_get_info_response.h
+++ b/device/fido/authenticator_get_info_response.h
@@ -26,7 +26,7 @@
 class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetInfoResponse {
  public:
   AuthenticatorGetInfoResponse(base::flat_set<ProtocolVersion> versions,
-                               std::vector<uint8_t> aaguid);
+                               base::span<const uint8_t, kAaguidLength> aaguid);
   AuthenticatorGetInfoResponse(AuthenticatorGetInfoResponse&& that);
   AuthenticatorGetInfoResponse& operator=(AuthenticatorGetInfoResponse&& other);
   ~AuthenticatorGetInfoResponse();
@@ -40,7 +40,7 @@
       AuthenticatorSupportedOptions options);
 
   const base::flat_set<ProtocolVersion>& versions() const { return versions_; }
-  const std::vector<uint8_t>& aaguid() const { return aaguid_; }
+  const std::array<uint8_t, kAaguidLength>& aaguid() const { return aaguid_; }
   const base::Optional<uint32_t>& max_msg_size() const { return max_msg_size_; }
   const base::Optional<std::vector<uint8_t>>& pin_protocol() const {
     return pin_protocols_;
@@ -52,7 +52,7 @@
 
  private:
   base::flat_set<ProtocolVersion> versions_;
-  std::vector<uint8_t> aaguid_;
+  std::array<uint8_t, kAaguidLength> aaguid_;
   base::Optional<uint32_t> max_msg_size_;
   base::Optional<std::vector<uint8_t>> pin_protocols_;
   base::Optional<std::vector<std::string>> extensions_;
diff --git a/device/fido/ctap_make_credential_request.h b/device/fido/ctap_make_credential_request.h
index 556b55466..3b43491 100644
--- a/device/fido/ctap_make_credential_request.h
+++ b/device/fido/ctap_make_credential_request.h
@@ -70,6 +70,9 @@
   exclude_list() const {
     return exclude_list_;
   }
+  const base::Optional<std::vector<uint8_t>>& pin_auth() const {
+    return pin_auth_;
+  }
 
  private:
   std::array<uint8_t, kClientDataHashLength> client_data_hash_;
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc
index 2d8e23b..567ac36 100644
--- a/device/fido/ctap_response_unittest.cc
+++ b/device/fido/ctap_response_unittest.cc
@@ -198,9 +198,9 @@
     // and test_data::kTestECPublicKeyCOSE.
     0x58, 0xC4};
 
-constexpr uint8_t kTestDeviceAaguid[] = {0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A,
-                                         0x4D, 0x15, 0x80, 0x06, 0x17, 0x11,
-                                         0x1F, 0x9E, 0xDC, 0x7D};
+constexpr std::array<uint8_t, kAaguidLength> kTestDeviceAaguid = {
+    {0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17, 0x11,
+     0x1F, 0x9E, 0xDC, 0x7D}};
 
 std::vector<uint8_t> GetTestAttestedCredentialDataBytes() {
   // Combine kTestAttestedCredentialDataPrefix and kTestECPublicKeyCOSE.
diff --git a/device/fido/make_credential_task_unittest.cc b/device/fido/make_credential_task_unittest.cc
index fa504c5..b97aa9b 100644
--- a/device/fido/make_credential_task_unittest.cc
+++ b/device/fido/make_credential_task_unittest.cc
@@ -20,6 +20,7 @@
 #include "device/fido/make_credential_task.h"
 #include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
+#include "device/fido/virtual_ctap2_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -107,6 +108,21 @@
   EXPECT_TRUE(device->device_info());
 }
 
+TEST_F(FidoMakeCredentialTaskTest, TestRegisterSuccessWithFake) {
+  auto device = std::make_unique<VirtualCtap2Device>();
+  const auto task = CreateMakeCredentialTask(device.get());
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            make_credential_callback_receiver().status());
+
+  // We don't verify the response from the fake, but do a quick sanity check.
+  ASSERT_TRUE(make_credential_callback_receiver().value());
+  EXPECT_EQ(
+      32u,
+      make_credential_callback_receiver().value()->raw_credential_id().size());
+}
+
 TEST_F(FidoMakeCredentialTaskTest, MakeCredentialWithIncorrectRpIdHash) {
   auto device = std::make_unique<MockFidoDevice>();
 
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
new file mode 100644
index 0000000..da36e42b
--- /dev/null
+++ b/device/fido/virtual_ctap2_device.cc
@@ -0,0 +1,278 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/fido/virtual_ctap2_device.h"
+
+#include <array>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/cbor/cbor_writer.h"
+#include "crypto/ec_private_key.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/ec_public_key.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_parsing_utils.h"
+#include "device/fido/opaque_attestation_statement.h"
+
+namespace device {
+
+namespace {
+
+constexpr std::array<uint8_t, kAaguidLength> kDeviceAaguid = {
+    {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04,
+     0x05, 0x06, 0x07, 0x08}};
+
+std::vector<uint8_t> ConstructResponse(CtapDeviceResponseCode response_code,
+                                       base::span<const uint8_t> data) {
+  std::vector<uint8_t> response{base::strict_cast<uint8_t>(response_code)};
+  fido_parsing_utils::Append(&response, data);
+  return response;
+}
+
+void ReturnCtap2Response(
+    FidoDevice::DeviceCallback cb,
+    CtapDeviceResponseCode response_code,
+    base::Optional<base::span<const uint8_t>> data = base::nullopt) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(cb),
+                     ConstructResponse(response_code,
+                                       data.value_or(std::vector<uint8_t>{}))));
+}
+
+bool AreMakeCredentialOptionsValid(const AuthenticatorSupportedOptions& options,
+                                   const CtapMakeCredentialRequest& request) {
+  if (request.resident_key_supported() && !options.supports_resident_key())
+    return false;
+
+  return !request.user_verification_required() ||
+         options.user_verification_availability() ==
+             AuthenticatorSupportedOptions::UserVerificationAvailability::
+                 kSupportedAndConfigured;
+}
+
+// Checks that whether the received MakeCredential request includes EA256
+// algorithm in publicKeyCredParam.
+bool AreMakeCredentialParamsValid(const CtapMakeCredentialRequest& request) {
+  const auto& params =
+      request.public_key_credential_params().public_key_credential_params();
+  return std::any_of(
+      params.begin(), params.end(), [](const auto& credential_info) {
+        return credential_info.algorithm ==
+               base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256);
+      });
+}
+
+std::unique_ptr<ECPublicKey> ConstructECPublicKey(
+    std::string public_key_string) {
+  DCHECK_EQ(64u, public_key_string.size());
+
+  const auto public_key_x_coordinate =
+      base::as_bytes(base::make_span(public_key_string)).first(32);
+  const auto public_key_y_coordinate =
+      base::as_bytes(base::make_span(public_key_string)).last(32);
+  return std::make_unique<ECPublicKey>(
+      fido_parsing_utils::kEs256,
+      fido_parsing_utils::Materialize(public_key_x_coordinate),
+      fido_parsing_utils::Materialize(public_key_y_coordinate));
+}
+
+std::vector<uint8_t> ConstructSignatureBuffer(
+    const AuthenticatorData& authenticator_data,
+    base::span<const uint8_t, kClientDataHashLength> client_data_hash) {
+  std::vector<uint8_t> signature_buffer;
+  fido_parsing_utils::Append(&signature_buffer,
+                             authenticator_data.SerializeToByteArray());
+  fido_parsing_utils::Append(&signature_buffer, client_data_hash);
+  return signature_buffer;
+}
+
+std::vector<uint8_t> ConstructMakeCredentialResponse(
+    base::span<const uint8_t> attestation_certificate,
+    base::span<const uint8_t> signature,
+    AuthenticatorData authenticator_data) {
+  cbor::CBORValue::MapValue attestation_map;
+  attestation_map.emplace("alg", -7);
+  attestation_map.emplace("sig", fido_parsing_utils::Materialize(signature));
+
+  cbor::CBORValue::ArrayValue certificate_chain;
+  certificate_chain.emplace_back(
+      fido_parsing_utils::Materialize(attestation_certificate));
+  attestation_map.emplace("x5c", std::move(certificate_chain));
+  AuthenticatorMakeCredentialResponse make_credential_response(
+      AttestationObject(
+          std::move(authenticator_data),
+          std::make_unique<OpaqueAttestationStatement>(
+              "packed", cbor::CBORValue(std::move(attestation_map)))));
+  return GetSerializedCtapDeviceResponse(make_credential_response);
+}
+
+}  // namespace
+
+VirtualCtap2Device::VirtualCtap2Device()
+    : VirtualFidoDevice(),
+      device_info_(AuthenticatorGetInfoResponse({ProtocolVersion::kCtap},
+                                                kDeviceAaguid)),
+      weak_factory_(this) {}
+
+VirtualCtap2Device::VirtualCtap2Device(scoped_refptr<State> state)
+    : VirtualFidoDevice(std::move(state)),
+      device_info_(AuthenticatorGetInfoResponse({ProtocolVersion::kCtap},
+                                                kDeviceAaguid)),
+      weak_factory_(this) {}
+
+VirtualCtap2Device::~VirtualCtap2Device() = default;
+
+// As all operations for VirtualCtap2Device are synchronous and we do not wait
+// for user touch, Cancel command is no-op.
+void VirtualCtap2Device::Cancel() {}
+
+void VirtualCtap2Device::DeviceTransact(std::vector<uint8_t> command,
+                                        DeviceCallback cb) {
+  if (command.empty()) {
+    ReturnCtap2Response(std::move(cb), CtapDeviceResponseCode::kCtap2ErrOther);
+    return;
+  }
+
+  auto cmd_type = command[0];
+  const auto request_bytes = base::make_span(command).subspan(1);
+  CtapDeviceResponseCode response_code = CtapDeviceResponseCode::kCtap2ErrOther;
+  std::vector<uint8_t> response_data;
+
+  switch (static_cast<CtapRequestCommand>(cmd_type)) {
+    case CtapRequestCommand::kAuthenticatorGetInfo:
+      if (!request_bytes.empty()) {
+        ReturnCtap2Response(std::move(cb),
+                            CtapDeviceResponseCode::kCtap2ErrOther);
+        return;
+      }
+
+      response_code = OnAuthenticatorGetInfo(&response_data);
+      break;
+    case CtapRequestCommand::kAuthenticatorMakeCredential:
+      response_code = OnMakeCredential(request_bytes, &response_data);
+      break;
+    default:
+      break;
+  }
+
+  // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
+  // support callback hairpinning.
+  ReturnCtap2Response(std::move(cb), response_code, std::move(response_data));
+}
+
+base::WeakPtr<FidoDevice> VirtualCtap2Device::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+void VirtualCtap2Device::SetAuthenticatorSupportedOptions(
+    AuthenticatorSupportedOptions options) {
+  device_info_.SetOptions(std::move(options));
+}
+
+CtapDeviceResponseCode VirtualCtap2Device::OnMakeCredential(
+    base::span<const uint8_t> request_bytes,
+    std::vector<uint8_t>* response) {
+  auto request = ParseCtapMakeCredentialRequest(request_bytes);
+  if (!request)
+    return CtapDeviceResponseCode::kCtap2ErrOther;
+
+  if (!AreMakeCredentialOptionsValid(device_info_.options(), *request) ||
+      !AreMakeCredentialParamsValid(*request)) {
+    return CtapDeviceResponseCode::kCtap2ErrOther;
+  }
+
+  // Client pin is not supported.
+  if (request->pin_auth())
+    return CtapDeviceResponseCode::kCtap2ErrPinInvalid;
+
+  // Check for already registered credentials.
+  const auto rp_id_hash =
+      fido_parsing_utils::CreateSHA256Hash(request->rp().rp_id());
+  if (request->exclude_list()) {
+    for (const auto& excluded_credential : *request->exclude_list()) {
+      if (FindRegistrationData(excluded_credential.id(), rp_id_hash))
+        return CtapDeviceResponseCode::kCtap2ErrCredentialExcluded;
+    }
+  }
+
+  // Create key to register.
+  // Note: Non-deterministic, you need to mock this out if you rely on
+  // deterministic behavior.
+  auto private_key = crypto::ECPrivateKey::Create();
+  std::string public_key;
+  bool status = private_key->ExportRawPublicKey(&public_key);
+  DCHECK(status);
+
+  // Our key handles are simple hashes of the public key.
+  auto hash = fido_parsing_utils::CreateSHA256Hash(public_key);
+  std::vector<uint8_t> key_handle(hash.begin(), hash.end());
+
+  AttestedCredentialData attested_credential_data(
+      kDeviceAaguid, {{0, crypto::kSHA256Length}}, key_handle,
+      ConstructECPublicKey(public_key));
+
+  auto authenticator_data = ConstructAuthenticatorData(
+      rp_id_hash, std::move(attested_credential_data));
+  auto sign_buffer =
+      ConstructSignatureBuffer(authenticator_data, request->client_data_hash());
+
+  // Sign with attestation key.
+  // Note: Non-deterministic, you need to mock this out if you rely on
+  // deterministic behavior.
+  std::vector<uint8_t> sig;
+  std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
+  status = Sign(attestation_private_key.get(), std::move(sign_buffer), &sig);
+  DCHECK(status);
+
+  auto attestation_cert = GenerateAttestationCertificate(
+      false /* individual_attestation_requested */);
+  if (!attestation_cert)
+    return CtapDeviceResponseCode::kCtap2ErrOther;
+
+  *response = ConstructMakeCredentialResponse(std::move(*attestation_cert), sig,
+                                              std::move(authenticator_data));
+
+  StoreNewKey(rp_id_hash, key_handle, std::move(private_key));
+  return CtapDeviceResponseCode::kSuccess;
+}
+
+CtapDeviceResponseCode VirtualCtap2Device::OnAuthenticatorGetInfo(
+    std::vector<uint8_t>* response) const {
+  *response = EncodeToCBOR(device_info_);
+  return CtapDeviceResponseCode::kSuccess;
+}
+
+AuthenticatorData VirtualCtap2Device::ConstructAuthenticatorData(
+    base::span<const uint8_t, kRpIdHashLength> rp_id_hash,
+    base::Optional<AttestedCredentialData> attested_credential_data) {
+  uint8_t flag =
+      base::strict_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence);
+  std::array<uint8_t, kSignCounterLength> signature_counter;
+
+  // Constructing AuthenticatorData for registration operation.
+  if (attested_credential_data) {
+    flag |= base::strict_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
+    signature_counter = {{0x00, 0x00, 0x00, 0x01}};
+    // Constructing AuthenticatorData for sign operation.
+  } else {
+    auto* registration_data = FindRegistrationData(
+        attested_credential_data->credential_id(), rp_id_hash);
+    signature_counter[0] = (registration_data->counter >> 24) & 0xff;
+    signature_counter[1] = (registration_data->counter >> 16) & 0xff;
+    signature_counter[2] = (registration_data->counter >> 8) & 0xff;
+    signature_counter[3] = (registration_data->counter) & 0xff;
+  }
+
+  return AuthenticatorData(rp_id_hash, flag, signature_counter,
+                           std::move(attested_credential_data));
+}
+
+}  // namespace device
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
new file mode 100644
index 0000000..7808b85
--- /dev/null
+++ b/device/fido/virtual_ctap2_device.h
@@ -0,0 +1,59 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
+#define DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "device/fido/attested_credential_data.h"
+#include "device/fido/authenticator_data.h"
+#include "device/fido/authenticator_supported_options.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/virtual_fido_device.h"
+
+namespace device {
+
+class COMPONENT_EXPORT(DEVICE_FIDO) VirtualCtap2Device
+    : public VirtualFidoDevice {
+ public:
+  VirtualCtap2Device();
+  explicit VirtualCtap2Device(scoped_refptr<State> state);
+  ~VirtualCtap2Device() override;
+
+  // FidoDevice:
+  void Cancel() override;
+  void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
+
+  void SetAuthenticatorSupportedOptions(AuthenticatorSupportedOptions options);
+
+ private:
+  CtapDeviceResponseCode OnMakeCredential(base::span<const uint8_t> request,
+                                          std::vector<uint8_t>* response);
+
+  CtapDeviceResponseCode OnAuthenticatorGetInfo(
+      std::vector<uint8_t>* response) const;
+
+  AuthenticatorData ConstructAuthenticatorData(
+      base::span<const uint8_t, kRpIdHashLength> rp_id_hash,
+      base::Optional<AttestedCredentialData> attested_credential_data);
+
+  AuthenticatorGetInfoResponse device_info_;
+  base::WeakPtrFactory<FidoDevice> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(VirtualCtap2Device);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
diff --git a/device/fido/virtual_fido_device.cc b/device/fido/virtual_fido_device.cc
index fc73cbd1..06c5dac 100644
--- a/device/fido/virtual_fido_device.cc
+++ b/device/fido/virtual_fido_device.cc
@@ -7,7 +7,6 @@
 #include <tuple>
 #include <utility>
 
-#include "crypto/ec_private_key.h"
 #include "crypto/ec_signature_creator.h"
 #include "device/fido/fido_parsing_utils.h"
 
@@ -122,6 +121,34 @@
   return std::vector<uint8_t>(attestation_cert.begin(), attestation_cert.end());
 }
 
+void VirtualFidoDevice::StoreNewKey(
+    base::span<const uint8_t, kRpIdHashLength> application_parameter,
+    base::span<const uint8_t> key_handle,
+    std::unique_ptr<crypto::ECPrivateKey> private_key) {
+  // Store the registration. Because the key handle is the hashed public key we
+  // just generated, no way this should already be registered.
+  bool did_insert = false;
+  std::tie(std::ignore, did_insert) = mutable_state()->registrations.emplace(
+      fido_parsing_utils::Materialize(key_handle),
+      RegistrationData(std::move(private_key), application_parameter, 1));
+  DCHECK(did_insert);
+}
+
+VirtualFidoDevice::RegistrationData* VirtualFidoDevice::FindRegistrationData(
+    base::span<const uint8_t> key_handle,
+    base::span<const uint8_t, kRpIdHashLength> application_parameter) {
+  // Check if this is our key_handle and it's for this appId.
+  auto it = mutable_state()->registrations.find(key_handle);
+  if (it == mutable_state()->registrations.end())
+    return nullptr;
+
+  if (application_parameter !=
+      base::make_span(it->second.application_parameter))
+    return nullptr;
+
+  return &(it->second);
+}
+
 void VirtualFidoDevice::TryWink(WinkCallback cb) {
   std::move(cb).Run();
 }
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index e4ae439..92ad511e 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
+#include "crypto/ec_private_key.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_device.h"
 #include "device/fido/fido_parsing_utils.h"
@@ -120,6 +121,15 @@
   base::Optional<std::vector<uint8_t>> GenerateAttestationCertificate(
       bool individual_attestation_requested) const;
 
+  void StoreNewKey(
+      base::span<const uint8_t, kRpIdHashLength> application_parameter,
+      base::span<const uint8_t> key_handle,
+      std::unique_ptr<crypto::ECPrivateKey> private_key);
+
+  RegistrationData* FindRegistrationData(
+      base::span<const uint8_t> key_handle,
+      base::span<const uint8_t, kRpIdHashLength> application_parameter);
+
   // FidoDevice:
   void TryWink(WinkCallback cb) override;
   std::string GetId() const override;
diff --git a/device/fido/virtual_u2f_device.cc b/device/fido/virtual_u2f_device.cc
index c39e67c..be3f07c0 100644
--- a/device/fido/virtual_u2f_device.cc
+++ b/device/fido/virtual_u2f_device.cc
@@ -176,14 +176,7 @@
   Append(&response, *attestation_cert);
   Append(&response, sig);
 
-  // Store the registration. Because the key handle is the hashed public key we
-  // just generated, no way this should already be registered.
-  bool did_insert = false;
-  std::tie(std::ignore, did_insert) = mutable_state()->registrations.emplace(
-      std::move(key_handle),
-      RegistrationData(std::move(private_key), application_parameter, 1));
-  DCHECK(did_insert);
-
+  StoreNewKey(application_parameter, key_handle, std::move(private_key));
   return apdu::ApduResponse(std::move(response),
                             apdu::ApduResponse::Status::SW_NO_ERROR)
       .GetEncodedResponse();
@@ -204,42 +197,29 @@
     mutable_state()->simulate_press_callback.Run();
   }
 
-  if (data.size() < 32 + 32 + 1) {
+  if (data.size() < 32 + 32 + 1)
     return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
-  }
 
   auto challenge_param = data.first<32>();
   auto application_parameter = data.subspan<32, 32>();
   size_t key_handle_length = data[64];
-  if (data.size() != 32 + 32 + 1 + key_handle_length) {
+  if (data.size() != 32 + 32 + 1 + key_handle_length)
     return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
-  }
+
   auto key_handle = data.last(key_handle_length);
-
-  // Check if this is our key_handle and it's for this appId.
-  auto it = mutable_state()->registrations.find(key_handle);
-  if (it == mutable_state()->registrations.end()) {
+  auto* registration = FindRegistrationData(key_handle, application_parameter);
+  if (!registration)
     return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
 
-  base::span<const uint8_t> registered_app_id_hash =
-      base::make_span(it->second.application_parameter);
-  if (application_parameter != registered_app_id_hash) {
-    // It's important this error looks identical to the previous one, as
-    // tokens should not reveal the existence of keyHandles to unrelated appIds.
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
-
-  auto& registration = it->second;
-  ++registration.counter;
+  ++registration->counter;
 
   // First create the part of the response that gets signed over.
   std::vector<uint8_t> response;
   response.push_back(0x01);  // Always pretend we got a touch.
-  response.push_back(registration.counter >> 24);
-  response.push_back(registration.counter >> 16);
-  response.push_back(registration.counter >> 8);
-  response.push_back(registration.counter);
+  response.push_back(registration->counter >> 24);
+  response.push_back(registration->counter >> 16);
+  response.push_back(registration->counter >> 8);
+  response.push_back(registration->counter);
 
   std::vector<uint8_t> sign_buffer;
   sign_buffer.reserve(application_parameter.size() + response.size() +
@@ -250,7 +230,7 @@
 
   // Sign with credential key.
   std::vector<uint8_t> sig;
-  bool status = Sign(registration.private_key.get(), sign_buffer, &sig);
+  bool status = Sign(registration->private_key.get(), sign_buffer, &sig);
   DCHECK(status);
 
   // Add signature for full response.
diff --git a/docs/clang_tool_refactoring.md b/docs/clang_tool_refactoring.md
index b23d8d85..107ff8e 100644
--- a/docs/clang_tool_refactoring.md
+++ b/docs/clang_tool_refactoring.md
@@ -123,9 +123,9 @@
 ninja -d keeprsp -C out/Debug  # For Windows
 
 # experimental alternative:
-$gen_targets = $(ninja -C out/gn -t targets all \
+$gen_targets = $(ninja -C out/Debug -t targets all \
                  | grep '^gen/[^: ]*\.[ch][pc]*:' \
-                 | cut -f 1 -d :`)
+                 | cut -f 1 -d :)
 ninja -C out/Debug $gen_targets
 ```
 
@@ -150,7 +150,7 @@
 
 ```shell
 tools/clang/scripts/run_tool.py --tool empty_string  \
-  --generated-compdb \
+  --generate-compdb \
   -p out/Debug net >/tmp/list-of-edits.debug
 ```
 
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc
index b496d90..5760745 100644
--- a/extensions/common/permissions/permissions_data.cc
+++ b/extensions/common/permissions/permissions_data.cc
@@ -309,14 +309,6 @@
                                                             manifest_type_));
 }
 
-bool PermissionsData::HasWithheldImpliedAllHosts() const {
-  base::AutoLock auto_lock(runtime_lock_);
-  // Since we currently only withhold all_hosts, it's sufficient to check
-  // that either set is not empty.
-  return !withheld_permissions_unsafe_->explicit_hosts().is_empty() ||
-         !withheld_permissions_unsafe_->scriptable_hosts().is_empty();
-}
-
 bool PermissionsData::CanAccessPage(const GURL& document_url,
                                     int tab_id,
                                     std::string* error) const {
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h
index 265d2e8..68cba77 100644
--- a/extensions/common/permissions/permissions_data.h
+++ b/extensions/common/permissions/permissions_data.h
@@ -176,10 +176,6 @@
   PermissionMessages GetNewPermissionMessages(
       const PermissionSet& granted_permissions) const;
 
-  // Returns true if the extension has requested all-hosts permissions (or
-  // something close to it), but has had it withheld.
-  bool HasWithheldImpliedAllHosts() const;
-
   // Returns true if the associated extension has permission to access and
   // interact with the specified page, in order to do things like inject
   // scripts or modify the content.
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 8221c4c..10b3292 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -663,7 +663,7 @@
       'GL_PIXEL_PACK_BUFFER',
     ],
   },
-  'FramebufferParameter': {
+  'FramebufferAttachmentParameter': {
     'type': 'GLenum',
     'valid': [
       'GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE',
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 018ebeb..b90e63c 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -964,12 +964,12 @@
                                                               GLint* params) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params);
-  GPU_CLIENT_LOG("[" << GetLogPrefix()
-                     << "] glGetFramebufferAttachmentParameteriv("
-                     << GLES2Util::GetStringFramebufferTarget(target) << ", "
-                     << GLES2Util::GetStringAttachmentQuery(attachment) << ", "
-                     << GLES2Util::GetStringFramebufferParameter(pname) << ", "
-                     << static_cast<const void*>(params) << ")");
+  GPU_CLIENT_LOG(
+      "[" << GetLogPrefix() << "] glGetFramebufferAttachmentParameteriv("
+          << GLES2Util::GetStringFramebufferTarget(target) << ", "
+          << GLES2Util::GetStringAttachmentQuery(attachment) << ", "
+          << GLES2Util::GetStringFramebufferAttachmentParameter(pname) << ", "
+          << static_cast<const void*>(params) << ")");
   TRACE_EVENT0("gpu",
                "GLES2Implementation::GetFramebufferAttachmentParameteriv");
   if (GetFramebufferAttachmentParameterivHelper(target, attachment, pname,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc
index b9da433..f1d8764 100644
--- a/gpu/command_buffer/client/raster_implementation_gles.cc
+++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -257,6 +257,7 @@
                          viz::TextureStorageFormat(texture->format), width,
                          height);
   } else {
+    DCHECK(GLSupportsFormat(texture->format));
     gl_->TexImage2D(texture->target, 0, viz::GLInternalFormat(texture->format),
                     width, height, 0, viz::GLDataFormat(texture->format),
                     viz::GLDataType(texture->format), nullptr);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index c6bc86a..72bdd8c 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -34,7 +34,7 @@
 static std::string GetStringEquation(uint32_t value);
 static std::string GetStringFaceMode(uint32_t value);
 static std::string GetStringFaceType(uint32_t value);
-static std::string GetStringFramebufferParameter(uint32_t value);
+static std::string GetStringFramebufferAttachmentParameter(uint32_t value);
 static std::string GetStringFramebufferTarget(uint32_t value);
 static std::string GetStringGLState(uint32_t value);
 static std::string GetStringGetMaxIndexType(uint32_t value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index ec2707bc..4d63d1b4 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4532,7 +4532,7 @@
                                            arraysize(string_table), value);
 }
 
-std::string GLES2Util::GetStringFramebufferParameter(uint32_t value) {
+std::string GLES2Util::GetStringFramebufferAttachmentParameter(uint32_t value) {
   static const EnumToString string_table[] = {
       {GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
        "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"},
diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
index fcc1484..3ae9356 100644
--- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt
+++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
@@ -92,7 +92,7 @@
 GL_APICALL GLenum       GL_APIENTRY glGetError (void);
 GL_APICALL void         GL_APIENTRY glGetFloatv (GLenumGLState pname, GLfloat* params);
 GL_APICALL GLint        GL_APIENTRY glGetFragDataLocation (GLidProgram program, const char* name);
-GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenumFramebufferTarget target, GLenumAttachmentQuery attachment, GLenumFramebufferParameter pname, GLint* params);
+GL_APICALL void         GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenumFramebufferTarget target, GLenumAttachmentQuery attachment, GLenumFramebufferAttachmentParameter pname, GLint* params);
 GL_APICALL void         GL_APIENTRY glGetInteger64v (GLenumGLState pname, GLint64* params);
 GL_APICALL void         GL_APIENTRY glGetIntegeri_v (GLenumIndexedGLState pname, GLuint index, GLint* data);
 GL_APICALL void         GL_APIENTRY glGetInteger64i_v (GLenumIndexedGLState pname, GLuint index, GLint64* data);
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 7bc4600..a8ed234 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -698,7 +698,7 @@
     validators_.texture_format.AddValue(GL_SRGB_EXT);
     validators_.texture_format.AddValue(GL_SRGB_ALPHA_EXT);
     validators_.render_buffer_format.AddValue(GL_SRGB8_ALPHA8_EXT);
-    validators_.framebuffer_parameter.AddValue(
+    validators_.framebuffer_attachment_parameter.AddValue(
         GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT);
     validators_.texture_unsized_internal_format.AddValue(GL_SRGB_EXT);
     validators_.texture_unsized_internal_format.AddValue(GL_SRGB_ALPHA_EXT);
@@ -934,7 +934,7 @@
   if (feature_flags_.multisampled_render_to_texture) {
     validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT);
     validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT);
-    validators_.framebuffer_parameter.AddValue(
+    validators_.framebuffer_attachment_parameter.AddValue(
         GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT);
     AddExtensionString("GL_EXT_multisampled_render_to_texture");
   }
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index 17882dd8..83259d2 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -267,7 +267,7 @@
         GL_SRGB_ALPHA_EXT));
     EXPECT_TRUE(info_->validators()->render_buffer_format.IsValid(
         GL_SRGB8_ALPHA8_EXT));
-    EXPECT_TRUE(info_->validators()->framebuffer_parameter.IsValid(
+    EXPECT_TRUE(info_->validators()->framebuffer_attachment_parameter.IsValid(
         GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT));
   } else {
     EXPECT_FALSE(gfx::HasExtension(info_->extensions(), "GL_EXT_sRGB"));
@@ -280,7 +280,7 @@
         GL_SRGB_ALPHA_EXT));
     EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid(
         GL_SRGB8_ALPHA8_EXT));
-    EXPECT_FALSE(info_->validators()->framebuffer_parameter.IsValid(
+    EXPECT_FALSE(info_->validators()->framebuffer_attachment_parameter.IsValid(
         GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT));
   }
 
@@ -633,7 +633,7 @@
         GL_SRGB_ALPHA_EXT));
     EXPECT_FALSE(
         info_->validators()->render_buffer_format.IsValid(GL_SRGB8_ALPHA8_EXT));
-    EXPECT_FALSE(info_->validators()->framebuffer_parameter.IsValid(
+    EXPECT_FALSE(info_->validators()->framebuffer_attachment_parameter.IsValid(
         GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT));
   } else {
     EXPECT_TRUE(gfx::HasExtension(info_->extensions(), "GL_EXT_sRGB"));
@@ -645,7 +645,7 @@
         GL_SRGB_ALPHA_EXT));
     EXPECT_TRUE(
         info_->validators()->render_buffer_format.IsValid(GL_SRGB8_ALPHA8_EXT));
-    EXPECT_TRUE(info_->validators()->framebuffer_parameter.IsValid(
+    EXPECT_TRUE(info_->validators()->framebuffer_attachment_parameter.IsValid(
         GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT));
   }
 }
@@ -977,7 +977,7 @@
       GL_SRGB_ALPHA_EXT));
   EXPECT_FALSE(info_->validators()->render_buffer_format.IsValid(
       GL_SRGB8_ALPHA8_EXT));
-  EXPECT_FALSE(info_->validators()->framebuffer_parameter.IsValid(
+  EXPECT_FALSE(info_->validators()->framebuffer_attachment_parameter.IsValid(
       GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT));
 }
 
@@ -1126,7 +1126,7 @@
       GL_MAX_SAMPLES_EXT));
   EXPECT_TRUE(info_->validators()->render_buffer_parameter.IsValid(
       GL_RENDERBUFFER_SAMPLES_EXT));
-  EXPECT_TRUE(info_->validators()->framebuffer_parameter.IsValid(
+  EXPECT_TRUE(info_->validators()->framebuffer_attachment_parameter.IsValid(
       GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT));
 }
 
@@ -1142,7 +1142,7 @@
       GL_MAX_SAMPLES_EXT));
   EXPECT_TRUE(info_->validators()->render_buffer_parameter.IsValid(
       GL_RENDERBUFFER_SAMPLES_EXT));
-  EXPECT_TRUE(info_->validators()->framebuffer_parameter.IsValid(
+  EXPECT_TRUE(info_->validators()->framebuffer_attachment_parameter.IsValid(
       GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT));
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 3703197..1fc24c5 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -1462,7 +1462,7 @@
                                     attachment, "attachment");
     return error::kNoError;
   }
-  if (!validators_->framebuffer_parameter.IsValid(pname)) {
+  if (!validators_->framebuffer_attachment_parameter.IsValid(pname)) {
     LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetFramebufferAttachmentParameteriv",
                                     pname, "pname");
     return error::kNoError;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index c820cb53c4..96767ea8 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -113,7 +113,7 @@
 };
 FaceTypeValidator face_type;
 
-ValueValidator<GLenum> framebuffer_parameter;
+ValueValidator<GLenum> framebuffer_attachment_parameter;
 ValueValidator<GLenum> framebuffer_target;
 ValueValidator<GLenum> g_l_state;
 class GetMaxIndexTypeValidator {
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index 555bef78..97f89cb 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -225,14 +225,14 @@
   return false;
 }
 
-static const GLenum valid_framebuffer_parameter_table[] = {
+static const GLenum valid_framebuffer_attachment_parameter_table[] = {
     GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
     GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
     GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
     GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
 };
 
-static const GLenum valid_framebuffer_parameter_table_es3[] = {
+static const GLenum valid_framebuffer_attachment_parameter_table_es3[] = {
     GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
     GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
     GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
@@ -1395,8 +1395,9 @@
       dst_blend_factor(valid_dst_blend_factor_table,
                        arraysize(valid_dst_blend_factor_table)),
       equation(valid_equation_table, arraysize(valid_equation_table)),
-      framebuffer_parameter(valid_framebuffer_parameter_table,
-                            arraysize(valid_framebuffer_parameter_table)),
+      framebuffer_attachment_parameter(
+          valid_framebuffer_attachment_parameter_table,
+          arraysize(valid_framebuffer_attachment_parameter_table)),
       framebuffer_target(valid_framebuffer_target_table,
                          arraysize(valid_framebuffer_target_table)),
       g_l_state(valid_g_l_state_table, arraysize(valid_g_l_state_table)),
@@ -1478,9 +1479,9 @@
                              arraysize(valid_dst_blend_factor_table_es3));
   equation.AddValues(valid_equation_table_es3,
                      arraysize(valid_equation_table_es3));
-  framebuffer_parameter.AddValues(
-      valid_framebuffer_parameter_table_es3,
-      arraysize(valid_framebuffer_parameter_table_es3));
+  framebuffer_attachment_parameter.AddValues(
+      valid_framebuffer_attachment_parameter_table_es3,
+      arraysize(valid_framebuffer_attachment_parameter_table_es3));
   framebuffer_target.AddValues(valid_framebuffer_target_table_es3,
                                arraysize(valid_framebuffer_target_table_es3));
   g_l_state.AddValues(valid_g_l_state_table_es3,
diff --git a/gpu/command_buffer/service/raster_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/raster_cmd_validation_implementation_autogen.h
index 23601cb..e32ec2e 100644
--- a/gpu/command_buffer/service/raster_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/raster_cmd_validation_implementation_autogen.h
@@ -68,11 +68,17 @@
 };
 
 static const viz::ResourceFormat valid_viz_resource_format_table[] = {
-    viz::ResourceFormat::RGBA_8888,   viz::ResourceFormat::RGBA_4444,
-    viz::ResourceFormat::BGRA_8888,   viz::ResourceFormat::ALPHA_8,
-    viz::ResourceFormat::LUMINANCE_8, viz::ResourceFormat::RGB_565,
-    viz::ResourceFormat::RED_8,       viz::ResourceFormat::LUMINANCE_F16,
-    viz::ResourceFormat::RGBA_F16,    viz::ResourceFormat::R16_EXT,
+    viz::ResourceFormat::RGBA_8888,    viz::ResourceFormat::RGBA_4444,
+    viz::ResourceFormat::BGRA_8888,    viz::ResourceFormat::ALPHA_8,
+    viz::ResourceFormat::LUMINANCE_8,  viz::ResourceFormat::RGB_565,
+    viz::ResourceFormat::RGB_565,      viz::ResourceFormat::RED_8,
+    viz::ResourceFormat::RG_88,        viz::ResourceFormat::LUMINANCE_F16,
+    viz::ResourceFormat::RGBA_F16,     viz::ResourceFormat::R16_EXT,
+    viz::ResourceFormat::RGBX_8888,    viz::ResourceFormat::BGRX_8888,
+    viz::ResourceFormat::RGBX_1010102, viz::ResourceFormat::BGRX_1010102,
+    viz::ResourceFormat::YVU_420,      viz::ResourceFormat::YUV_420_BIPLANAR,
+    viz::ResourceFormat::UYVY_422
+
 };
 
 Validators::Validators()
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 000bc461..a97a98aa 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -2070,6 +2070,7 @@
                                       bool use_buffer,
                                       gfx::BufferUsage buffer_usage,
                                       viz::ResourceFormat resource_format) {
+  DCHECK(GLSupportsFormat(resource_format));
   texture_metadata_.emplace(std::make_pair(
       client_id, TextureMetadata(use_buffer, buffer_usage, resource_format,
                                  GetCapabilities())));
@@ -2387,6 +2388,7 @@
                          "Invalid buffer format");
       return false;
   }
+  DCHECK(GLSupportsFormat(texture_metadata.format()));
   GLint untyped_format = viz::GLDataFormat(texture_metadata.format());
 
   if (!GetContextGroup()->image_factory()) {
@@ -2549,6 +2551,7 @@
     return;
   }
 
+  DCHECK(GLSupportsFormat(texture_metadata->format()));
   // Check if we have enough memory.
   unsigned int internal_format =
       viz::GLInternalFormat(texture_metadata->format());
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h
index 6563388e..9b047ae 100644
--- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h
+++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.h
@@ -20,8 +20,7 @@
 class ChromeBrowserState;
 }  // namespace ios
 
-using TimerGeneratorBlock =
-    std::unique_ptr<base::Timer> (^)(bool retain_user_task, bool is_repeating);
+using TimerGeneratorBlock = std::unique_ptr<base::OneShotTimer> (^)();
 
 @protocol ChromeSigninViewControllerDelegate<NSObject>
 
@@ -119,7 +118,8 @@
 // Exposes methods for testing.
 @interface ChromeSigninViewController (Testing)
 
-// Timer generator. Should stay nil to use the default timer class: base::Timer.
+// Timer generator. Should stay nil to use the default timer class:
+// base::OneShotTimer.
 @property(nonatomic, copy) TimerGeneratorBlock timerGenerator;
 
 @end
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
index 483c661b..4e73e93b 100644
--- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
@@ -734,15 +734,11 @@
       [strongSelf->_activityIndicator stopAnimating];
       strongSelf->_leavingPendingStateTimer.reset();
     };
-    const bool retain_user_task = false;
-    const bool is_repeating = false;
     if (self.timerGenerator) {
-      _leavingPendingStateTimer =
-          self.timerGenerator(retain_user_task, is_repeating);
+      _leavingPendingStateTimer = self.timerGenerator();
       DCHECK(_leavingPendingStateTimer);
     } else {
-      _leavingPendingStateTimer =
-          std::make_unique<base::Timer>(retain_user_task, is_repeating);
+      _leavingPendingStateTimer = std::make_unique<base::OneShotTimer>();
     }
     _leavingPendingStateTimer->Start(FROM_HERE, remainingTime,
                                      base::BindRepeating(completionBlock));
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
index c4db4f3..a9a0149 100644
--- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
@@ -180,12 +180,10 @@
                   dispatcher:nil];
     vc_delegate_ = [[FakeChromeSigninViewControllerDelegate alloc] init];
     vc_.delegate = vc_delegate_;
-    __block base::MockTimer* mock_timer_ptr = nullptr;
+    __block base::MockOneShotTimer* mock_timer_ptr = nullptr;
     if (!unified_consent_enabled_) {
-      vc_.timerGenerator = ^std::unique_ptr<base::Timer>(bool retain_user_task,
-                                                         bool is_repeating) {
-        auto mock_timer =
-            std::make_unique<base::MockTimer>(retain_user_task, is_repeating);
+      vc_.timerGenerator = ^std::unique_ptr<base::OneShotTimer>() {
+        auto mock_timer = std::make_unique<base::MockOneShotTimer>();
         mock_timer_ptr = mock_timer.get();
         return mock_timer;
       };
@@ -406,7 +404,7 @@
   FakeConsentAuditor* fake_consent_auditor_;
   AccountTrackerService* account_tracker_service_;
   base::test::ScopedFeatureList scoped_feature_list_;
-  base::MockTimer* mock_timer_ptr_ = nullptr;
+  base::MockOneShotTimer* mock_timer_ptr_ = nullptr;
   FakeChromeSigninViewControllerDelegate* vc_delegate_;
 };
 
diff --git a/ios/chrome/browser/ui/history/history_entry_inserter.mm b/ios/chrome/browser/ui/history/history_entry_inserter.mm
index b0de08c..8ef149ef 100644
--- a/ios/chrome/browser/ui/history/history_entry_inserter.mm
+++ b/ios/chrome/browser/ui/history/history_entry_inserter.mm
@@ -80,15 +80,22 @@
                               inSortedRange:range
                                     options:NSBinarySearchingInsertionIndex
                             usingComparator:objectComparator];
+
+    // Calculate the new tableView indexPath row before inserting into the
+    // model. No matter where in the model the item is inserted, a new row will
+    // be created for the tableView. For this reason, make sure to insert a new
+    // index into the tableView after the item has been inserted into the model.
+    NSInteger section =
+        [_listModel sectionForSectionIdentifier:sectionIdentifier];
+    NSInteger tableViewRow = [_listModel numberOfItemsInSection:section];
+    NSIndexPath* tableIndexPath =
+        [NSIndexPath indexPathForRow:tableViewRow inSection:section];
+
     [_listModel insertItem:item
         inSectionWithIdentifier:sectionIdentifier
                         atIndex:index];
-    NSIndexPath* indexPath = [NSIndexPath
-        indexPathForItem:index
-               inSection:[_listModel
-                             sectionForSectionIdentifier:sectionIdentifier]];
     [self.delegate historyEntryInserter:self
-               didInsertItemAtIndexPath:indexPath];
+               didInsertItemAtIndexPath:tableIndexPath];
   }
 }
 
@@ -120,6 +127,8 @@
                            usingComparator:comparator];
   [_dates insertObject:date atIndex:index];
   NSInteger insertionIndex = _firstSectionIndex + index;
+  [_listModel insertSectionWithIdentifier:sectionIdentifier
+                                  atIndex:insertionIndex];
   if (IsUIRefreshPhase1Enabled()) {
     TableViewTextHeaderFooterItem* header =
         [[TableViewTextHeaderFooterItem alloc] initWithType:kItemTypeEnumZero];
@@ -134,8 +143,6 @@
         base::SysUTF16ToNSString(history::GetRelativeDateLocalized(timestamp));
     [_listModel setHeader:header forSectionWithIdentifier:sectionIdentifier];
   }
-  [_listModel insertSectionWithIdentifier:sectionIdentifier
-                                  atIndex:insertionIndex];
   [self.delegate historyEntryInserter:self
               didInsertSectionAtIndex:insertionIndex];
   return sectionIdentifier;
diff --git a/ios/chrome/browser/ui/history/history_entry_inserter_unittest.mm b/ios/chrome/browser/ui/history/history_entry_inserter_unittest.mm
index b4cf5be..4f2db2c 100644
--- a/ios/chrome/browser/ui/history/history_entry_inserter_unittest.mm
+++ b/ios/chrome/browser/ui/history/history_entry_inserter_unittest.mm
@@ -75,7 +75,7 @@
 
   [[mock_delegate expect]
           historyEntryInserter:inserter_
-      didInsertItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
+      didInsertItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]];
   [inserter_ insertHistoryEntryItem:entry1];
   EXPECT_OCMOCK_VERIFY(mock_delegate);
 
@@ -176,7 +176,7 @@
 
   [[mock_delegate expect]
           historyEntryInserter:inserter_
-      didInsertItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:2]];
+      didInsertItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:2]];
   [inserter_ insertHistoryEntryItem:day2_entry1];
   EXPECT_EQ(4, [model_ numberOfSections]);
   EXPECT_EQ(0, [model_ numberOfItemsInSection:0]);
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index a8ea5c8..d3acbee2 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -11,8 +11,12 @@
     "reading_list_coordinator.h",
     "reading_list_coordinator.mm",
     "reading_list_list_item.h",
-    "reading_list_list_view_item_util.h",
-    "reading_list_list_view_item_util.mm",
+    "reading_list_list_item_custom_action_factory.h",
+    "reading_list_list_item_custom_action_factory.mm",
+    "reading_list_list_item_factory.h",
+    "reading_list_list_item_factory.mm",
+    "reading_list_list_item_util.h",
+    "reading_list_list_item_util.mm",
     "reading_list_mediator.h",
     "reading_list_mediator.mm",
     "reading_list_menu_notification_delegate.h",
@@ -67,6 +71,8 @@
 source_set("reading_list_ui") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "empty_reading_list_background_view.h",
+    "empty_reading_list_background_view.mm",
     "number_badge_view.h",
     "number_badge_view.mm",
     "reading_list_collection_view_cell.h",
@@ -75,11 +81,12 @@
     "reading_list_collection_view_controller.mm",
     "reading_list_data_sink.h",
     "reading_list_data_source.h",
-    "reading_list_empty_collection_background.h",
-    "reading_list_empty_collection_background.mm",
-    "reading_list_list_view_item_accessibility_delegate.h",
-    "reading_list_list_view_item_custom_action_factory.h",
-    "reading_list_list_view_item_custom_action_factory.mm",
+    "reading_list_list_item_accessibility_delegate.h",
+    "reading_list_list_item_updater.h",
+    "reading_list_list_view_controller_audience.h",
+    "reading_list_list_view_controller_delegate.h",
+    "reading_list_table_view_controller.h",
+    "reading_list_table_view_controller.mm",
     "reading_list_toolbar.h",
     "reading_list_toolbar.mm",
     "reading_list_toolbar_button.h",
@@ -112,6 +119,7 @@
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/list_model",
+    "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/table_view/cells/resources:table_view_cell_check_mark",
     "//ios/chrome/browser/ui/util",
@@ -136,6 +144,7 @@
     "offline_page_native_content_unittest.mm",
     "reading_list_collection_view_controller_unittest.mm",
     "reading_list_coordinator_unittest.mm",
+    "reading_list_list_item_factory_unittest.mm",
     "reading_list_mediator_unittest.mm",
     "text_badge_view_unittest.mm",
   ]
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h
new file mode 100644
index 0000000..869735f6
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h
@@ -0,0 +1,22 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_
+
+#import <UIKit/UIKit.h>
+
+// The view to use as the background view for an empty reading list list view.
+@interface EmptyReadingListBackgroundView : UIView
+
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
+- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
+
++ (NSString*)accessibilityIdentifier;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_BACKGROUND_VIEW_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm
similarity index 95%
rename from ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
rename to ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm
index 6c6adde..ea5354a7 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.mm
+++ b/ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
+#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h"
 
 #include "base/logging.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
@@ -41,7 +41,7 @@
 
 }  // namespace
 
-@interface ReadingListEmptyCollectionBackground ()
+@interface EmptyReadingListBackgroundView ()
 
 // Attaches the icon named |iconName| to |instructionString| and a |caret|. The
 // icon is positionned using the |iconOffset| and with the |attributes| (mainly
@@ -62,7 +62,7 @@
 
 @end
 
-@implementation ReadingListEmptyCollectionBackground
+@implementation EmptyReadingListBackgroundView
 
 #pragma mark - Public
 
@@ -175,7 +175,7 @@
     label.textAlignment = NSTextAlignmentCenter;
     label.accessibilityLabel = accessibilityLabel;
     label.accessibilityIdentifier =
-        [ReadingListEmptyCollectionBackground accessibilityIdentifier];
+        [EmptyReadingListBackgroundView accessibilityIdentifier];
     [label setTranslatesAutoresizingMaskIntoConstraints:NO];
     [self addSubview:label];
 
@@ -214,9 +214,9 @@
       appendAttributedString:[NSAttributedString
                                  attributedStringWithAttachment:toolbarIcon]];
 
-    [instructionString appendAttributedString:[[NSAttributedString alloc]
-                                                  initWithString:@" "
-                                                      attributes:attributes]];
+  [instructionString appendAttributedString:[[NSAttributedString alloc]
+                                                initWithString:@" "
+                                                    attributes:attributes]];
 
   [instructionString appendAttributedString:caret];
 }
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h
index 25de322..314662c67 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h
@@ -7,60 +7,16 @@
 
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
 
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 
-@class ReadingListCollectionViewController;
 @protocol ReadingListDataSource;
-
-// Audience for the ReadingListCollectionViewController
-@protocol ReadingListCollectionViewControllerAudience
-
-// Whether the collection has items.
-- (void)readingListHasItems:(BOOL)hasItems;
-
-@end
-
-// Delegate for the ReadingListCollectionViewController, managing the visibility
-// of the toolbar, dismissing the Reading List View and opening elements.
-@protocol ReadingListCollectionViewControllerDelegate<NSObject>
-
-// Dismisses the Reading List View.
-- (void)dismissReadingListCollectionViewController:
-    (ReadingListCollectionViewController*)readingListCollectionViewController;
-
-// Displays the context menu for the |readingListItem|. The |menuLocation| is
-// the anchor of the context menu in the
-// readingListCollectionViewController.collectionView coordinates.
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                  displayContextMenuForItem:(CollectionViewItem*)readingListItem
-                                    atPoint:(CGPoint)menuLocation;
-
-// Opens the entry corresponding to the |readingListItem|.
-- (void)
-readingListCollectionViewController:
-    (ReadingListCollectionViewController*)readingListCollectionViewController
-                           openItem:(CollectionViewItem*)readingListItem;
-
-// Opens the entry corresponding to the |item| in a new tab, |incognito| or not.
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                           openItemInNewTab:(CollectionViewItem*)item
-                                  incognito:(BOOL)incognito;
-
-// Opens the offline version of the entry corresponding to the |item| in a new
-// tab, if available.
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                    openItemOfflineInNewTab:(CollectionViewItem*)item;
-
-@end
+@protocol ReadingListListViewControllerAudience;
+@protocol ReadingListListViewControllerDelegate;
 
 @interface ReadingListCollectionViewController
-    : CollectionViewController<ReadingListToolbarActions>
+    : CollectionViewController<ReadingListListItemAccessibilityDelegate,
+                               ReadingListToolbarActions>
 
 - (instancetype)initWithDataSource:(id<ReadingListDataSource>)dataSource
                            toolbar:(ReadingListToolbar*)toolbar
@@ -69,10 +25,8 @@
                          style:(CollectionViewControllerStyle)style
     NS_UNAVAILABLE;
 
-@property(nonatomic, weak) id<ReadingListCollectionViewControllerDelegate>
-    delegate;
-@property(nonatomic, weak) id<ReadingListCollectionViewControllerAudience>
-    audience;
+@property(nonatomic, weak) id<ReadingListListViewControllerDelegate> delegate;
+@property(nonatomic, weak) id<ReadingListListViewControllerAudience> audience;
 @property(nonatomic, weak) id<ReadingListDataSource> dataSource;
 
 // Prepares this view controller to be dismissed.
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
index e70ae61..a710730 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
@@ -14,11 +14,12 @@
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/list_model/list_item+Controller.h"
+#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_data_source.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/third_party/material_components_ios/src/components/AppBar/src/MaterialAppBar.h"
@@ -30,24 +31,19 @@
 #endif
 
 namespace {
-
-typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  SectionIdentifierUnread = kSectionIdentifierEnumZero,
-  SectionIdentifierRead,
-};
-
+// Types of ListItems used by the reading list UI.
 typedef NS_ENUM(NSInteger, ItemType) {
   ItemTypeHeader = kItemTypeEnumZero,
   ItemTypeItem,
 };
-
-// Typedef for a block taking a CollectionViewItem as parameter and returning
-// nothing.
-typedef void (^EntryUpdater)(CollectionViewItem* item);
-}
+// Identifiers for sections in the reading list.
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierUnread = kSectionIdentifierEnumZero,
+  SectionIdentifierRead,
+};
+}  // namespace
 
 @interface ReadingListCollectionViewController ()<
-    ReadingListListViewItemAccessibilityDelegate,
     ReadingListDataSink,
     UIGestureRecognizerDelegate> {
   // Toolbar with the actions.
@@ -60,20 +56,23 @@
   BOOL _dataSourceHasBeenModified;
 }
 
+// Redefine the model to return ReadingListListItems
+@property(nonatomic, readonly)
+    CollectionViewModel<CollectionViewItem<ReadingListListItem>*>*
+        collectionViewModel;
+
 // Whether the data source modifications should be taken into account.
 @property(nonatomic, assign) BOOL shouldMonitorDataSource;
 
-// The factory that provides custom accessibility actions to the cells, using
-// self as the accessibility delegate.
-@property(nonatomic, strong)
-    ReadingListListViewItemCustomActionFactory* customActionFactory;
-
+// Casts |item| to a CollectionViewItem.
+- (CollectionViewItem<ReadingListListItem>*)collectionItemForReadingListItem:
+    (id<ReadingListListItem>)item;
 // Handles "Done" button touches.
 - (void)donePressed;
 // Loads all the items in all sections.
 - (void)loadItems;
 // Fills section |sectionIdentifier| with the items from |array|.
-- (void)loadItemsFromArray:(NSArray<CollectionViewItem*>*)array
+- (void)loadItemsFromArray:(NSArray<id<ReadingListListItem>>*)array
                  toSection:(SectionIdentifier)sectionIdentifier;
 // Reloads the data if a change occurred during editing
 - (void)applyPendingUpdates;
@@ -114,12 +113,12 @@
 // order. The monitoring of the data source updates are suspended during this
 // time.
 - (void)updateItemsInSectionIdentifier:(SectionIdentifier)identifier
-                     usingEntryUpdater:(EntryUpdater)updater;
+                      usingItemUpdater:(ReadingListListItemUpdater)updater;
 // Applies |updater| to the URL of every element in |indexPaths|. The updates
 // are done in reverse order |indexPaths| to keep the order. The monitoring of
 // the data source updates are suspended during this time.
 - (void)updateIndexPaths:(NSArray<NSIndexPath*>*)indexPaths
-       usingEntryUpdater:(EntryUpdater)updater;
+        usingItemUpdater:(ReadingListListItemUpdater)updater;
 // Move all the items from |sourceSectionIdentifier| to
 // |destinationSectionIdentifier| and removes the empty section from the
 // collection.
@@ -147,8 +146,8 @@
 @synthesize delegate = _delegate;
 @synthesize dataSource = _dataSource;
 
+@dynamic collectionViewModel;
 @synthesize shouldMonitorDataSource = _shouldMonitorDataSource;
-@synthesize customActionFactory = _customActionFactory;
 
 + (NSString*)accessibilityIdentifier {
   return @"ReadingListCollectionView";
@@ -165,16 +164,11 @@
     _toolbar = toolbar;
 
     _dataSource = dataSource;
-    _emptyCollectionBackground =
-        [[ReadingListEmptyCollectionBackground alloc] init];
+    _emptyCollectionBackground = [[EmptyReadingListBackgroundView alloc] init];
 
     _shouldMonitorDataSource = YES;
     _dataSourceHasBeenModified = NO;
 
-    _customActionFactory =
-        [[ReadingListListViewItemCustomActionFactory alloc] init];
-    _customActionFactory.accessibilityDelegate = self;
-
     _dataSource.dataSink = self;
   }
   return self;
@@ -186,7 +180,7 @@
   [_toolbar setState:toolbarState];
 }
 
-- (void)setAudience:(id<ReadingListCollectionViewControllerAudience>)audience {
+- (void)setAudience:(id<ReadingListListViewControllerAudience>)audience {
   _audience = audience;
   if (self.dataSource.ready) {
     [audience readingListHasItems:self.dataSource.hasElements];
@@ -236,10 +230,9 @@
   if (self.editor.editing) {
     [self updateToolbarState];
   } else {
-    [self.delegate
-        readingListCollectionViewController:self
-                                   openItem:[self.collectionViewModel
-                                                itemAtIndexPath:indexPath]];
+    id<ReadingListListItem> item =
+        [self.collectionViewModel itemAtIndexPath:indexPath];
+    [self.delegate readingListListViewController:self openItem:item];
   }
 }
 
@@ -297,34 +290,42 @@
   }
 }
 
-- (NSArray<CollectionViewItem*>*)readItems {
-  if (![self.collectionViewModel
-          hasSectionForSectionIdentifier:SectionIdentifierRead]) {
-    return nil;
-  }
-  return [self.collectionViewModel
-      itemsInSectionWithIdentifier:SectionIdentifierRead];
+- (NSArray<id<ReadingListListItem>>*)readItems {
+  return [self readingListItemsForSection:SectionIdentifierRead];
 }
 
-- (NSArray<CollectionViewItem*>*)unreadItems {
-  if (![self.collectionViewModel
-          hasSectionForSectionIdentifier:SectionIdentifierUnread]) {
-    return nil;
-  }
-  return [self.collectionViewModel
-      itemsInSectionWithIdentifier:SectionIdentifierUnread];
+- (NSArray<id<ReadingListListItem>>*)unreadItems {
+  return [self readingListItemsForSection:SectionIdentifierUnread];
 }
 
-- (void)itemHasChangedAfterDelay:(CollectionViewItem*)item {
-  if ([self.collectionViewModel hasItem:item]) {
-    [self reconfigureCellsForItems:@[ item ]];
+- (void)itemHasChangedAfterDelay:(id<ReadingListListItem>)item {
+  CollectionViewItem<ReadingListListItem>* collectionItem =
+      [self collectionItemForReadingListItem:item];
+  if ([self.collectionViewModel hasItem:collectionItem]) {
+    [self reconfigureCellsForItems:@[ collectionItem ]];
   }
 }
 
-- (void)itemsHaveChanged:(NSArray<CollectionViewItem*>*)items {
+- (void)itemsHaveChanged:(NSArray<id<ReadingListListItem>>*)items {
   [self reconfigureCellsForItems:items];
 }
 
+#pragma mark - ReadingListDataSink Helpers
+
+- (NSArray<id<ReadingListListItem>>*)readingListItemsForSection:
+    (SectionIdentifier)sectionID {
+  if (![self.collectionViewModel hasSectionForSectionIdentifier:sectionID]) {
+    return nil;
+  }
+  NSMutableArray<id<ReadingListListItem>>* items = [NSMutableArray array];
+  NSArray<CollectionViewItem*>* sectionItems =
+      [self.collectionViewModel itemsInSectionWithIdentifier:sectionID];
+  for (id<ReadingListListItem> item in sectionItems) {
+    [items addObject:item];
+  }
+  return items;
+}
+
 #pragma mark - Public methods
 
 - (void)reloadData {
@@ -339,63 +340,55 @@
   [_actionSheet stop];
 }
 
-#pragma mark - ReadingListListViewItemAccessibilityDelegate
+#pragma mark - ReadingListListItemAccessibilityDelegate
 
-- (BOOL)isEntryRead:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  return [self.dataSource isEntryRead:item];
+- (BOOL)isItemRead:(id<ReadingListListItem>)item {
+  return [self.dataSource isItemRead:item];
 }
 
-- (void)deleteEntry:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  if ([self.collectionViewModel hasItem:item]) {
+- (void)deleteItem:(id<ReadingListListItem>)item {
+  CollectionViewItem<ReadingListListItem>* collectionItem =
+      [self collectionItemForReadingListItem:item];
+  if ([self.collectionViewModel hasItem:collectionItem]) {
     [self deleteItemsAtIndexPaths:@[ [self.collectionViewModel
-                                      indexPathForItem:item] ]];
+                                      indexPathForItem:collectionItem] ]];
   }
 }
 
-- (void)openEntryInNewTab:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  [self.delegate readingListCollectionViewController:self
-                                    openItemInNewTab:item
-                                           incognito:NO];
+- (void)openItemInNewTab:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                              openItemInNewTab:item
+                                     incognito:NO];
 }
 
-- (void)openEntryInNewIncognitoTab:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  [self.delegate readingListCollectionViewController:self
-                                    openItemInNewTab:item
-                                           incognito:YES];
+- (void)openItemInNewIncognitoTab:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                              openItemInNewTab:item
+                                     incognito:YES];
 }
 
-- (void)openEntryOffline:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  [self.delegate readingListCollectionViewController:self
-                             openItemOfflineInNewTab:item];
+- (void)openItemOffline:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                       openItemOfflineInNewTab:item];
 }
 
-- (void)markEntryRead:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  if ([self.collectionViewModel hasItem:item
+- (void)markItemRead:(id<ReadingListListItem>)item {
+  CollectionViewItem<ReadingListListItem>* collectionItem =
+      [self collectionItemForReadingListItem:item];
+  if ([self.collectionViewModel hasItem:collectionItem
                 inSectionWithIdentifier:SectionIdentifierUnread]) {
     [self markItemsReadAtIndexPath:@[ [self.collectionViewModel
-                                       indexPathForItem:item] ]];
+                                       indexPathForItem:collectionItem] ]];
   }
 }
 
-- (void)markEntryUnread:(ListItem*)entry {
-  CollectionViewItem* item =
-      base::mac::ObjCCastStrict<CollectionViewItem>(entry);
-  if ([self.collectionViewModel hasItem:item
+- (void)markItemUnread:(id<ReadingListListItem>)item {
+  CollectionViewItem<ReadingListListItem>* collectionItem =
+      [self collectionItemForReadingListItem:item];
+  if ([self.collectionViewModel hasItem:collectionItem
                 inSectionWithIdentifier:SectionIdentifierRead]) {
     [self markItemsUnreadAtIndexPath:@[ [self.collectionViewModel
-                                         indexPathForItem:item] ]];
+                                         indexPathForItem:collectionItem] ]];
   }
 }
 
@@ -419,7 +412,7 @@
 }
 
 - (void)dismiss {
-  [self.delegate dismissReadingListCollectionViewController:self];
+  [self.delegate dismissReadingListListViewController:self];
 }
 
 - (void)loadModel {
@@ -436,7 +429,7 @@
   }
 }
 
-- (void)loadItemsFromArray:(NSArray<CollectionViewItem*>*)items
+- (void)loadItemsFromArray:(NSArray<id<ReadingListListItem>>*)items
                  toSection:(SectionIdentifier)sectionIdentifier {
   if (items.count == 0) {
     return;
@@ -445,7 +438,7 @@
   [model addSectionWithIdentifier:sectionIdentifier];
   [model setHeader:[self headerForSection:sectionIdentifier]
       forSectionWithIdentifier:sectionIdentifier];
-  for (CollectionViewItem* item in items) {
+  for (CollectionViewItem<ReadingListListItem>* item in items) {
     item.type = ItemTypeItem;
     [self.dataSource fetchFaviconForItem:item];
     [model addItem:item toSectionWithIdentifier:sectionIdentifier];
@@ -453,11 +446,9 @@
 }
 
 - (void)loadItems {
-  NSMutableArray<CollectionViewItem*>* readArray = [NSMutableArray array];
-  NSMutableArray<CollectionViewItem*>* unreadArray = [NSMutableArray array];
-  [self.dataSource fillReadItems:readArray
-                     unreadItems:unreadArray
-         withCustomActionFactory:self.customActionFactory];
+  NSMutableArray<id<ReadingListListItem>>* readArray = [NSMutableArray array];
+  NSMutableArray<id<ReadingListListItem>>* unreadArray = [NSMutableArray array];
+  [self.dataSource fillReadItems:readArray unreadItems:unreadArray];
   [self loadItemsFromArray:unreadArray toSection:SectionIdentifierUnread];
   [self loadItemsFromArray:readArray toSection:SectionIdentifierRead];
 
@@ -511,17 +502,17 @@
     // Make sure there is an item at this position.
     return;
   }
-  CollectionViewItem* touchedItem =
-      [self.collectionViewModel itemAtIndexPath:touchedItemIndexPath];
 
-  if (touchedItem.type != ItemTypeItem) {
+  CollectionViewItem<ReadingListListItem>* item =
+      [self.collectionViewModel itemAtIndexPath:touchedItemIndexPath];
+  if (item.type != ItemTypeItem) {
     // Do not trigger context menu on headers.
     return;
   }
 
-  [self.delegate readingListCollectionViewController:self
-                           displayContextMenuForItem:touchedItem
-                                             atPoint:touchLocation];
+  [self.delegate readingListListViewController:self
+                     displayContextMenuForItem:item
+                                       atPoint:touchLocation];
 }
 
 #pragma mark - ReadingListToolbarDelegate
@@ -577,6 +568,12 @@
 
 #pragma mark - Private methods - Toolbar
 
+- (CollectionViewItem<ReadingListListItem>*)collectionItemForReadingListItem:
+    (id<ReadingListListItem>)item {
+  return base::mac::ObjCCastStrict<CollectionViewItem<ReadingListListItem>>(
+      item);
+}
+
 - (void)updateToolbarState {
   BOOL readSelected = NO;
   BOOL unreadSelected = NO;
@@ -685,9 +682,9 @@
   }
 
   [self updateItemsInSectionIdentifier:SectionIdentifierUnread
-                     usingEntryUpdater:^(CollectionViewItem* item) {
-                       [self.dataSource setReadStatus:YES forItem:item];
-                     }];
+                      usingItemUpdater:^(id<ReadingListListItem> item) {
+                        [self.dataSource setReadStatus:YES forItem:item];
+                      }];
 
   [self exitEditingModeAnimated:YES];
   [self moveItemsFromSection:SectionIdentifierUnread
@@ -701,9 +698,9 @@
   }
 
   [self updateItemsInSectionIdentifier:SectionIdentifierRead
-                     usingEntryUpdater:^(CollectionViewItem* item) {
-                       [self.dataSource setReadStatus:NO forItem:item];
-                     }];
+                      usingItemUpdater:^(id<ReadingListListItem> item) {
+                        [self.dataSource setReadStatus:NO forItem:item];
+                      }];
 
   [self exitEditingModeAnimated:YES];
   [self moveItemsFromSection:SectionIdentifierRead
@@ -715,9 +712,9 @@
   NSArray* sortedIndexPaths =
       [indexPaths sortedArrayUsingSelector:@selector(compare:)];
   [self updateIndexPaths:sortedIndexPaths
-       usingEntryUpdater:^(CollectionViewItem* item) {
-         [self.dataSource setReadStatus:YES forItem:item];
-       }];
+        usingItemUpdater:^(id<ReadingListListItem> item) {
+          [self.dataSource setReadStatus:YES forItem:item];
+        }];
 
   [self exitEditingModeAnimated:YES];
   [self moveSelectedItems:sortedIndexPaths toSection:SectionIdentifierRead];
@@ -728,9 +725,9 @@
   NSArray* sortedIndexPaths =
       [indexPaths sortedArrayUsingSelector:@selector(compare:)];
   [self updateIndexPaths:sortedIndexPaths
-       usingEntryUpdater:^(CollectionViewItem* item) {
-         [self.dataSource setReadStatus:NO forItem:item];
-       }];
+        usingItemUpdater:^(id<ReadingListListItem> item) {
+          [self.dataSource setReadStatus:NO forItem:item];
+        }];
 
   [self exitEditingModeAnimated:YES];
   [self moveSelectedItems:sortedIndexPaths toSection:SectionIdentifierUnread];
@@ -744,9 +741,9 @@
   }
 
   [self updateItemsInSectionIdentifier:SectionIdentifierRead
-                     usingEntryUpdater:^(CollectionViewItem* item) {
-                       [self.dataSource removeEntryFromItem:item];
-                     }];
+                      usingItemUpdater:^(id<ReadingListListItem> item) {
+                        [self.dataSource removeEntryFromItem:item];
+                      }];
 
   [self exitEditingModeAnimated:YES];
   [self.collectionView performBatchUpdates:^{
@@ -768,9 +765,9 @@
 
 - (void)deleteItemsAtIndexPaths:(NSArray*)indexPaths {
   [self updateIndexPaths:indexPaths
-       usingEntryUpdater:^(CollectionViewItem* item) {
-         [self.dataSource removeEntryFromItem:item];
-       }];
+        usingItemUpdater:^(id<ReadingListListItem> item) {
+          [self.dataSource removeEntryFromItem:item];
+        }];
 
   [self exitEditingModeAnimated:YES];
 
@@ -790,7 +787,7 @@
 }
 
 - (void)updateItemsInSectionIdentifier:(SectionIdentifier)identifier
-                     usingEntryUpdater:(EntryUpdater)updater {
+                      usingItemUpdater:(ReadingListListItemUpdater)updater {
   [self.dataSource beginBatchUpdates];
   NSArray* readItems =
       [self.collectionViewModel itemsInSectionWithIdentifier:identifier];
@@ -803,11 +800,12 @@
 }
 
 - (void)updateIndexPaths:(NSArray<NSIndexPath*>*)indexPaths
-       usingEntryUpdater:(EntryUpdater)updater {
+        usingItemUpdater:(ReadingListListItemUpdater)updater {
   [self.dataSource beginBatchUpdates];
   // Read the objects in reverse order to keep the order (last modified first).
   for (NSIndexPath* index in [indexPaths reverseObjectEnumerator]) {
-    CollectionViewItem* item = [self.collectionViewModel itemAtIndexPath:index];
+    id<ReadingListListItem> item =
+        [self.collectionViewModel itemAtIndexPath:index];
     if (updater)
       updater(item);
   }
@@ -954,7 +952,7 @@
   if (!self.dataSource.hasElements) {
     [self collectionIsEmpty];
   } else {
-    [_toolbar setHasReadItem:self.dataSource.hasRead];
+    [_toolbar setHasReadItem:self.dataSource.hasReadElements];
   }
 }
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm
index 75282cb..1311a81b 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm
@@ -20,6 +20,9 @@
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -61,16 +64,17 @@
         nullptr, nullptr, base::DefaultClock::GetInstance()));
     large_icon_service_.reset(new favicon::LargeIconService(
         &mock_favicon_service_, /*image_fetcher=*/nullptr));
-    mediator_ =
-        [[ReadingListMediator alloc] initWithModel:reading_list_model_.get()
-                                  largeIconService:large_icon_service_.get()];
+    mediator_ = [[ReadingListMediator alloc]
+           initWithModel:reading_list_model_.get()
+        largeIconService:large_icon_service_.get()
+         listItemFactory:[ReadingListListItemFactory
+                             collectionViewItemFactory]];
     reading_list_view_controller_ = [[ReadingListCollectionViewController alloc]
         initWithDataSource:mediator_
                    toolbar:nil];
 
     mock_delegate_ = [OCMockObject
-        niceMockForProtocol:@protocol(
-                                ReadingListCollectionViewControllerDelegate)];
+        niceMockForProtocol:@protocol(ReadingListListViewControllerDelegate)];
     [reading_list_view_controller_ setDelegate:mock_delegate_];
   }
 
@@ -109,7 +113,7 @@
   [reading_list_view_controller_ view];
 
   [[mock_delegate_ expect]
-      dismissReadingListCollectionViewController:reading_list_view_controller_];
+      dismissReadingListListViewController:reading_list_view_controller_];
 
   // Simulate tap on "Done" button.
   UIBarButtonItem* done =
@@ -142,8 +146,8 @@
               itemAtIndexPath:indexPath]);
 
   [[mock_delegate_ expect]
-      readingListCollectionViewController:reading_list_view_controller_
-                                 openItem:readingListItem];
+      readingListListViewController:reading_list_view_controller_
+                           openItem:readingListItem];
 
   // Simulate touch on second cell.
   [reading_list_view_controller_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm
index a86c2ae..0f8a994 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm
@@ -7,8 +7,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "components/url_formatter/url_formatter.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
 #import "ios/chrome/browser/ui/util/pasteboard_util.h"
 #import "ios/chrome/common/favicon/favicon_view.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -55,9 +55,7 @@
   cell.accessibilityLabel = GetReadingListCellAccessibilityLabel(
       self.title, subtitle, self.distillationState);
   cell.accessibilityCustomActions =
-      [self.customActionFactory customActionsForItem:self
-                                             withURL:self.entryURL
-                                  distillationStatus:self.distillationState];
+      [self.customActionFactory customActionsForItem:self];
 }
 
 #pragma mark - NSObject
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h
index 52e2eb65..acb71bb 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.h
@@ -6,7 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COORDINATOR_H_
 
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h"
 
 namespace ios {
 class ChromeBrowserState;
@@ -17,7 +17,7 @@
 
 // Coordinator for Reading List, displaying the Reading List when starting.
 @interface ReadingListCoordinator
-    : ChromeCoordinator<ReadingListCollectionViewControllerDelegate>
+    : ChromeCoordinator<ReadingListListViewControllerDelegate>
 
 // Mediator used by this coordinator. Reset when |-start| is called.
 @property(nonatomic, strong, nullable) ReadingListMediator* mediator;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
index 097f6a0..f372471 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -24,7 +24,9 @@
 #import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_commands.h"
 #import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_coordinator.h"
 #import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_params.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_view_controller.h"
@@ -90,9 +92,12 @@
     favicon::LargeIconService* largeIconService =
         IOSChromeLargeIconServiceFactory::GetForBrowserState(self.browserState);
 
-    self.mediator =
-        [[ReadingListMediator alloc] initWithModel:model
-                                  largeIconService:largeIconService];
+    ReadingListListItemFactory* itemFactory =
+        [ReadingListListItemFactory collectionViewItemFactory];
+
+    self.mediator = [[ReadingListMediator alloc] initWithModel:model
+                                              largeIconService:largeIconService
+                                               listItemFactory:itemFactory];
     ReadingListToolbar* toolbar = [[ReadingListToolbar alloc] init];
     ReadingListCollectionViewController* collectionViewController =
         [[ReadingListCollectionViewController alloc]
@@ -100,6 +105,7 @@
 
                        toolbar:toolbar];
     collectionViewController.delegate = self;
+    itemFactory.accessibilityDelegate = collectionViewController;
     self.collectionViewController = collectionViewController;
 
     self.containerViewController = [[ReadingListViewController alloc]
@@ -126,30 +132,29 @@
   self.containerViewController = nil;
 }
 
-#pragma mark - ReadingListCollectionViewControllerDelegate
+#pragma mark - ReadingListListViewControllerDelegate
 
-- (void)dismissReadingListCollectionViewController:
-    (ReadingListCollectionViewController*)readingListCollectionViewController {
-  [readingListCollectionViewController willBeDismissed];
+- (void)dismissReadingListListViewController:(UIViewController*)viewController {
+  DCHECK_EQ(viewController, self.collectionViewController);
+  [self.collectionViewController willBeDismissed];
   [self stop];
 }
 
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                  displayContextMenuForItem:(CollectionViewItem*)item
-                                    atPoint:(CGPoint)menuLocation {
+- (void)readingListListViewController:(UIViewController*)viewController
+            displayContextMenuForItem:(ListItem<ReadingListListItem>*)item
+                              atPoint:(CGPoint)menuLocation {
+  DCHECK_EQ(viewController, self.collectionViewController);
   if (!self.containerViewController) {
     return;
   }
 
-  ReadingListCollectionViewItem* readingListItem =
+  ListItem<ReadingListListItem>* readingListItem =
       base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
 
-  const ReadingListEntry* entry = [self.mediator entryFromItem:item];
+  const ReadingListEntry* entry = [self.mediator entryFromItem:readingListItem];
 
   if (!entry) {
-    [readingListCollectionViewController reloadData];
+    [self.collectionViewController reloadData];
     return;
   }
   const GURL entryURL = entry->URL();
@@ -165,7 +170,7 @@
   params.title = readingListItem.title;
   params.message = base::SysUTF8ToNSString(readingListItem.entryURL.host());
   params.rect = CGRectMake(menuLocation.x, menuLocation.y, 0, 0);
-  params.view = readingListCollectionViewController.collectionView;
+  params.view = self.collectionViewController.collectionView;
   params.entryURL = entryURL;
   params.offlineURL = offlineURL;
 
@@ -176,65 +181,47 @@
   [self.contextMenuCoordinator start];
 }
 
-- (void)
-readingListCollectionViewController:
-    (ReadingListCollectionViewController*)readingListCollectionViewController
-                           openItem:(CollectionViewItem*)readingListItem {
-  const ReadingListEntry* entry = [self.mediator entryFromItem:readingListItem];
-
-  if (!entry) {
-    [readingListCollectionViewController reloadData];
-    return;
-  }
-
-  base::RecordAction(base::UserMetricsAction("MobileReadingListOpen"));
-
-  [readingListCollectionViewController willBeDismissed];
-
-  web::NavigationManager::WebLoadParams params(entry->URL());
-  params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK;
-  // Use a referrer with a specific URL to signal that this entry should not be
-  // taken into account for the Most Visited tiles.
-  params.referrer =
-      web::Referrer(GURL(kReadingListReferrerURL), web::ReferrerPolicyDefault);
-  [self.URLLoader loadURLWithParams:params];
-  new_tab_page_uma::RecordAction(
-      self.browserState, new_tab_page_uma::ACTION_OPENED_READING_LIST_ENTRY);
-
-  [self stop];
-}
-
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                           openItemInNewTab:(CollectionViewItem*)item
-                                  incognito:(BOOL)incognito {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
-  [self readingListCollectionViewController:readingListCollectionViewController
-                          openNewTabWithURL:readingListItem.entryURL
-                                  incognito:incognito];
-}
-
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                    openItemOfflineInNewTab:(CollectionViewItem*)item {
+- (void)readingListListViewController:(UIViewController*)viewController
+                             openItem:(ListItem<ReadingListListItem>*)item {
   const ReadingListEntry* entry = [self.mediator entryFromItem:item];
-
   if (!entry) {
+    [self.collectionViewController reloadData];
     return;
   }
+  [self loadEntryURL:entry->URL()
+      withOfflineURL:GURL::EmptyGURL()
+            inNewTab:NO
+           incognito:NO];
+}
+
+- (void)readingListListViewController:(UIViewController*)viewController
+                     openItemInNewTab:(ListItem<ReadingListListItem>*)item
+                            incognito:(BOOL)incognito {
+  const ReadingListEntry* entry = [self.mediator entryFromItem:item];
+  if (!entry) {
+    [self.collectionViewController reloadData];
+    return;
+  }
+  [self loadEntryURL:entry->URL()
+      withOfflineURL:GURL::EmptyGURL()
+            inNewTab:YES
+           incognito:incognito];
+}
+
+- (void)readingListListViewController:(UIViewController*)viewController
+              openItemOfflineInNewTab:(id<ReadingListListItem>)item {
+  const ReadingListEntry* entry = [self.mediator entryFromItem:item];
+  if (!entry)
+    return;
 
   if (entry->DistilledState() == ReadingListEntry::PROCESSED) {
     const GURL entryURL = entry->URL();
     GURL offlineURL = reading_list::OfflineURLForPath(
         entry->DistilledPath(), entryURL, entry->DistilledURL());
-
-    [self
-        readingListCollectionViewController:readingListCollectionViewController
-                             openOfflineURL:offlineURL
-                      correspondingEntryURL:entryURL];
+    [self loadEntryURL:entry->URL()
+        withOfflineURL:offlineURL
+              inNewTab:YES
+             incognito:NO];
   }
 }
 
@@ -242,17 +229,19 @@
 
 - (void)openURLInNewTabForContextMenuWithParams:
     (ReadingListContextMenuParams*)params {
-  [self readingListCollectionViewController:self.collectionViewController
-                          openNewTabWithURL:params.entryURL
-                                  incognito:NO];
+  [self loadEntryURL:params.entryURL
+      withOfflineURL:GURL::EmptyGURL()
+            inNewTab:YES
+           incognito:NO];
   [self cleanUpContextMenu];
 }
 
 - (void)openURLInNewIncognitoTabForContextMenuWithParams:
     (ReadingListContextMenuParams*)params {
-  [self readingListCollectionViewController:self.collectionViewController
-                          openNewTabWithURL:params.entryURL
-                                  incognito:YES];
+  [self loadEntryURL:params.entryURL
+      withOfflineURL:GURL::EmptyGURL()
+            inNewTab:YES
+           incognito:YES];
   [self cleanUpContextMenu];
 }
 
@@ -263,9 +252,10 @@
 
 - (void)openOfflineURLInNewTabForContextMenuWithParams:
     (ReadingListContextMenuParams*)params {
-  [self readingListCollectionViewController:self.collectionViewController
-                             openOfflineURL:params.offlineURL
-                      correspondingEntryURL:params.entryURL];
+  [self loadEntryURL:params.entryURL
+      withOfflineURL:params.offlineURL
+            inNewTab:YES
+           incognito:NO];
   [self cleanUpContextMenu];
 }
 
@@ -284,36 +274,51 @@
 
 #pragma mark - Private
 
-// Opens the offline url |offlineURL| of the entry saved in the reading list
-// model with the |entryURL| url.
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                             openOfflineURL:(const GURL&)offlineURL
-                      correspondingEntryURL:(const GURL&)entryURL {
-  [self readingListCollectionViewController:readingListCollectionViewController
-                          openNewTabWithURL:offlineURL
-                                  incognito:NO];
-
-  UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true);
-  const GURL updateURL = entryURL;
-  [self.mediator markEntryRead:updateURL];
-}
-
-// Opens |URL| in a new tab |incognito| or not.
-- (void)readingListCollectionViewController:
-            (ReadingListCollectionViewController*)
-                readingListCollectionViewController
-                          openNewTabWithURL:(const GURL&)URL
-                                  incognito:(BOOL)incognito {
+// Loads reading list URLs.  If |offlineURL| is valid, the item will be loaded
+// offline; otherwise |entryURL| is loaded.  |newTab| and |incognito| can be
+// used to optionally open the URL in a new tab or in incognito.  The
+// coordinator is also stopped after the load is requested.
+- (void)loadEntryURL:(const GURL&)entryURL
+      withOfflineURL:(const GURL&)offlineURL
+            inNewTab:(BOOL)newTab
+           incognito:(BOOL)incognito {
+  DCHECK(entryURL.is_valid());
   base::RecordAction(base::UserMetricsAction("MobileReadingListOpen"));
+  new_tab_page_uma::RecordAction(
+      self.browserState, new_tab_page_uma::ACTION_OPENED_READING_LIST_ENTRY);
 
-  [readingListCollectionViewController willBeDismissed];
-  [self.URLLoader webPageOrderedOpen:URL
-                            referrer:web::Referrer()
-                         inIncognito:incognito
-                        inBackground:NO
-                            appendTo:kLastTab];
+  // Load the offline URL if available.
+  GURL loadURL = entryURL;
+  if (offlineURL.is_valid()) {
+    loadURL = offlineURL;
+    // Offline URLs should always be opened in new tabs.
+    newTab = YES;
+    // Record the offline load and update the model.
+    UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true);
+    const GURL updateURL = entryURL;
+    [self.mediator markEntryRead:updateURL];
+  }
+
+  // Prepare the collection for dismissal.
+  [self.collectionViewController willBeDismissed];
+
+  // Use a referrer with a specific URL to signal that this entry should not be
+  // taken into account for the Most Visited tiles.
+  web::Referrer referrer =
+      web::Referrer(GURL(kReadingListReferrerURL), web::ReferrerPolicyDefault);
+  if (newTab) {
+    [self.URLLoader webPageOrderedOpen:loadURL
+                              referrer:referrer
+                           inIncognito:incognito
+                          inBackground:NO
+                              appendTo:kLastTab];
+  } else {
+    web::NavigationManager::WebLoadParams params(loadURL);
+    params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK;
+    params.referrer = web::Referrer(GURL(kReadingListReferrerURL),
+                                    web::ReferrerPolicyDefault);
+    [self.URLLoader loadURLWithParams:params];
+  }
 
   [self stop];
 }
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
index e46aefe..9cf5f3a4 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
@@ -21,6 +21,7 @@
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_utils.h"
 #import "ios/chrome/browser/ui/url_loader.h"
@@ -57,9 +58,11 @@
         nullptr, nullptr, base::DefaultClock::GetInstance()));
     large_icon_service_.reset(new favicon::LargeIconService(
         &mock_favicon_service_, /*image_fetcher=*/nullptr));
-    mediator_ =
-        [[ReadingListMediator alloc] initWithModel:reading_list_model_.get()
-                                  largeIconService:large_icon_service_.get()];
+    mediator_ = [[ReadingListMediator alloc]
+           initWithModel:reading_list_model_.get()
+        largeIconService:large_icon_service_.get()
+         listItemFactory:[ReadingListListItemFactory
+                             collectionViewItemFactory]];
     coordinator_ = [[ReadingListCoordinator alloc]
         initWithBaseViewController:nil
                       browserState:browser_state_.get()
@@ -117,9 +120,9 @@
   item.distillationState = ReadingListUIDistillationStatusSuccess;
 
   // Action.
-  [GetCoordinator() readingListCollectionViewController:
-                        GetAReadingListCollectionViewController()
-                                               openItem:item];
+  [GetCoordinator()
+      readingListListViewController:GetAReadingListCollectionViewController()
+                           openItem:item];
 
   // Tests.
   FakeURLLoader* loader = GetLoader();
@@ -149,9 +152,9 @@
   ASSERT_FALSE(model->GetEntryByURL(url)->IsRead());
 
   // Action.
-  [GetCoordinator() readingListCollectionViewController:
-                        GetAReadingListCollectionViewController()
-                                openItemOfflineInNewTab:item];
+  [GetCoordinator()
+      readingListListViewController:GetAReadingListCollectionViewController()
+            openItemOfflineInNewTab:item];
 
   // Tests.
   FakeURLLoader* loader = GetLoader();
@@ -173,10 +176,10 @@
   item.distillationState = ReadingListUIDistillationStatusSuccess;
 
   // Action.
-  [GetCoordinator() readingListCollectionViewController:
-                        GetAReadingListCollectionViewController()
-                                       openItemInNewTab:item
-                                              incognito:YES];
+  [GetCoordinator()
+      readingListListViewController:GetAReadingListCollectionViewController()
+                   openItemInNewTab:item
+                          incognito:YES];
 
   // Tests.
   FakeURLLoader* loader = GetLoader();
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_data_sink.h b/ios/chrome/browser/ui/reading_list/reading_list_data_sink.h
index 29203ef9..48337c7 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_data_sink.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_data_sink.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_DATA_SINK_H_
 
 @protocol ReadingListDataSource;
+@protocol ReadingListListItem;
 
 // Data Sink for the Reading List UI, receiving informations from the data
 // source.
@@ -18,16 +19,16 @@
 - (void)dataSourceChanged;
 
 // Returns the read items displayed.
-- (NSArray<CollectionViewItem*>*)readItems;
+- (NSArray<id<ReadingListListItem>>*)readItems;
 // Returns the unread items displayed.
-- (NSArray<CollectionViewItem*>*)unreadItems;
+- (NSArray<id<ReadingListListItem>>*)unreadItems;
 
 // Notifies the DataSink that the |item| has changed and it should be reloaded
 // if it is still displayed.
-- (void)itemHasChangedAfterDelay:(CollectionViewItem*)item;
+- (void)itemHasChangedAfterDelay:(id<ReadingListListItem>)item;
 // Notifies the DataSink that the |items| have changed and must be reloaded. The
 // |items| must be presented.
-- (void)itemsHaveChanged:(NSArray<CollectionViewItem*>*)items;
+- (void)itemsHaveChanged:(NSArray<id<ReadingListListItem>>*)items;
 
 @end
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_data_source.h b/ios/chrome/browser/ui/reading_list/reading_list_data_source.h
index 6381151..3704ed2 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_data_source.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_data_source.h
@@ -7,9 +7,8 @@
 
 #include <memory>
 
-@class CollectionViewItem;
 @protocol ReadingListDataSink;
-@class ReadingListListViewItemCustomActionFactory;
+@protocol ReadingListListItem;
 
 // Data Source for the Reading List UI, providing the data sink with the data to
 // be displayed. Handle the interactions with the model.
@@ -18,35 +17,33 @@
 // The data sink associated with this data source.
 @property(nonatomic, weak, nullable) id<ReadingListDataSink> dataSink;
 // Whether the data source is ready to be used.
-- (BOOL)ready;
+@property(nonatomic, readonly, getter=isReady) BOOL ready;
 // Whether the data source has some elements.
-- (BOOL)hasElements;
+@property(nonatomic, readonly) BOOL hasElements;
 // Whether the data source has some read elements.
-- (BOOL)hasRead;
+@property(nonatomic, readonly) BOOL hasReadElements;
+
 // Whether the entry corresponding to the |item| is read.
-- (BOOL)isEntryRead:(nonnull CollectionViewItem*)item;
+- (BOOL)isItemRead:(nonnull id<ReadingListListItem>)item;
 
 // Mark all entries as seen and stop sending updates to the data sink.
 - (void)dataSinkWillBeDismissed;
 
 // Set the read status of the entry associated with |item|.
-- (void)setReadStatus:(BOOL)read forItem:(nonnull CollectionViewItem*)item;
+- (void)setReadStatus:(BOOL)read forItem:(nonnull id<ReadingListListItem>)item;
 
 // Removes the entry associated with |item| and logs the deletion.
-- (void)removeEntryFromItem:(nonnull CollectionViewItem*)item;
+- (void)removeEntryFromItem:(nonnull id<ReadingListListItem>)item;
 
 // Fills the |readArray| and |unreadArray| with the corresponding items from the
 // model. The items are sorted most recent first.
-- (void)fillReadItems:(nullable NSMutableArray<CollectionViewItem*>*)readArray
-                unreadItems:
-                    (nullable NSMutableArray<CollectionViewItem*>*)unreadArray
-    withCustomActionFactory:
-        (nullable ReadingListListViewItemCustomActionFactory*)
-            customActionFactory;
+- (void)
+fillReadItems:(nullable NSMutableArray<id<ReadingListListItem>>*)readArray
+  unreadItems:(nullable NSMutableArray<id<ReadingListListItem>>*)unreadArray;
 
 // Fetches the |faviconURL| of this |item|, notifies the data sink when
 // receiving the favicon.
-- (void)fetchFaviconForItem:(nonnull CollectionViewItem*)item;
+- (void)fetchFaviconForItem:(nonnull id<ReadingListListItem>)item;
 
 // Prepares the data source for batch updates. The UI is not notified for the
 // updates happenning between |-beginBatchUpdates| and |-endBatchUpdates|.
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index ab35cf8..60558cde 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -16,10 +16,10 @@
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #import "ios/chrome/browser/ui/commands/reading_list_add_command.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
+#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button.h"
 #include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
@@ -275,7 +275,7 @@
 // Returns a match for the Reading List Empty Collection Background.
 id<GREYMatcher> EmptyBackground() {
   return grey_accessibilityID(
-      [ReadingListEmptyCollectionBackground accessibilityIdentifier]);
+      [EmptyReadingListBackgroundView accessibilityIdentifier]);
 }
 
 // Adds the current page to the Reading List.
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h b/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h
deleted file mode 100644
index edd28f6..0000000
--- a/ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_EMPTY_COLLECTION_BACKGROUND_H_
-#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_EMPTY_COLLECTION_BACKGROUND_H_
-
-#import <UIKit/UIKit.h>
-
-@interface ReadingListEmptyCollectionBackground : UIView
-
-- (instancetype)init NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
-- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
-
-+ (NSString*)accessibilityIdentifier;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_EMPTY_COLLECTION_BACKGROUND_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item.h
index cd32c3c..2360ad9 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_item.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item.h
@@ -11,7 +11,7 @@
 
 class GURL;
 @class FaviconAttributes;
-@class ReadingListListViewItemCustomActionFactory;
+@class ReadingListListItemCustomActionFactory;
 
 // Protocol used to supply reading list data to list items.
 @protocol ReadingListListItem<NSObject>
@@ -30,7 +30,7 @@
 @property(nonatomic, copy) NSString* distillationDateText;
 // The custom action factory.
 @property(nonatomic, weak)
-    ReadingListListViewItemCustomActionFactory* customActionFactory;
+    ReadingListListItemCustomActionFactory* customActionFactory;
 // Attributes for favicon.
 @property(nonatomic, strong) FaviconAttributes* attributes;
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h
new file mode 100644
index 0000000..2bd0fca
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_ACCESSIBILITY_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_ACCESSIBILITY_DELEGATE_H_
+
+@protocol ReadingListListItem;
+
+// Protocol used to implement custom accessibility actions for cells set up by
+// ReadingListListItems.
+@protocol ReadingListListItemAccessibilityDelegate
+
+// Returns whether the entry is read.
+- (BOOL)isItemRead:(id<ReadingListListItem>)item;
+
+- (void)deleteItem:(id<ReadingListListItem>)item;
+- (void)openItemInNewTab:(id<ReadingListListItem>)item;
+- (void)openItemInNewIncognitoTab:(id<ReadingListListItem>)item;
+- (void)openItemOffline:(id<ReadingListListItem>)item;
+- (void)markItemRead:(id<ReadingListListItem>)item;
+- (void)markItemUnread:(id<ReadingListListItem>)item;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_ACCESSIBILITY_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h
new file mode 100644
index 0000000..cf3c517
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_CUSTOM_ACTION_FACTORY_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_CUSTOM_ACTION_FACTORY_H_
+
+#import <UIKit/UIKit.h>
+
+@protocol ReadingListListItem;
+@protocol ReadingListListItemAccessibilityDelegate;
+
+// Factory object that creates arrays of custom accessibility actions for
+// ListItems used by the reading list.
+@interface ReadingListListItemCustomActionFactory : NSObject
+
+// Delegate for the accessibility actions.
+@property(nonatomic, weak) id<ReadingListListItemAccessibilityDelegate>
+    accessibilityDelegate;
+
+// Creates an array of custom a11y actions for a reading list cell configured
+// for |item| with |status|.
+- (NSArray<UIAccessibilityCustomAction*>*)customActionsForItem:
+    (id<ReadingListListItem>)item;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_CUSTOM_ACTION_FACTORY_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm
similarity index 67%
rename from ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.mm
rename to ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm
index ac44a65..47e4fd9 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.mm
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
 
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h"
 #import "ios/chrome/browser/ui/util/pasteboard_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -20,15 +21,13 @@
 @interface ReadingListCustomAction : UIAccessibilityCustomAction
 
 // The reading list item.
-@property(nonatomic, readonly, strong) ListItem* item;
-// The URL.
-@property(nonatomic, readonly) GURL itemURL;
+@property(nonatomic, readonly, strong) id<ReadingListListItem> item;
 
 - (instancetype)initWithName:(NSString*)name
                       target:(id)target
                     selector:(SEL)selector
-                        item:(ListItem*)item
-                         URL:(const GURL&)URL NS_DESIGNATED_INITIALIZER;
+                        item:(id<ReadingListListItem>)item
+    NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithName:(NSString*)name
                       target:(id)target
                     selector:(SEL)selector NS_UNAVAILABLE;
@@ -36,54 +35,46 @@
 
 @implementation ReadingListCustomAction
 @synthesize item = _item;
-@synthesize itemURL = _itemURL;
 
 - (instancetype)initWithName:(NSString*)name
                       target:(id)target
                     selector:(SEL)selector
-                        item:(ListItem*)item
-                         URL:(const GURL&)URL {
+                        item:(id<ReadingListListItem>)item {
   if (self = [super initWithName:name target:target selector:selector]) {
     _item = item;
-    _itemURL = URL;
   }
   return self;
 }
 
 @end
 
-#pragma mark - ReadingListListViewItemCustomActionFactory
+#pragma mark - ReadingListListItemCustomActionFactory
 
-@implementation ReadingListListViewItemCustomActionFactory
+@implementation ReadingListListItemCustomActionFactory
 @synthesize accessibilityDelegate = _accessibilityDelegate;
 
-- (NSArray<UIAccessibilityCustomAction*>*)
-customActionsForItem:(ListItem*)item
-             withURL:(const GURL&)URL
-  distillationStatus:(ReadingListUIDistillationStatus)status {
+- (NSArray<UIAccessibilityCustomAction*>*)customActionsForItem:
+    (id<ReadingListListItem>)item {
   ReadingListCustomAction* deleteAction = [[ReadingListCustomAction alloc]
       initWithName:l10n_util::GetNSString(IDS_IOS_READING_LIST_DELETE_BUTTON)
             target:self
-          selector:@selector(deleteEntry:)
-              item:item
-               URL:URL];
+          selector:@selector(deleteItem:)
+              item:item];
   ReadingListCustomAction* toggleReadStatus = nil;
-  if ([self.accessibilityDelegate isEntryRead:item]) {
+  if ([self.accessibilityDelegate isItemRead:item]) {
     toggleReadStatus = [[ReadingListCustomAction alloc]
         initWithName:l10n_util::GetNSString(
                          IDS_IOS_READING_LIST_MARK_UNREAD_BUTTON)
               target:self
             selector:@selector(markUnread:)
-                item:item
-                 URL:URL];
+                item:item];
   } else {
     toggleReadStatus = [[ReadingListCustomAction alloc]
         initWithName:l10n_util::GetNSString(
                          IDS_IOS_READING_LIST_MARK_READ_BUTTON)
               target:self
             selector:@selector(markRead:)
-                item:item
-                 URL:URL];
+                item:item];
   }
 
   ReadingListCustomAction* openInNewTabAction = [[ReadingListCustomAction alloc]
@@ -91,28 +82,25 @@
                        IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)
             target:self
           selector:@selector(openInNewTab:)
-              item:item
-               URL:URL];
+              item:item];
   ReadingListCustomAction* openInNewIncognitoTabAction =
       [[ReadingListCustomAction alloc]
           initWithName:l10n_util::GetNSString(
                            IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)
                 target:self
               selector:@selector(openInNewIncognitoTab:)
-                  item:item
-                   URL:URL];
+                  item:item];
   ReadingListCustomAction* copyURLAction = [[ReadingListCustomAction alloc]
       initWithName:l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY)
             target:self
           selector:@selector(copyURL:)
-              item:item
-               URL:URL];
+              item:item];
 
   NSMutableArray* customActions = [NSMutableArray
       arrayWithObjects:deleteAction, toggleReadStatus, openInNewTabAction,
                        openInNewIncognitoTabAction, copyURLAction, nil];
 
-  if (status == ReadingListUIDistillationStatusSuccess) {
+  if (item.distillationState == ReadingListUIDistillationStatusSuccess) {
     // Add the possibility to open offline version only if the entry is
     // distilled.
     ReadingListCustomAction* openOfflineAction =
@@ -121,8 +109,7 @@
                              IDS_IOS_READING_LIST_CONTENT_CONTEXT_OFFLINE)
                   target:self
                 selector:@selector(openOffline:)
-                    item:item
-                     URL:URL];
+                    item:item];
 
     [customActions addObject:openOfflineAction];
   }
@@ -130,38 +117,38 @@
   return customActions;
 }
 
-- (BOOL)deleteEntry:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate deleteEntry:action.item];
+- (BOOL)deleteItem:(ReadingListCustomAction*)action {
+  [self.accessibilityDelegate deleteItem:action.item];
   return YES;
 }
 
 - (BOOL)markRead:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate markEntryRead:action.item];
+  [self.accessibilityDelegate markItemRead:action.item];
   return YES;
 }
 
 - (BOOL)markUnread:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate markEntryUnread:action.item];
+  [self.accessibilityDelegate markItemUnread:action.item];
   return YES;
 }
 
 - (BOOL)openInNewTab:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate openEntryInNewTab:action.item];
+  [self.accessibilityDelegate openItemInNewTab:action.item];
   return YES;
 }
 
 - (BOOL)openInNewIncognitoTab:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate openEntryInNewIncognitoTab:action.item];
+  [self.accessibilityDelegate openItemInNewIncognitoTab:action.item];
   return YES;
 }
 
 - (BOOL)copyURL:(ReadingListCustomAction*)action {
-  StoreURLInPasteboard(action.itemURL);
+  StoreURLInPasteboard(action.item.entryURL);
   return YES;
 }
 
 - (BOOL)openOffline:(ReadingListCustomAction*)action {
-  [self.accessibilityDelegate openEntryOffline:action.item];
+  [self.accessibilityDelegate openItemOffline:action.item];
   return YES;
 }
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h
new file mode 100644
index 0000000..ab76c21
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_FACTORY_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_FACTORY_H_
+
+#import <UIKit/UIKit.h>
+
+@class ListItem;
+class ReadingListEntry;
+@protocol ReadingListListItem;
+@protocol ReadingListListItemAccessibilityDelegate;
+
+// Factory object that produces ListItems for Reading List.
+@interface ReadingListListItemFactory : NSObject
+
+// A factory that produces ReadingListTableViewItems.
++ (instancetype)tableViewItemFactory;
+
+// A factory that produces ReadingListCollectionViewItems.
++ (instancetype)collectionViewItemFactory;
+
+// Use either |+tableViewItemFactory| or |+collectionViewItemFactory|.
+- (instancetype)init NS_UNAVAILABLE;
+
+// The accessibility delegate to use for the created items.
+@property(nonatomic, weak) id<ReadingListListItemAccessibilityDelegate>
+    accessibilityDelegate;
+
+// Factory method that provides a ListItem for the reading list.
+- (ListItem<ReadingListListItem>*)cellItemForReadingListEntry:
+    (const ReadingListEntry*)entry;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_FACTORY_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm
new file mode 100644
index 0000000..5ca6401
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm
@@ -0,0 +1,105 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/reading_list/core/reading_list_entry.h"
+#include "components/url_formatter/url_formatter.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_utils.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// The different types of items to be vended by the factory.
+enum class ItemFactoryType { TABLE, COLLECTION };
+}  // namespace
+
+@interface ReadingListListItemFactory ()
+
+// The factory type.
+@property(nonatomic, assign) ItemFactoryType factoryType;
+// The factory supplying custom accessibility actions to the items.
+@property(nonatomic, readonly, strong)
+    ReadingListListItemCustomActionFactory* customActionFactory;
+
+// Initializer for a factory of |factoryType|.
+- (instancetype)initWithFactoryType:(ItemFactoryType)factoryType
+    NS_DESIGNATED_INITIALIZER;
+
+@end
+
+@implementation ReadingListListItemFactory
+@synthesize factoryType = _factoryType;
+@synthesize customActionFactory = _customActionFactory;
+
+- (instancetype)initWithFactoryType:(ItemFactoryType)factoryType {
+  if (self = [super init]) {
+    _factoryType = factoryType;
+    _customActionFactory =
+        [[ReadingListListItemCustomActionFactory alloc] init];
+  }
+  return self;
+}
+
+#pragma mark Accessors
+
+- (void)setAccessibilityDelegate:
+    (id<ReadingListListItemAccessibilityDelegate>)accessibilityDelegate {
+  self.customActionFactory.accessibilityDelegate = accessibilityDelegate;
+}
+
+- (id<ReadingListListItemAccessibilityDelegate>)accessibilityDelegate {
+  return self.customActionFactory.accessibilityDelegate;
+}
+
+#pragma mark Public
+
++ (instancetype)tableViewItemFactory {
+  return [[ReadingListListItemFactory alloc]
+      initWithFactoryType:ItemFactoryType::TABLE];
+}
+
++ (instancetype)collectionViewItemFactory {
+  return [[ReadingListListItemFactory alloc]
+      initWithFactoryType:ItemFactoryType::COLLECTION];
+}
+
+- (ListItem<ReadingListListItem>*)cellItemForReadingListEntry:
+    (const ReadingListEntry*)entry {
+  ListItem<ReadingListListItem>* item =
+      self.factoryType == ItemFactoryType::TABLE
+          ? [[ReadingListTableViewItem alloc] initWithType:0]
+          : [[ReadingListCollectionViewItem alloc] initWithType:0];
+  item.title = base::SysUTF8ToNSString(entry->Title());
+  const GURL& URL = entry->URL();
+  item.entryURL = URL;
+  item.faviconPageURL =
+      entry->DistilledURL().is_valid() ? entry->DistilledURL() : URL;
+  item.distillationState =
+      reading_list::UIStatusFromModelStatus(entry->DistilledState());
+  BOOL hasDistillationDetails =
+      entry->DistilledState() == ReadingListEntry::PROCESSED &&
+      entry->DistillationSize() != 0 && entry->DistillationTime() != 0;
+  int64_t distillationDate =
+      hasDistillationDetails ? entry->DistillationTime() : 0;
+  item.distillationDateText =
+      GetReadingListCellDistillationDateText(distillationDate);
+  int64_t distillationSize =
+      hasDistillationDetails ? entry->DistillationSize() : 0;
+  item.distillationSizeText =
+      GetReadingListCellDistillationSizeText(distillationSize);
+  item.customActionFactory = self.customActionFactory;
+  return item;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm
new file mode 100644
index 0000000..08845a42
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
+
+#include "base/time/time.h"
+#include "components/reading_list/core/reading_list_entry.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "url/gurl.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+class ReadingListListItemFactoryTest : public PlatformTest {
+ public:
+  ReadingListListItemFactoryTest()
+      : PlatformTest(),
+        entry_(GURL("https://www.google.com"), "Google", base::Time::Now()) {}
+
+ protected:
+  const ReadingListEntry entry_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ReadingListListItemFactoryTest);
+};
+
+// Tests that the accessibility delegate is properly passed to the generated
+// ListItems.
+TEST_F(ReadingListListItemFactoryTest, SetA11yDelegate) {
+  id<ReadingListListItemAccessibilityDelegate> mockDelegate =
+      OCMProtocolMock(@protocol(ReadingListListItemAccessibilityDelegate));
+  ReadingListListItemFactory* factory =
+      [ReadingListListItemFactory tableViewItemFactory];
+  factory.accessibilityDelegate = mockDelegate;
+  id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_];
+  EXPECT_EQ(item.customActionFactory.accessibilityDelegate, mockDelegate);
+}
+
+// Tests that |+tableViewItemFactory| returns ReadingListTableViewItems.
+TEST_F(ReadingListListItemFactoryTest, TableViewItem) {
+  ReadingListListItemFactory* factory =
+      [ReadingListListItemFactory tableViewItemFactory];
+  id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_];
+  EXPECT_TRUE([item isKindOfClass:[ReadingListTableViewItem class]]);
+}
+
+// Tests that |+collectionViewItemFactory| returns
+// ReadingListCollectionViewItems.
+TEST_F(ReadingListListItemFactoryTest, CollectionViewItem) {
+  ReadingListListItemFactory* factory =
+      [ReadingListListItemFactory collectionViewItemFactory];
+  id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_];
+  EXPECT_TRUE([item isKindOfClass:[ReadingListCollectionViewItem class]]);
+}
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h
new file mode 100644
index 0000000..b1c45af
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h
@@ -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.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UPDATER_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UPDATER_H_
+
+#import <Foundation/Foundation.h>
+
+@protocol ReadingListListItem;
+
+// Typedef for a block taking a ReadingListListItem as parameter and returning
+// nothing.
+typedef void (^ReadingListListItemUpdater)(id<ReadingListListItem> item);
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UPDATER_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h
similarity index 87%
rename from ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h
rename to ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h
index 577bed5..853f1c1 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_UTIL_H_
-#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_UTIL_H_
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UTIL_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UTIL_H_
 
 #import <Foundation/Foundation.h>
 
@@ -30,4 +30,4 @@
 BOOL AreReadingListListItemsEqual(id<ReadingListListItem> first,
                                   id<ReadingListListItem> second);
 
-#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_UTIL_H_
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_ITEM_UTIL_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_util.mm
similarity index 94%
rename from ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.mm
rename to ios/chrome/browser/ui/reading_list/reading_list_list_item_util.mm
index a549460..9d15fdc 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_util.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
 
 #include "base/i18n/time_formatting.h"
 #include "base/strings/sys_string_conversions.h"
@@ -35,12 +35,16 @@
 }
 
 NSString* GetReadingListCellDistillationSizeText(int64_t distillation_size) {
+  if (!distillation_size)
+    return nil;
   return [NSByteCountFormatter
       stringFromByteCount:distillation_size
                countStyle:NSByteCountFormatterCountStyleFile];
 }
 
 NSString* GetReadingListCellDistillationDateText(int64_t distillation_date) {
+  if (!distillation_date)
+    return nil;
   int64_t now = (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds();
   int64_t elapsed = now - distillation_date;
   if (elapsed < base::Time::kMicrosecondsPerMinute) {
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h b/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h
new file mode 100644
index 0000000..594d151
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h
@@ -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.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_AUDIENCE_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_AUDIENCE_H_
+
+// Audience for the Reading List view controllers.
+@protocol ReadingListListViewControllerAudience
+
+// Whether the collection has items.
+- (void)readingListHasItems:(BOOL)hasItems;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_AUDIENCE_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h b/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h
new file mode 100644
index 0000000..3e90fad
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_DELEGATE_H_
+
+#import <Foundation/Foundation.h>
+
+@class ListItem;
+@protocol ReadingListListItem;
+
+// Delegate protocol for actions performed by the list view implementations,
+// managing the visibility of the toolbar, dismissing the Reading List View and
+// opening elements.
+@protocol ReadingListListViewControllerDelegate<NSObject>
+
+// Dismisses the Reading List View.
+- (void)dismissReadingListListViewController:
+    (UIViewController*)readingListCollectionViewController;
+
+// Displays the context menu for the |item|. |menuLocation| is used as the
+// anchor of the context menu in the |viewController.view|'s coordinates.
+- (void)readingListListViewController:(UIViewController*)viewController
+            displayContextMenuForItem:(id<ReadingListListItem>)item
+                              atPoint:(CGPoint)menuLocation;
+
+// Opens |item.entryURL|.
+- (void)readingListListViewController:(UIViewController*)viewController
+                             openItem:(id<ReadingListListItem>)item;
+
+// Opens the entry corresponding to the |item| in a new tab, |incognito| or not.
+- (void)readingListListViewController:(UIViewController*)viewController
+                     openItemInNewTab:(id<ReadingListListItem>)item
+                            incognito:(BOOL)incognito;
+
+// Opens the offline version of the entry corresponding to the |item| in a new
+// tab, if available.
+- (void)readingListListViewController:(UIViewController*)viewController
+              openItemOfflineInNewTab:(id<ReadingListListItem>)item;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h b/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h
deleted file mode 100644
index be7387b..0000000
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_ACCESSIBILITY_DELEGATE_H_
-#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_ACCESSIBILITY_DELEGATE_H_
-
-@class ListItem;
-
-@protocol ReadingListListViewItemAccessibilityDelegate
-
-// Returns whether the entry is read.
-- (BOOL)isEntryRead:(ListItem*)item;
-
-- (void)deleteEntry:(ListItem*)item;
-- (void)openEntryInNewTab:(ListItem*)item;
-- (void)openEntryInNewIncognitoTab:(ListItem*)item;
-- (void)openEntryOffline:(ListItem*)item;
-- (void)markEntryRead:(ListItem*)item;
-- (void)markEntryUnread:(ListItem*)item;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_ACCESSIBILITY_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h b/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h
deleted file mode 100644
index b0887c39b..0000000
--- a/ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_CUSTOM_ACTION_FACTORY_H_
-#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_CUSTOM_ACTION_FACTORY_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/ui/reading_list/reading_list_ui_distillation_status.h"
-
-class GURL;
-@class ListItem;
-@protocol ReadingListListViewItemAccessibilityDelegate;
-
-// Factory object that creates arrays of custom accessibility actions for
-// ListItems used by the reading list.
-@interface ReadingListListViewItemCustomActionFactory : NSObject
-
-// Delegate for the accessibility actions.
-@property(nonatomic, weak) id<ReadingListListViewItemAccessibilityDelegate>
-    accessibilityDelegate;
-
-// Creates an array of custom a11y actions for a reading list cell configured
-// for |item| with |status|.
-- (NSArray<UIAccessibilityCustomAction*>*)
-customActionsForItem:(ListItem*)item
-             withURL:(const GURL&)URL
-  distillationStatus:(ReadingListUIDistillationStatus)status;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_LIST_VIEW_ITEM_CUSTOM_ACTION_FACTORY_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator.h b/ios/chrome/browser/ui/reading_list/reading_list_mediator.h
index 2e66c90..70f34380 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_mediator.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator.h
@@ -15,6 +15,7 @@
 
 class GURL;
 class ReadingListEntry;
+@class ReadingListListItemFactory;
 class ReadingListModel;
 
 // Mediator between the Model and the UI.
@@ -22,16 +23,17 @@
 
 - (nullable instancetype)init NS_UNAVAILABLE;
 
-- (nullable instancetype)initWithModel:(nonnull ReadingListModel*)model
-                      largeIconService:
-                          (nonnull favicon::LargeIconService*)largeIconService
+- (nullable instancetype)
+   initWithModel:(nonnull ReadingListModel*)model
+largeIconService:(nonnull favicon::LargeIconService*)largeIconService
+ listItemFactory:(nonnull ReadingListListItemFactory*)itemFactory
     NS_DESIGNATED_INITIALIZER;
 
 // Returns the entry corresponding to the |item|. The item should be of type
 // ReadingListCollectionViewItem. Returns nullptr if there is no corresponding
 // entry.
 - (nullable const ReadingListEntry*)entryFromItem:
-    (nonnull CollectionViewItem*)item;
+    (nonnull id<ReadingListListItem>)item;
 
 // Marks the entry with |URL| as read.
 - (void)markEntryRead:(const GURL&)URL;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
index 71d77155..4b255b7 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
@@ -16,7 +16,10 @@
 #import "ios/chrome/browser/ui/favicon/favicon_attributes_provider.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_utils.h"
 #import "ios/chrome/common/favicon/favicon_view.h"
 
@@ -25,6 +28,7 @@
 #endif
 
 namespace {
+// Sorter function that orders ReadingListEntries by their update time.
 bool EntrySorter(const ReadingListEntry* rhs, const ReadingListEntry* lhs) {
   return rhs->UpdateTime() > lhs->UpdateTime();
 }
@@ -35,10 +39,15 @@
   std::unique_ptr<ReadingListModel::ScopedReadingListBatchUpdate> _batchToken;
 }
 
+// The model passed on initialization.
 @property(nonatomic, assign) ReadingListModel* model;
 
+// Whether the consumer should be notified of model changes.
 @property(nonatomic, assign) BOOL shouldMonitorModel;
 
+// The ListItem factory passed on initialization.
+@property(nonatomic, strong) ReadingListListItemFactory* itemFactory;
+
 // Lazily instantiated.
 @property(nonatomic, strong, readonly)
     FaviconAttributesProvider* attributesProvider;
@@ -50,20 +59,23 @@
 
 @implementation ReadingListMediator
 
-@synthesize model = _model;
 @synthesize dataSink = _dataSink;
+@synthesize model = _model;
 @synthesize shouldMonitorModel = _shouldMonitorModel;
+@synthesize itemFactory = _itemFactory;
 @synthesize attributesProvider = _attributesProvider;
 @synthesize largeIconService = _largeIconService;
 
 #pragma mark - Public
 
 - (instancetype)initWithModel:(ReadingListModel*)model
-             largeIconService:(favicon::LargeIconService*)largeIconService {
+             largeIconService:(favicon::LargeIconService*)largeIconService
+              listItemFactory:(ReadingListListItemFactory*)itemFactory {
   self = [super init];
   if (self) {
     _model = model;
     _largeIconService = largeIconService;
+    _itemFactory = itemFactory;
     _shouldMonitorModel = YES;
 
     // This triggers the callback method. Should be created last.
@@ -72,10 +84,8 @@
   return self;
 }
 
-- (const ReadingListEntry*)entryFromItem:(CollectionViewItem*)item {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
-  return self.model->GetEntryByURL(readingListItem.entryURL);
+- (const ReadingListEntry*)entryFromItem:(id<ReadingListListItem>)item {
+  return self.model->GetEntryByURL(item.entryURL);
 }
 
 - (void)markEntryRead:(const GURL&)URL {
@@ -84,11 +94,9 @@
 
 #pragma mark - ReadingListDataSource
 
-- (BOOL)isEntryRead:(CollectionViewItem*)item {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
+- (BOOL)isItemRead:(id<ReadingListListItem>)item {
   const ReadingListEntry* readingListEntry =
-      self.model->GetEntryByURL(readingListItem.entryURL);
+      self.model->GetEntryByURL(item.entryURL);
 
   if (!readingListEntry) {
     return NO;
@@ -103,27 +111,21 @@
   self.dataSink = nil;
 }
 
-- (void)setReadStatus:(BOOL)read forItem:(CollectionViewItem*)item {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
-  self.model->SetReadStatus(readingListItem.entryURL, read);
+- (void)setReadStatus:(BOOL)read forItem:(id<ReadingListListItem>)item {
+  self.model->SetReadStatus(item.entryURL, read);
 }
 
 - (const ReadingListEntry*)entryWithURL:(const GURL&)URL {
   return self.model->GetEntryByURL(URL);
 }
 
-- (void)removeEntryFromItem:(CollectionViewItem*)item {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
-  [self logDeletionOfItem:readingListItem];
-  self.model->RemoveEntryByURL(readingListItem.entryURL);
+- (void)removeEntryFromItem:(id<ReadingListListItem>)item {
+  [self logDeletionOfItem:item];
+  self.model->RemoveEntryByURL(item.entryURL);
 }
 
-- (void)fillReadItems:(NSMutableArray<CollectionViewItem*>*)readArray
-                unreadItems:(NSMutableArray<CollectionViewItem*>*)unreadArray
-    withCustomActionFactory:
-        (ReadingListListViewItemCustomActionFactory*)customActionFactory {
+- (void)fillReadItems:(NSMutableArray<id<ReadingListListItem>>*)readArray
+          unreadItems:(NSMutableArray<id<ReadingListListItem>>*)unreadArray {
   std::vector<const ReadingListEntry*> readEntries;
   std::vector<const ReadingListEntry*> unreadEntries;
 
@@ -141,28 +143,23 @@
   std::sort(unreadEntries.begin(), unreadEntries.end(), EntrySorter);
 
   for (const ReadingListEntry* entry : readEntries) {
-    [readArray
-        addObject:[self cellItemForReadingListEntry:entry
-                            withCustomActionFactory:customActionFactory]];
+    [readArray addObject:[self.itemFactory cellItemForReadingListEntry:entry]];
   }
 
   for (const ReadingListEntry* entry : unreadEntries) {
     [unreadArray
-        addObject:[self cellItemForReadingListEntry:entry
-                            withCustomActionFactory:customActionFactory]];
+        addObject:[self.itemFactory cellItemForReadingListEntry:entry]];
   }
 
   DCHECK(self.model->Keys().size() == [readArray count] + [unreadArray count]);
 }
 
-- (void)fetchFaviconForItem:(CollectionViewItem*)item {
-  ReadingListCollectionViewItem* readingListItem =
-      base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item);
-  __weak ReadingListCollectionViewItem* weakItem = readingListItem;
+- (void)fetchFaviconForItem:(id<ReadingListListItem>)item {
+  __weak id<ReadingListListItem> weakItem = item;
   __weak ReadingListMediator* weakSelf = self;
   void (^completionBlock)(FaviconAttributes* attributes) =
       ^(FaviconAttributes* attributes) {
-        ReadingListCollectionViewItem* strongItem = weakItem;
+        id<ReadingListListItem> strongItem = weakItem;
         ReadingListMediator* strongSelf = weakSelf;
         if (!strongSelf || !strongItem) {
           return;
@@ -173,9 +170,8 @@
         [strongSelf.dataSink itemHasChangedAfterDelay:strongItem];
       };
 
-  [self.attributesProvider
-      fetchFaviconAttributesForURL:readingListItem.faviconPageURL
-                        completion:completionBlock];
+  [self.attributesProvider fetchFaviconAttributesForURL:item.faviconPageURL
+                                             completion:completionBlock];
 }
 
 - (void)beginBatchUpdates {
@@ -212,7 +208,7 @@
   }
 }
 
-- (BOOL)ready {
+- (BOOL)isReady {
   return self.model->loaded();
 }
 
@@ -220,7 +216,7 @@
   return self.model->size() > 0;
 }
 
-- (BOOL)hasRead {
+- (BOOL)hasReadElements {
   return self.model->size() != self.model->unread_size();
 }
 
@@ -258,53 +254,11 @@
 
 #pragma mark - Private
 
-// Creates a ReadingListCollectionViewItem from a ReadingListEntry |entry|.
-- (ReadingListCollectionViewItem*)
-cellItemForReadingListEntry:(const ReadingListEntry*)entry
-    withCustomActionFactory:
-        (ReadingListListViewItemCustomActionFactory*)customActionFactory {
-  const GURL& url = entry->URL();
-  ReadingListCollectionViewItem* item =
-      [[ReadingListCollectionViewItem alloc] initWithType:0];
-  item.entryURL = entry->URL();
-  item.faviconPageURL =
-      entry->DistilledURL().is_valid() ? entry->DistilledURL() : url;
-
-  BOOL hasDistillationDetails =
-      entry->DistilledState() == ReadingListEntry::PROCESSED &&
-      entry->DistillationSize() != 0 && entry->DistillationTime() != 0;
-  NSString* title = base::SysUTF8ToNSString(entry->Title());
-  if ([title length]) {
-    item.title = title;
-  } else {
-    item.title =
-        base::SysUTF16ToNSString(url_formatter::FormatUrl(url.GetOrigin()));
-  }
-  int64_t distillationDate =
-      hasDistillationDetails ? entry->DistillationTime() : 0;
-  int64_t distillationSize =
-      hasDistillationDetails ? entry->DistillationSize() : 0;
-  item.distillationDateText =
-      distillationDate > 0
-          ? GetReadingListCellDistillationDateText(distillationDate)
-          : nil;
-  item.distillationSizeText =
-      distillationSize > 0
-          ? GetReadingListCellDistillationSizeText(distillationSize)
-          : nil;
-  item.distillationState =
-      reading_list::UIStatusFromModelStatus(entry->DistilledState());
-  item.customActionFactory = customActionFactory;
-  return item;
-}
-
 // Whether the data source has changed.
 - (BOOL)hasDataSourceChanged {
-  NSMutableArray<CollectionViewItem*>* readArray = [NSMutableArray array];
-  NSMutableArray<CollectionViewItem*>* unreadArray = [NSMutableArray array];
-  [self fillReadItems:readArray
-                  unreadItems:unreadArray
-      withCustomActionFactory:nil];
+  NSMutableArray<id<ReadingListListItem>>* readArray = [NSMutableArray array];
+  NSMutableArray<id<ReadingListListItem>>* unreadArray = [NSMutableArray array];
+  [self fillReadItems:readArray unreadItems:unreadArray];
 
   return [self currentSection:[self.dataSink readItems]
              isDifferentOfArray:readArray] ||
@@ -316,27 +270,25 @@
 // |sectionIdentifier| and those in the |array|. The comparison is done with the
 // URL of the elements. If an element exist in both, the one in |currentSection|
 // will be overwriten with the informations contained in the one from|array|.
-- (BOOL)currentSection:(NSArray<CollectionViewItem*>*)currentSection
-    isDifferentOfArray:(NSArray<CollectionViewItem*>*)array {
+- (BOOL)currentSection:(NSArray<id<ReadingListListItem>>*)currentSection
+    isDifferentOfArray:(NSArray<id<ReadingListListItem>>*)array {
   if (currentSection.count != array.count)
     return YES;
 
-  NSMutableArray<ReadingListCollectionViewItem*>* itemsToReconfigure =
+  NSMutableArray<id<ReadingListListItem>>* itemsToReconfigure =
       [NSMutableArray array];
 
   NSInteger index = 0;
-  for (ReadingListCollectionViewItem* newItem in array) {
-    ReadingListCollectionViewItem* oldItem =
-        base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(
-            currentSection[index]);
+  for (id<ReadingListListItem> newItem in array) {
+    id<ReadingListListItem> oldItem = currentSection[index];
     if (oldItem.entryURL == newItem.entryURL) {
       if (![oldItem isEqual:newItem]) {
+        [itemsToReconfigure addObject:oldItem];
         oldItem.title = newItem.title;
         oldItem.entryURL = newItem.entryURL;
         oldItem.distillationState = newItem.distillationState;
         oldItem.distillationDateText = newItem.distillationDateText;
         oldItem.distillationSizeText = newItem.distillationSizeText;
-        [itemsToReconfigure addObject:oldItem];
       }
       if (oldItem.faviconPageURL != newItem.faviconPageURL) {
         oldItem.faviconPageURL = newItem.faviconPageURL;
@@ -353,7 +305,7 @@
 }
 
 // Logs the deletions histograms for the entry associated with |item|.
-- (void)logDeletionOfItem:(CollectionViewItem*)item {
+- (void)logDeletionOfItem:(id<ReadingListListItem>)item {
   const ReadingListEntry* entry = [self entryFromItem:item];
 
   if (!entry)
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm
index a888055d..f99875a 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm
@@ -14,8 +14,9 @@
 #include "components/url_formatter/url_formatter.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_accessibility_delegate.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -57,9 +58,11 @@
     large_icon_service_.reset(new favicon::LargeIconService(
         &mock_favicon_service_, /*image_fetcher=*/nullptr));
 
-    mediator_ =
-        [[ReadingListMediator alloc] initWithModel:model_.get()
-                                  largeIconService:large_icon_service_.get()];
+    mediator_ = [[ReadingListMediator alloc]
+           initWithModel:model_.get()
+        largeIconService:large_icon_service_.get()
+         listItemFactory:[ReadingListListItemFactory
+                             collectionViewItemFactory]];
   }
 
  protected:
@@ -77,29 +80,18 @@
 
 TEST_F(ReadingListMediatorTest, fillItems) {
   // Setup.
-  NSMutableArray<CollectionViewItem*>* readArray = [NSMutableArray array];
-  NSMutableArray<CollectionViewItem*>* unreadArray = [NSMutableArray array];
-  ReadingListListViewItemCustomActionFactory* customActionFactory =
-      [[ReadingListListViewItemCustomActionFactory alloc] init];
+  NSMutableArray<id<ReadingListListItem>>* readArray = [NSMutableArray array];
+  NSMutableArray<id<ReadingListListItem>>* unreadArray = [NSMutableArray array];
 
   // Action.
-  [mediator_ fillReadItems:readArray
-                  unreadItems:unreadArray
-      withCustomActionFactory:customActionFactory];
+  [mediator_ fillReadItems:readArray unreadItems:unreadArray];
 
   // Tests.
   EXPECT_EQ(3U, [unreadArray count]);
   EXPECT_EQ(2U, [readArray count]);
   NSArray<ReadingListCollectionViewItem*>* rlReadArray = [readArray copy];
   NSArray<ReadingListCollectionViewItem*>* rlUneadArray = [unreadArray copy];
-  EXPECT_TRUE([rlUneadArray[0].title
-      isEqualToString:base::SysUTF16ToNSString(url_formatter::FormatUrl(
-                          no_title_entry_url_.GetOrigin()))]);
+  EXPECT_TRUE([rlUneadArray[0].title isEqualToString:@""]);
   EXPECT_TRUE([rlReadArray[0].title isEqualToString:@"read2"]);
   EXPECT_TRUE([rlReadArray[1].title isEqualToString:@"read1"]);
-  EXPECT_EQ(customActionFactory, rlReadArray[0].customActionFactory);
-  EXPECT_EQ(customActionFactory, rlReadArray[1].customActionFactory);
-  EXPECT_EQ(customActionFactory, rlUneadArray[0].customActionFactory);
-  EXPECT_EQ(customActionFactory, rlUneadArray[1].customActionFactory);
-  EXPECT_EQ(customActionFactory, rlUneadArray[2].customActionFactory);
 }
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h
new file mode 100644
index 0000000..29e91ce
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_TABLE_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_TABLE_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h"
+
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h"
+
+@protocol ReadingListDataSource;
+@protocol ReadingListListViewControllerAudience;
+@protocol ReadingListListViewControllerDelegate;
+
+// View controller that displays reading list items in a table view.
+@interface ReadingListTableViewController
+    : ChromeTableViewController<ReadingListListItemAccessibilityDelegate>
+
+// The delegate.
+@property(nonatomic, weak) id<ReadingListListViewControllerDelegate> delegate;
+// The audience that is interested in whether the table has any items.
+@property(nonatomic, weak) id<ReadingListListViewControllerAudience> audience;
+// The table's data source.
+@property(nonatomic, weak) id<ReadingListDataSource> dataSource;
+
+// Initializers.
+- (instancetype)init NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithTableViewStyle:(UITableViewStyle)style
+                           appBarStyle:
+                               (ChromeTableViewControllerStyle)appBarStyle
+    NS_UNAVAILABLE;
+
+// Prepares this view controller to be dismissed.
+- (void)willBeDismissed;
+
+// Reloads all the data.
+- (void)reloadData;
+
+@end
+#endif  // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
new file mode 100644
index 0000000..2596dee
--- /dev/null
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -0,0 +1,852 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "base/stl_util.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
+#import "ios/chrome/browser/ui/list_model/list_item+Controller.h"
+#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_data_source.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_commands.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_manager.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Types of ListItems used by the reading list UI.
+typedef NS_ENUM(NSInteger, ItemType) {
+  ItemTypeHeader = kItemTypeEnumZero,
+  ItemTypeItem,
+};
+// Identifiers for sections in the reading list.
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierUnread = kSectionIdentifierEnumZero,
+  SectionIdentifierRead,
+};
+// Returns the ReadingListSelectionState corresponding with the provided numbers
+// of read and unread items.
+ReadingListSelectionState GetSelectionStateForSelectedCounts(
+    NSUInteger selected_unread_count,
+    NSUInteger selected_read_count) {
+  if (selected_read_count > 0 && selected_unread_count > 0)
+    return ReadingListSelectionState::READ_AND_UNREAD_ITEMS;
+  if (selected_read_count > 0)
+    return ReadingListSelectionState::ONLY_READ_ITEMS;
+  if (selected_unread_count > 0)
+    return ReadingListSelectionState::ONLY_UNREAD_ITEMS;
+  return ReadingListSelectionState::NONE;
+}
+}  // namespace
+
+@interface ReadingListTableViewController ()<ReadingListDataSink,
+                                             ReadingListToolbarButtonCommands>
+
+// Redefine the model to return ReadingListListItems
+@property(nonatomic, readonly)
+    TableViewModel<TableViewItem<ReadingListListItem>*>* tableViewModel;
+
+// Whether the data source has been modified while in editing mode.
+@property(nonatomic, assign) BOOL dataSourceModifiedWhileEditing;
+// The toolbar button manager.
+@property(nonatomic, strong) ReadingListToolbarButtonManager* toolbarManager;
+// The number of read and unread cells that are currently selected.
+@property(nonatomic, assign) NSUInteger selectedUnreadItemCount;
+@property(nonatomic, assign) NSUInteger selectedReadItemCount;
+// The action sheet used to confirm whether items should be marked as read or
+// unread.
+@property(nonatomic, strong) ActionSheetCoordinator* markConfirmationSheet;
+// The background to use when the table is empty.
+@property(nonatomic, strong) UIView* emptyStateBackgroundView;
+
+@end
+
+@implementation ReadingListTableViewController
+@synthesize delegate = _delegate;
+@synthesize audience = _audience;
+@synthesize dataSource = _dataSource;
+@dynamic tableViewModel;
+@synthesize dataSourceModifiedWhileEditing = _dataSourceModifiedWhileEditing;
+@synthesize toolbarManager = _toolbarManager;
+@synthesize selectedUnreadItemCount = _selectedUnreadItemCount;
+@synthesize selectedReadItemCount = _selectedReadItemCount;
+@synthesize markConfirmationSheet = _markConfirmationSheet;
+@synthesize emptyStateBackgroundView = _emptyStateBackgroundView;
+
+- (instancetype)init {
+  self = [super initWithTableViewStyle:UITableViewStylePlain
+                           appBarStyle:ChromeTableViewControllerStyleNoAppBar];
+  if (self) {
+    _toolbarManager = [[ReadingListToolbarButtonManager alloc] init];
+    _toolbarManager.commandHandler = self;
+    _emptyStateBackgroundView = [[EmptyReadingListBackgroundView alloc] init];
+  }
+  return self;
+}
+
+#pragma mark - Accessors
+
+- (void)setAudience:(id<ReadingListListViewControllerAudience>)audience {
+  if (_audience == audience)
+    return;
+  _audience = audience;
+  BOOL hasItems = self.dataSource.ready && self.dataSource.hasElements;
+  [_audience readingListHasItems:hasItems];
+}
+
+- (void)setDataSource:(id<ReadingListDataSource>)dataSource {
+  if (_dataSource == dataSource)
+    return;
+  _dataSource.dataSink = nil;
+  _dataSource = dataSource;
+  _dataSource.dataSink = self;
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  if (self.editing == editing)
+    return;
+  [super setEditing:editing animated:animated];
+  self.selectedUnreadItemCount = 0;
+  self.selectedReadItemCount = 0;
+  [self updateToolbarItems];
+}
+
+- (void)setSelectedUnreadItemCount:(NSUInteger)selectedUnreadItemCount {
+  if (_selectedUnreadItemCount == selectedUnreadItemCount)
+    return;
+  BOOL hadSelectedUnreadItems = _selectedUnreadItemCount > 0;
+  _selectedUnreadItemCount = selectedUnreadItemCount;
+  if ((_selectedUnreadItemCount > 0) != hadSelectedUnreadItems)
+    [self updateToolbarItems];
+}
+
+- (void)setSelectedReadItemCount:(NSUInteger)selectedReadItemCount {
+  if (_selectedReadItemCount == selectedReadItemCount)
+    return;
+  BOOL hadSelectedReadItems = _selectedReadItemCount > 0;
+  _selectedReadItemCount = selectedReadItemCount;
+  if ((_selectedReadItemCount > 0) != hadSelectedReadItems)
+    [self updateToolbarItems];
+}
+
+- (void)setMarkConfirmationSheet:
+    (ActionSheetCoordinator*)markConfirmationSheet {
+  if (_markConfirmationSheet == markConfirmationSheet)
+    return;
+  [_markConfirmationSheet stop];
+  _markConfirmationSheet = markConfirmationSheet;
+}
+
+#pragma mark - Public
+
+- (void)reloadData {
+  [self loadModel];
+  if (self.viewLoaded)
+    [self.tableView reloadData];
+}
+
+- (void)willBeDismissed {
+  [self.dataSource dataSinkWillBeDismissed];
+  self.markConfirmationSheet = nil;
+}
+
++ (NSString*)accessibilityIdentifier {
+  return @"ReadingListTableView";
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.title = l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_READING_LIST);
+
+  self.tableView.accessibilityIdentifier =
+      [[self class] accessibilityIdentifier];
+  self.tableView.estimatedRowHeight = 56;
+  self.tableView.rowHeight = UITableViewAutomaticDimension;
+  self.tableView.estimatedSectionHeaderHeight = 56;
+  self.tableView.allowsMultipleSelectionDuringEditing = YES;
+  self.tableView.allowsMultipleSelection = YES;
+
+  // Add gesture recognizer for the context menu.
+  UILongPressGestureRecognizer* longPressRecognizer =
+      [[UILongPressGestureRecognizer alloc]
+          initWithTarget:self
+                  action:@selector(handleLongPress:)];
+  [self.tableView addGestureRecognizer:longPressRecognizer];
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  if (self.editing) {
+    // Update the selected item counts and the toolbar buttons.
+    NSInteger sectionID =
+        [self.tableViewModel sectionIdentifierForSection:indexPath.section];
+    if (sectionID == SectionIdentifierUnread)
+      self.selectedUnreadItemCount++;
+    if (sectionID == SectionIdentifierRead)
+      self.selectedReadItemCount++;
+  } else {
+    // Open the URL.
+    id<ReadingListListItem> item =
+        [self.tableViewModel itemAtIndexPath:indexPath];
+    [self.delegate readingListListViewController:self openItem:item];
+  }
+}
+
+- (void)tableView:(UITableView*)tableView
+    didDeselectRowAtIndexPath:(NSIndexPath*)indexPath {
+  if (self.editing) {
+    // Update the selected item counts and the toolbar buttons.
+    NSInteger sectionID =
+        [self.tableViewModel sectionIdentifierForSection:indexPath.section];
+    if (sectionID == SectionIdentifierUnread)
+      self.selectedUnreadItemCount--;
+    if (sectionID == SectionIdentifierRead)
+      self.selectedReadItemCount--;
+  }
+}
+
+- (BOOL)tableView:(UITableView*)tableView
+    canEditRowAtIndexPath:(NSIndexPath*)indexPath {
+  return [self.tableViewModel itemAtIndexPath:indexPath].type == ItemTypeItem;
+}
+
+#pragma mark - ChromeTableViewController
+
+- (void)loadModel {
+  [super loadModel];
+  self.dataSourceModifiedWhileEditing = NO;
+
+  if (self.dataSource.hasElements) {
+    [self loadItems];
+    [self.audience readingListHasItems:YES];
+    self.tableView.alwaysBounceVertical = YES;
+    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
+    self.tableView.backgroundView = nil;
+  } else {
+    [self tableIsEmpty];
+  }
+}
+
+#pragma mark - ReadingListDataSink
+
+- (void)dataSourceReady:(id<ReadingListDataSource>)dataSource {
+  [self reloadData];
+}
+
+- (void)dataSourceChanged {
+  // If we are editing and monitoring the model updates, set a flag to reload
+  // the data at the end of the editing.
+  if (self.editing) {
+    self.dataSourceModifiedWhileEditing = YES;
+  } else {
+    [self reloadData];
+  }
+}
+
+- (NSArray<id<ReadingListListItem>>*)readItems {
+  return [self itemsForSection:SectionIdentifierRead];
+}
+
+- (NSArray<id<ReadingListListItem>>*)unreadItems {
+  return [self itemsForSection:SectionIdentifierUnread];
+}
+
+- (void)itemHasChangedAfterDelay:(id<ReadingListListItem>)item {
+  TableViewItem<ReadingListListItem>* tableItem =
+      [self tableItemForReadingListItem:item];
+  if ([self.tableViewModel hasItem:tableItem])
+    [self reconfigureCellsForItems:@[ tableItem ]];
+}
+
+- (void)itemsHaveChanged:(NSArray<ListItem*>*)items {
+  [self reconfigureCellsForItems:items];
+}
+
+#pragma mark - ReadingListDataSink Helpers
+
+// Returns the items for the |sectionID|.
+- (NSArray<id<ReadingListListItem>>*)itemsForSection:
+    (SectionIdentifier)sectionID {
+  TableViewModel* model = self.tableViewModel;
+  return [model hasSectionForSectionIdentifier:sectionID]
+             ? [model itemsInSectionWithIdentifier:sectionID]
+             : nil;
+}
+
+#pragma mark - ReadingListListItemAccessibilityDelegate
+
+- (BOOL)isItemRead:(id<ReadingListListItem>)item {
+  return [self.dataSource isItemRead:item];
+}
+
+- (void)deleteItem:(id<ReadingListListItem>)item {
+  TableViewModel* model = self.tableViewModel;
+  TableViewItem* tableViewItem = base::mac::ObjCCastStrict<TableViewItem>(item);
+  if ([model hasItem:tableViewItem])
+    [self deleteItemsAtIndexPaths:@[ [model indexPathForItem:tableViewItem] ]];
+}
+
+- (void)openItemInNewTab:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                              openItemInNewTab:item
+                                     incognito:NO];
+}
+
+- (void)openItemInNewIncognitoTab:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                              openItemInNewTab:item
+                                     incognito:YES];
+}
+
+- (void)openItemOffline:(id<ReadingListListItem>)item {
+  [self.delegate readingListListViewController:self
+                       openItemOfflineInNewTab:item];
+}
+
+- (void)markItemRead:(id<ReadingListListItem>)item {
+  TableViewModel* model = self.tableViewModel;
+  TableViewItem* tableViewItem = base::mac::ObjCCastStrict<TableViewItem>(item);
+  if ([model hasItem:tableViewItem
+          inSectionWithIdentifier:SectionIdentifierUnread]) {
+    [self markItemsAtIndexPaths:@[ [model indexPathForItem:tableViewItem] ]
+                 withReadStatus:YES];
+  }
+}
+
+- (void)markItemUnread:(id<ReadingListListItem>)item {
+  TableViewModel* model = self.tableViewModel;
+  TableViewItem* tableViewItem = base::mac::ObjCCastStrict<TableViewItem>(item);
+  if ([model hasItem:tableViewItem
+          inSectionWithIdentifier:SectionIdentifierRead]) {
+    [self markItemsAtIndexPaths:@[ [model indexPathForItem:tableViewItem] ]
+                 withReadStatus:NO];
+  }
+}
+
+#pragma mark - ReadingListToolbarButtonCommands
+
+- (void)enterReadingListEditMode {
+  if (self.editing)
+    return;
+  [self setEditing:YES animated:YES];
+}
+
+- (void)exitReadingListEditMode {
+  if (!self.editing)
+    return;
+  [self exitEditingModeAnimated:YES];
+}
+
+- (void)deleteAllReadReadingListItems {
+  base::RecordAction(base::UserMetricsAction("MobileReadingListDeleteRead"));
+  if (![self hasItemInSection:SectionIdentifierRead]) {
+    [self exitEditingModeAnimated:YES];
+    return;
+  }
+
+  // Delete the items in the data source and exit editing mode.
+  ReadingListListItemUpdater updater = ^(id<ReadingListListItem> item) {
+    [self.dataSource removeEntryFromItem:item];
+  };
+  [self updateItemsInSection:SectionIdentifierRead withItemUpdater:updater];
+  [self exitEditingModeAnimated:YES];
+
+  // Update the model and table view for the deleted items.
+  UITableView* tableView = self.tableView;
+  TableViewModel* model = self.tableViewModel;
+  void (^updates)(void) = ^{
+    NSInteger sectionIndex =
+        [model sectionForSectionIdentifier:SectionIdentifierRead];
+    [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
+             withRowAnimation:UITableViewRowAnimationFade];
+    [model removeSectionWithIdentifier:SectionIdentifierRead];
+  };
+  void (^completion)(BOOL) = ^(BOOL) {
+    [self batchEditDidFinish];
+  };
+  [self performBatchTableViewUpdates:updates completion:completion];
+}
+
+- (void)deleteSelectedReadingListItems {
+  [self deleteItemsAtIndexPaths:self.tableView.indexPathsForSelectedRows];
+  [self exitEditingModeAnimated:YES];
+}
+
+- (void)markSelectedReadingListItemsRead {
+  [self markItemsAtIndexPaths:self.tableView.indexPathsForSelectedRows
+               withReadStatus:YES];
+}
+
+- (void)markSelectedReadingListItemsUnread {
+  [self markItemsAtIndexPaths:self.tableView.indexPathsForSelectedRows
+               withReadStatus:NO];
+}
+
+- (void)markSelectedReadingListItemsAfterConfirmation {
+  [self initializeMarkConfirmationSheet];
+  __weak ReadingListTableViewController* weakSelf = self;
+  __weak NSArray<NSIndexPath*>* weakSelectedIndexPaths =
+      self.tableView.indexPathsForSelectedRows;
+  NSString* markAsReadTitle =
+      l10n_util::GetNSStringWithFixup(IDS_IOS_READING_LIST_MARK_READ_BUTTON);
+  [self.markConfirmationSheet
+      addItemWithTitle:markAsReadTitle
+                action:^{
+                  [weakSelf markItemsAtIndexPaths:weakSelectedIndexPaths
+                                   withReadStatus:YES];
+                  weakSelf.markConfirmationSheet = nil;
+                }
+                 style:UIAlertActionStyleDefault];
+  NSString* markAsUnreadTitle =
+      l10n_util::GetNSStringWithFixup(IDS_IOS_READING_LIST_MARK_UNREAD_BUTTON);
+  [self.markConfirmationSheet
+      addItemWithTitle:markAsUnreadTitle
+                action:^{
+                  [weakSelf markItemsAtIndexPaths:weakSelectedIndexPaths
+                                   withReadStatus:NO];
+                  weakSelf.markConfirmationSheet = nil;
+                }
+                 style:UIAlertActionStyleDefault];
+  [self.markConfirmationSheet start];
+}
+
+- (void)markAllReadingListItemsAfterConfirmation {
+  [self initializeMarkConfirmationSheet];
+  __weak ReadingListTableViewController* weakSelf = self;
+  NSString* markAsReadTitle = l10n_util::GetNSStringWithFixup(
+      IDS_IOS_READING_LIST_MARK_ALL_READ_ACTION);
+  [self.markConfirmationSheet
+      addItemWithTitle:markAsReadTitle
+                action:^{
+                  [weakSelf markItemsInSection:SectionIdentifierUnread
+                                withReadStatus:YES];
+                  weakSelf.markConfirmationSheet = nil;
+                }
+                 style:UIAlertActionStyleDefault];
+  NSString* markAsUnreadTitle = l10n_util::GetNSStringWithFixup(
+      IDS_IOS_READING_LIST_MARK_ALL_UNREAD_ACTION);
+  [self.markConfirmationSheet
+      addItemWithTitle:markAsUnreadTitle
+                action:^{
+                  [weakSelf markItemsInSection:SectionIdentifierRead
+                                withReadStatus:NO];
+                  weakSelf.markConfirmationSheet = nil;
+                }
+                 style:UIAlertActionStyleDefault];
+  [self.markConfirmationSheet start];
+}
+
+#pragma mark - ReadingListToolbarButtonCommands Helpers
+
+// Creates a confirmation action sheet for the "Mark" toolbar button item.
+- (void)initializeMarkConfirmationSheet {
+  self.markConfirmationSheet =
+      [self.toolbarManager markButtonConfirmationWithBaseViewController:self];
+
+  [self.markConfirmationSheet
+      addItemWithTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL)
+                action:nil
+                 style:UIAlertActionStyleCancel];
+}
+
+#pragma mark - Item Loading Helpers
+
+// Uses self.dataSource to load the TableViewItems into self.tableViewModel.
+- (void)loadItems {
+  NSMutableArray<id<ReadingListListItem>>* readArray = [NSMutableArray array];
+  NSMutableArray<id<ReadingListListItem>>* unreadArray = [NSMutableArray array];
+  [self.dataSource fillReadItems:readArray unreadItems:unreadArray];
+  [self loadItemsFromArray:unreadArray toSection:SectionIdentifierUnread];
+  [self loadItemsFromArray:readArray toSection:SectionIdentifierRead];
+
+  [self updateToolbarItems];
+}
+
+// Adds |items| to self.tableViewModel for the section designated by
+// |sectionID|.
+- (void)loadItemsFromArray:(NSArray<id<ReadingListListItem>>*)items
+                 toSection:(SectionIdentifier)sectionID {
+  if (!items.count)
+    return;
+
+  TableViewModel* model = self.tableViewModel;
+  [model addSectionWithIdentifier:sectionID];
+  [model setHeader:[self headerForSection:sectionID]
+      forSectionWithIdentifier:sectionID];
+  for (TableViewItem<ReadingListListItem>* item in items) {
+    item.type = ItemTypeItem;
+    [self.dataSource fetchFaviconForItem:item];
+    [model addItem:item toSectionWithIdentifier:sectionID];
+  }
+}
+
+// Returns a TableViewTextItem that displays the title for the section
+// designated by |sectionID|.
+- (TableViewHeaderFooterItem*)headerForSection:(SectionIdentifier)sectionID {
+  TableViewTextHeaderFooterItem* header =
+      [[TableViewTextHeaderFooterItem alloc] initWithType:ItemTypeHeader];
+
+  switch (sectionID) {
+    case SectionIdentifierRead:
+      header.text = l10n_util::GetNSString(IDS_IOS_READING_LIST_READ_HEADER);
+      break;
+    case SectionIdentifierUnread:
+      header.text = l10n_util::GetNSString(IDS_IOS_READING_LIST_UNREAD_HEADER);
+      break;
+  }
+  return header;
+}
+
+#pragma mark - Toolbar Helpers
+
+// Updates buttons displayed in the bottom toolbar.
+- (void)updateToolbarItems {
+  self.toolbarManager.editing = self.tableView.editing;
+  self.toolbarManager.hasReadItems =
+      self.dataSource.hasElements && self.dataSource.hasReadElements;
+  self.toolbarManager.selectionState = GetSelectionStateForSelectedCounts(
+      self.selectedUnreadItemCount, self.selectedReadItemCount);
+  if (self.toolbarManager.buttonItemsUpdated)
+    [self setToolbarItems:[self.toolbarManager buttonItems] animated:YES];
+}
+
+#pragma mark - Item Editing Helpers
+
+// Returns |item| cast as a TableViewItem.
+- (TableViewItem<ReadingListListItem>*)tableItemForReadingListItem:
+    (id<ReadingListListItem>)item {
+  return base::mac::ObjCCastStrict<TableViewItem<ReadingListListItem>>(item);
+}
+
+// Applies |updater| to the items in |section|. The updates are done in reverse
+// order of the cells in the section to keep the order. Monitoring of the
+// data source updates are suspended during this time.
+- (void)updateItemsInSection:(SectionIdentifier)section
+             withItemUpdater:(ReadingListListItemUpdater)updater {
+  DCHECK(updater);
+  [self.dataSource beginBatchUpdates];
+  NSArray* items = [self.tableViewModel itemsInSectionWithIdentifier:section];
+  // Read the objects in reverse order to keep the order (last modified first).
+  for (id<ReadingListListItem> item in [items reverseObjectEnumerator]) {
+    updater(item);
+  }
+  [self.dataSource endBatchUpdates];
+}
+
+// Applies |updater| to the items in |indexPaths|. The updates are done in
+// reverse order |indexPaths| to keep the order. The monitoring of the data
+// source updates are suspended during this time.
+- (void)updateItemsAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths
+                withItemUpdater:(ReadingListListItemUpdater)updater {
+  DCHECK(updater);
+  [self.dataSource beginBatchUpdates];
+  // Read the objects in reverse order to keep the order (last modified first).
+  for (NSIndexPath* indexPath in [indexPaths reverseObjectEnumerator]) {
+    updater([self.tableViewModel itemAtIndexPath:indexPath]);
+  }
+  [self.dataSource endBatchUpdates];
+}
+
+// Moves all the items from |fromSection| to |toSection| and removes the empty
+// section from the collection.
+- (void)moveItemsFromSection:(SectionIdentifier)fromSection
+                   toSection:(SectionIdentifier)toSection {
+  NSInteger sourceSection =
+      [self.tableViewModel sectionForSectionIdentifier:fromSection];
+  NSInteger itemCount =
+      [self.tableViewModel numberOfItemsInSection:sourceSection];
+
+  NSMutableArray* sortedIndexPaths = [NSMutableArray array];
+  for (NSInteger row = 0; row < itemCount; ++row) {
+    NSIndexPath* itemPath =
+        [NSIndexPath indexPathForRow:row inSection:sourceSection];
+    [sortedIndexPaths addObject:itemPath];
+  }
+
+  [self moveItemsAtIndexPaths:sortedIndexPaths toSection:toSection];
+}
+
+// Moves the items at |sortedIndexPaths| to |toSection|, removing any empty
+// sections.
+- (void)moveItemsAtIndexPaths:(NSArray*)sortedIndexPaths
+                    toSection:(SectionIdentifier)toSection {
+  // Reconfigure cells, allowing the custom actions to be updated.
+  for (NSIndexPath* indexPath in sortedIndexPaths) {
+    [[self.tableViewModel itemAtIndexPath:indexPath]
+        configureCell:[self.tableView cellForRowAtIndexPath:indexPath]
+           withStyler:self.styler];
+  }
+
+  NSInteger sectionCreatedIndex = [self initializeTableViewSection:toSection];
+  void (^updates)(void) = ^{
+    NSInteger sectionIndex =
+        [self.tableViewModel sectionForSectionIdentifier:toSection];
+
+    NSInteger newItemIndex = 0;
+    for (NSIndexPath* indexPath in sortedIndexPaths) {
+      // The |sortedIndexPaths| is a copy of the index paths before the
+      // destination section has been added if necessary. The section part of
+      // the index potentially needs to be updated.
+      NSInteger updatedSection = indexPath.section;
+      if (updatedSection >= sectionCreatedIndex)
+        updatedSection++;
+      if (updatedSection == sectionIndex) {
+        // The item is already in the targeted section, there is no need to move
+        // it.
+        continue;
+      }
+
+      NSIndexPath* updatedIndexPath =
+          [NSIndexPath indexPathForItem:indexPath.row inSection:updatedSection];
+      NSIndexPath* indexPathForModel =
+          [NSIndexPath indexPathForItem:indexPath.item - newItemIndex
+                              inSection:updatedSection];
+
+      // Index of the item in the new section. The newItemIndex is the index of
+      // this item in the targeted section.
+      NSIndexPath* newIndexPath =
+          [NSIndexPath indexPathForItem:newItemIndex++ inSection:sectionIndex];
+
+      [self moveItemWithModelIndex:indexPathForModel
+                    tableViewIndex:updatedIndexPath
+                           toIndex:newIndexPath];
+    }
+  };
+  void (^completion)(BOOL) = ^(BOOL) {
+    [self batchEditDidFinish];
+  };
+  [self performBatchTableViewUpdates:updates completion:completion];
+}
+
+// Moves the ListItem within self.tableViewModel at |modelIndex| and the
+// UITableViewCell at |tableViewIndex| to |toIndexPath|.
+- (void)moveItemWithModelIndex:(NSIndexPath*)modelIndex
+                tableViewIndex:(NSIndexPath*)tableViewIndex
+                       toIndex:(NSIndexPath*)toIndexPath {
+  TableViewModel* model = self.tableViewModel;
+  TableViewItem* item = [model itemAtIndexPath:modelIndex];
+
+  // Move the item in |model|.
+  [self deleteItemAtIndexPathFromModel:modelIndex];
+  NSInteger toSectionID =
+      [model sectionIdentifierForSection:toIndexPath.section];
+  [model insertItem:item
+      inSectionWithIdentifier:toSectionID
+                      atIndex:toIndexPath.row];
+
+  // Move the cells in the table view.
+  [self.tableView moveRowAtIndexPath:tableViewIndex toIndexPath:toIndexPath];
+}
+
+// Makes sure the table view section with |sectionID| exists with the correct
+// header. Returns the index of the new section in the table view, or
+// NSIntegerMax if no section has been created.
+- (NSInteger)initializeTableViewSection:(SectionIdentifier)sectionID {
+  TableViewModel* model = self.tableViewModel;
+  if ([model hasSectionForSectionIdentifier:sectionID])
+    return NSIntegerMax;
+
+  // There are at most two sections in the table.  The only time this creation
+  // will result in the index of 1 is while creating the read section when there
+  // are also unread items.
+  BOOL hasUnreadItems = [self hasItemInSection:SectionIdentifierUnread];
+  BOOL creatingReadSection = (sectionID == SectionIdentifierRead);
+  NSInteger sectionIndex = (hasUnreadItems && creatingReadSection) ? 1 : 0;
+
+  void (^updates)(void) = ^{
+    [model insertSectionWithIdentifier:sectionID atIndex:sectionIndex];
+    [model setHeader:[self headerForSection:sectionID]
+        forSectionWithIdentifier:sectionID];
+    [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
+                  withRowAnimation:UITableViewRowAnimationFade];
+  };
+  [self performBatchTableViewUpdates:updates completion:nil];
+
+  return sectionIndex;
+}
+
+// Whether the model has items in |sectionID|.
+- (BOOL)hasItemInSection:(SectionIdentifier)sectionID {
+  return [self itemsForSection:sectionID].count > 0;
+}
+
+// Deletes the items at |indexPaths|.
+- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths {
+  // Delete the items in the data source and exit editing mode.
+  ReadingListListItemUpdater updater = ^(id<ReadingListListItem> item) {
+    [self.dataSource removeEntryFromItem:item];
+  };
+  [self updateItemsAtIndexPaths:indexPaths withItemUpdater:updater];
+  [self exitEditingModeAnimated:YES];
+
+  // Update the model and table view for the deleted items.
+  UITableView* tableView = self.tableView;
+  NSArray* sortedIndexPaths =
+      [indexPaths sortedArrayUsingSelector:@selector(compare:)];
+  void (^updates)(void) = ^{
+    // Enumerate in reverse order to delete the items from the model.
+    for (NSIndexPath* indexPath in [sortedIndexPaths reverseObjectEnumerator]) {
+      [self deleteItemAtIndexPathFromModel:indexPath];
+    }
+    [tableView deleteRowsAtIndexPaths:indexPaths
+                     withRowAnimation:UITableViewRowAnimationFade];
+  };
+  void (^completion)(BOOL) = ^(BOOL) {
+    [self batchEditDidFinish];
+  };
+  [self performBatchTableViewUpdates:updates completion:completion];
+}
+
+// Deletes the ListItem corresponding to |indexPath| in the model.
+- (void)deleteItemAtIndexPathFromModel:(NSIndexPath*)indexPath {
+  TableViewModel* model = self.tableViewModel;
+  NSInteger sectionID = [model sectionIdentifierForSection:indexPath.section];
+  NSInteger itemType = [model itemTypeForIndexPath:indexPath];
+  NSUInteger index = [model indexInItemTypeForIndexPath:indexPath];
+  [model removeItemWithType:itemType
+      fromSectionWithIdentifier:sectionID
+                        atIndex:index];
+}
+
+// Marks all the items at |indexPaths| as read or unread depending on |read|.
+- (void)markItemsAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths
+               withReadStatus:(BOOL)read {
+  // Record metric.
+  base::RecordAction(base::UserMetricsAction(
+      read ? "MobileReadingListMarkRead" : "MobileReadingListMarkUnread"));
+
+  // Mark the items as |read| and exit editing.
+  ReadingListListItemUpdater updater = ^(id<ReadingListListItem> item) {
+    [self.dataSource setReadStatus:read forItem:item];
+  };
+  NSArray* sortedIndexPaths =
+      [indexPaths sortedArrayUsingSelector:@selector(compare:)];
+  [self updateItemsAtIndexPaths:sortedIndexPaths withItemUpdater:updater];
+  [self exitEditingModeAnimated:YES];
+
+  // Move the items to the appropriate section.
+  SectionIdentifier toSection =
+      read ? SectionIdentifierRead : SectionIdentifierUnread;
+  [self moveItemsAtIndexPaths:sortedIndexPaths toSection:toSection];
+}
+
+// Marks items from |section| with as read or unread dending on |read|.
+- (void)markItemsInSection:(SectionIdentifier)section
+            withReadStatus:(BOOL)read {
+  // Mark the items as |read| and exit editing.
+  ReadingListListItemUpdater updater = ^(id<ReadingListListItem> item) {
+    [self.dataSource setReadStatus:read forItem:item];
+  };
+  [self updateItemsInSection:section withItemUpdater:updater];
+  [self exitEditingModeAnimated:YES];
+
+  // Move the items to the appropriate section.
+  SectionIdentifier toSection =
+      read ? SectionIdentifierRead : SectionIdentifierUnread;
+  [self moveItemsFromSection:section toSection:toSection];
+}
+
+// Cleanup function called in the completion block of editing operations.
+- (void)batchEditDidFinish {
+  // Reload the items if the datasource was modified during the edit.
+  if (self.dataSourceModifiedWhileEditing)
+    [self reloadData];
+  // Remove any newly emptied sections.
+  [self removeEmptySections];
+}
+
+// Removes the empty sections from the table and the model.
+- (void)removeEmptySections {
+  UITableView* tableView = self.tableView;
+  TableViewModel* model = self.tableViewModel;
+  void (^updates)(void) = ^{
+    SectionIdentifier sections[] = {SectionIdentifierRead,
+                                    SectionIdentifierUnread};
+    for (size_t i = 0; i < base::size(sections); ++i) {
+      SectionIdentifier section = sections[i];
+
+      if ([model hasSectionForSectionIdentifier:section] &&
+          ![self hasItemInSection:section]) {
+        // If |section| has no items, remove it from the model and the table
+        // view.
+        NSInteger sectionIndex = [model sectionForSectionIdentifier:section];
+        [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
+                 withRowAnimation:UITableViewRowAnimationFade];
+        [model removeSectionWithIdentifier:section];
+      }
+    }
+  };
+  [self performBatchTableViewUpdates:updates completion:nil];
+
+  if (!self.dataSource.hasElements)
+    [self tableIsEmpty];
+  else
+    [self updateToolbarItems];
+}
+
+// Resets self.editing to NO, optionally with animation.
+- (void)exitEditingModeAnimated:(BOOL)animated {
+  self.markConfirmationSheet = nil;
+  [self setEditing:NO animated:animated];
+  [self updateToolbarItems];
+}
+
+#pragma mark - Emtpy Table Helpers
+
+// Called when the table is empty.
+- (void)tableIsEmpty {
+  if (self.tableView.backgroundView == self.emptyStateBackgroundView)
+    return;
+  self.tableView.alwaysBounceVertical = NO;
+  self.tableView.backgroundView = self.emptyStateBackgroundView;
+  self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+  [self.audience readingListHasItems:NO];
+}
+
+#pragma mark - Gesture Helpers
+
+// Shows the context menu for a long press from |recognizer|.
+- (void)handleLongPress:(UILongPressGestureRecognizer*)recognizer {
+  if (self.editing || recognizer.state != UIGestureRecognizerStateBegan)
+    return;
+
+  CGPoint location = [recognizer locationOfTouch:0 inView:self.tableView];
+  NSIndexPath* indexPath = [self.tableView indexPathForRowAtPoint:location];
+  if (!indexPath)
+    return;
+
+  if (![self.tableViewModel hasItemAtIndexPath:indexPath])
+    return;
+
+  TableViewItem<ReadingListListItem>* item =
+      [self.tableViewModel itemAtIndexPath:indexPath];
+  if (item.type != ItemTypeItem)
+    return;
+
+  [self.delegate readingListListViewController:self
+                     displayContextMenuForItem:item
+                                       atPoint:location];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
index 6488429..0014184 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_item.mm
@@ -9,8 +9,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_custom_action_factory.h"
-#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_item_util.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
 #include "ios/chrome/browser/ui/ui_util.h"
@@ -108,9 +108,7 @@
       self.title, base::SysUTF8ToNSString(self.entryURL.host()),
       self.distillationState);
   cell.accessibilityCustomActions =
-      [self.customActionFactory customActionsForItem:self
-                                             withURL:self.entryURL
-                                  distillationStatus:self.distillationState];
+      [self.customActionFactory customActionsForItem:self];
 }
 
 #pragma mark - NSObject
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h
index 7584304..3c4ce7e 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h
+++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.h
@@ -8,7 +8,7 @@
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 
 @class ReadingListCollectionViewController;
-@protocol ReadingListCollectionViewControllerDelegate;
+@protocol ReadingListListViewControllerDelegate;
 
 // Container for the ReadingList Collection View Controller and the toolbar. It
 // handles the interactions between the two.
@@ -25,8 +25,7 @@
 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
 - (instancetype)init NS_UNAVAILABLE;
 
-@property(nonatomic, weak) id<ReadingListCollectionViewControllerDelegate>
-    delegate;
+@property(nonatomic, weak) id<ReadingListListViewControllerDelegate> delegate;
 
 @end
 
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
index 27f1359..a0bee46 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
@@ -8,6 +8,8 @@
 
 #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h"
+#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h"
 #import "ios/chrome/common/ui_util/constraints_ui_util.h"
 
@@ -22,9 +24,8 @@
 };
 }
 
-@interface ReadingListViewController ()<
-    ReadingListToolbarActions,
-    ReadingListCollectionViewControllerAudience>
+@interface ReadingListViewController ()<ReadingListToolbarActions,
+                                        ReadingListListViewControllerAudience>
 
 @property(nonatomic, strong, readonly)
     ReadingListCollectionViewController* readingListCollectionViewController;
@@ -86,7 +87,7 @@
 #pragma mark UIAccessibilityAction
 
 - (BOOL)accessibilityPerformEscape {
-  [self.delegate dismissReadingListCollectionViewController:
+  [self.delegate dismissReadingListListViewController:
                      self.readingListCollectionViewController];
   return YES;
 }
@@ -113,7 +114,7 @@
   [self.readingListCollectionViewController exitEditingModePressed];
 }
 
-#pragma mark - ReadingListCollectionViewControllerAudience
+#pragma mark - ReadingListListViewControllerAudience
 
 - (void)readingListHasItems:(BOOL)hasItems {
   if (hasItems) {
@@ -140,15 +141,13 @@
 
 - (NSArray*)keyCommands {
   __weak ReadingListViewController* weakSelf = self;
-  return @[ [UIKeyCommand
-      cr_keyCommandWithInput:UIKeyInputEscape
-               modifierFlags:Cr_UIKeyModifierNone
-                       title:nil
-                      action:^{
-                        [weakSelf.delegate
-                            dismissReadingListCollectionViewController:
-                                weakSelf.readingListCollectionViewController];
-                      }] ];
+  return
+      @[ [UIKeyCommand cr_keyCommandWithInput:UIKeyInputEscape
+                                modifierFlags:Cr_UIKeyModifierNone
+                                        title:nil
+                                       action:^{
+                                         [weakSelf accessibilityPerformEscape];
+                                       }] ];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
index 9a7bbfb..3ef6614 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -104,7 +104,6 @@
 @interface RecentTabsTableViewController ()<SigninPromoViewConsumer,
                                             SigninPresenter,
                                             SyncPresenter,
-                                            TextButtonItemDelegate,
                                             UIGestureRecognizerDelegate> {
   std::unique_ptr<synced_sessions::SyncedSessions> _syncedSessions;
 }
@@ -426,7 +425,6 @@
       l10n_util::GetNSString(IDS_IOS_OPEN_TABS_SYNC_IS_OFF_MOBILE);
   signinSyncOffItem.buttonText =
       l10n_util::GetNSString(IDS_IOS_OPEN_TABS_ENABLE_SYNC_MOBILE);
-  signinSyncOffItem.delegate = self;
   [self.tableViewModel addItem:signinSyncOffItem
        toSectionWithIdentifier:SectionIdentifierOtherDevices];
 }
@@ -659,6 +657,14 @@
   if (itemTypeSelected == ItemTypeOtherDevicesNoSessions) {
     cell.selectionStyle = UITableViewCellSelectionStyleNone;
   }
+  // Set button action method for ItemTypeOtherDevicesSyncOff.
+  if (itemTypeSelected == ItemTypeOtherDevicesSyncOff) {
+    TableViewTextButtonCell* tableViewTextButtonCell =
+        base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell);
+    [tableViewTextButtonCell.button addTarget:self
+                                       action:@selector(updateSyncState)
+                             forControlEvents:UIControlEventTouchUpInside];
+  }
 
   return cell;
 }
@@ -1093,9 +1099,15 @@
   [self.dispatcher showSyncPassphraseSettingsFromViewController:self];
 }
 
-#pragma mark - TextButtonItemDelegate
+#pragma mark - SigninPresenter
 
-- (void)performButtonAction {
+- (void)showSignin:(ShowSigninCommand*)command {
+  [self.dispatcher showSignin:command baseViewController:self];
+}
+
+#pragma mark - Private Helpers
+
+- (void)updateSyncState {
   SyncSetupService::SyncServiceState syncState =
       GetSyncStateForBrowserState(_browserState);
   if (ShouldShowSyncSignin(syncState)) {
@@ -1107,10 +1119,4 @@
   }
 }
 
-#pragma mark - SigninPresenter
-
-- (void)showSignin:(ShowSigninCommand*)command {
-  [self.dispatcher showSignin:command baseViewController:self];
-}
-
 @end
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data_table_view_controller.mm
index 7527009..2abb57f 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data_table_view_controller.mm
@@ -30,8 +30,7 @@
 }
 
 @interface ClearBrowsingDataTableViewController ()<
-    TableViewTextLinkCellDelegate,
-    TextButtonItemDelegate>
+    TableViewTextLinkCellDelegate>
 
 // TODO(crbug.com/850699): remove direct dependency and replace with
 // delegate.
@@ -121,7 +120,10 @@
           base::mac::ObjCCastStrict<TableViewTextButtonCell>(cellToReturn);
       tableViewTextButtonCell.selectionStyle =
           UITableViewCellSelectionStyleNone;
-      tableViewTextButtonCell.delegate = self;
+      [tableViewTextButtonCell.button
+                 addTarget:self
+                    action:@selector(showClearBrowsingDataAlertController)
+          forControlEvents:UIControlEventTouchUpInside];
       break;
     }
     case ItemTypeDataTypeBrowsingHistory:
@@ -178,9 +180,9 @@
   [self.localDispatcher openURL:copiedURL];
 }
 
-#pragma mark - TextButtonItemDelegate
+#pragma mark - Private Helpers
 
-- (void)performButtonAction {
+- (void)showClearBrowsingDataAlertController {
   BrowsingDataRemoveMask dataTypeMaskToRemove =
       BrowsingDataRemoveMask::REMOVE_NOTHING;
   NSArray* dataTypeItems = [self.tableViewModel
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h
index 82af8c1..d410400 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h
@@ -7,18 +7,10 @@
 
 #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
 
-@protocol TextButtonItemDelegate<NSObject>
-// Delegates an action to be performed by the presenter.
-- (void)performButtonAction;
-
-@end
-
 // TableViewTextButtonItem contains the model for
 // TableViewTextButtonCell.
 @interface TableViewTextButtonItem : TableViewItem
 
-// EnableSyncActionDelegate to perform TableViewTextButtonCell actions.
-@property(nonatomic, weak) id<TextButtonItemDelegate> delegate;
 // Text being displayed above the button.
 @property(nonatomic, readwrite, strong) NSString* text;
 // Text for cell button.
@@ -33,11 +25,9 @@
 // laid out vertically and centered.
 @interface TableViewTextButtonCell : UITableViewCell
 
-// Delegate used to show sync settings options.
-@property(nonatomic, weak) id<TextButtonItemDelegate> delegate;
 // Cell text information.
 @property(nonatomic, strong) UILabel* textLabel;
-// Action button.
+// Action button. Note: Set action method in the TableView datasource method.
 @property(nonatomic, strong) UIButton* button;
 
 @end
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.mm
index fdd368d..394dc044 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.mm
@@ -33,7 +33,6 @@
 @implementation TableViewTextButtonItem
 @synthesize buttonBackgroundColor = _buttonBackgroundColor;
 @synthesize buttonText = _buttonText;
-@synthesize delegate = _delegate;
 @synthesize text = _text;
 
 - (instancetype)initWithType:(NSInteger)type {
@@ -49,7 +48,6 @@
   [super configureCell:tableCell withStyler:styler];
   TableViewTextButtonCell* cell =
       base::mac::ObjCCastStrict<TableViewTextButtonCell>(tableCell);
-  cell.delegate = self.delegate;
   cell.textLabel.text = self.text;
   [cell.button setTitle:self.buttonText forState:UIControlStateNormal];
   cell.button.backgroundColor = self.buttonBackgroundColor
@@ -61,7 +59,6 @@
 @end
 
 @implementation TableViewTextButtonCell
-@synthesize delegate = _delegate;
 @synthesize textLabel = _textLabel;
 @synthesize button = _button;
 
@@ -90,9 +87,6 @@
     self.button.contentEdgeInsets = UIEdgeInsetsMake(
         buttonTitleVerticalContentInset, buttonTitleHorizontalContentInset,
         buttonTitleVerticalContentInset, buttonTitleHorizontalContentInset);
-    [self.button addTarget:self
-                    action:@selector(performButtonAction)
-          forControlEvents:UIControlEventTouchUpInside];
 
     // Vertical stackView to hold label and button.
     UIStackView* verticalStackView = [[UIStackView alloc]
@@ -123,10 +117,4 @@
   return self;
 }
 
-#pragma mark - TextButtonItemDelegate
-
-- (void)performButtonAction {
-  [self.delegate performButtonAction];
-}
-
 @end
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item_unittest.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item_unittest.mm
index 33c53e2f..682b3e48 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item_unittest.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_button_item_unittest.mm
@@ -20,20 +20,15 @@
 using TableViewTextButtonItemTest = PlatformTest;
 }
 
-// Tests that the UILabels and delegate are set properly after a call to
-// |configureCell:|.
+// Tests that the UILabels are set properly after a call to |configureCell:|.
 TEST_F(TableViewTextButtonItemTest, SetProperties) {
   NSString* text = @"You need to do something.";
   NSString* buttonText = @"Tap to do something.";
 
-  id<TextButtonItemDelegate> mock_delegate =
-      [OCMockObject mockForProtocol:@protocol(TextButtonItemDelegate)];
-
   TableViewTextButtonItem* item =
       [[TableViewTextButtonItem alloc] initWithType:0];
   item.text = text;
   item.buttonText = buttonText;
-  item.delegate = mock_delegate;
 
   id cell = [[[item cellClass] alloc] init];
   ASSERT_TRUE([cell isMemberOfClass:[TableViewTextButtonCell class]]);
@@ -42,31 +37,9 @@
       base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell);
   EXPECT_FALSE(textButtonCell.textLabel.text);
   EXPECT_FALSE(textButtonCell.button.titleLabel.text);
-  EXPECT_FALSE(textButtonCell.delegate);
 
   [item configureCell:textButtonCell
            withStyler:[[ChromeTableViewStyler alloc] init]];
   EXPECT_NSEQ(text, textButtonCell.textLabel.text);
   EXPECT_NSEQ(buttonText, textButtonCell.button.titleLabel.text);
-  EXPECT_TRUE(textButtonCell.delegate);
-}
-
-// Test that pressing the button invokes delegate.
-TEST_F(TableViewTextButtonItemTest, DelegateCalled) {
-  TableViewTextButtonItem* item =
-      [[TableViewTextButtonItem alloc] initWithType:0];
-  id cell = [[[item cellClass] alloc] init];
-  ASSERT_TRUE([cell isMemberOfClass:[TableViewTextButtonCell class]]);
-
-  TableViewTextButtonCell* textButtonCell =
-      base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell);
-  id<TextButtonItemDelegate> mock_delegate =
-      [OCMockObject mockForProtocol:@protocol(TextButtonItemDelegate)];
-  [textButtonCell setDelegate:mock_delegate];
-
-  OCMockObject* mock_delegate_obj = (OCMockObject*)mock_delegate;
-  [[mock_delegate_obj expect] performButtonAction];
-  UIButton* button = textButtonCell.button;
-  [button sendActionsForControlEvents:UIControlEventTouchUpInside];
-  EXPECT_OCMOCK_VERIFY(mock_delegate_obj);
 }
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
index 9c1bd26..fb578a99 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
@@ -66,6 +66,11 @@
 // Removes the empty table view, if one is present.
 - (void)removeEmptyTableView;
 
+// Performs batch table view updates described by |updates|, using |completion|
+// as the completion block.
+- (void)performBatchTableViewUpdates:(void (^)(void))updates
+                          completion:(void (^)(BOOL finished))completion;
+
 // Methods for reconfiguring and reloading the table view are provided by
 // ChromeTableViewConsumer.
 
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
index 86957a5..d7c1be7 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -145,6 +145,20 @@
   }
 }
 
+- (void)performBatchTableViewUpdates:(void (^)(void))updates
+                          completion:(void (^)(BOOL finished))completion {
+  if (@available(iOS 11, *)) {
+    [self.tableView performBatchUpdates:updates completion:completion];
+  } else {
+    [self.tableView beginUpdates];
+    if (updates)
+      updates();
+    [self.tableView endUpdates];
+    if (completion)
+      completion(YES);
+  }
+}
+
 #pragma mark - UITableViewDataSource
 
 - (UITableViewCell*)tableView:(UITableView*)tableView
diff --git a/media/base/OWNERS b/media/base/OWNERS
index c83a845..f4ecf46 100644
--- a/media/base/OWNERS
+++ b/media/base/OWNERS
@@ -1 +1,4 @@
 per-file *audio*=file://media/audio/OWNERS
+
+per-file media_switches.*=beccahughes@chromium.org
+per-file media_switches.*=mlamouri@chromium.org
diff --git a/media/base/android/media_drm_storage_bridge.cc b/media/base/android/media_drm_storage_bridge.cc
index 040f8edc..d72e965 100644
--- a/media/base/android/media_drm_storage_bridge.cc
+++ b/media/base/android/media_drm_storage_bridge.cc
@@ -23,7 +23,8 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaByteArrayToByteVector;
 using base::android::JavaParamRef;
-using base::android::RunCallbackAndroid;
+using base::android::RunBooleanCallbackAndroid;
+using base::android::RunObjectCallbackAndroid;
 using base::android::ScopedJavaLocalRef;
 using base::android::ToJavaByteArray;
 
@@ -128,7 +129,7 @@
 
 void MediaDrmStorageBridge::RunAndroidBoolCallback(JavaObjectPtr j_callback,
                                                    bool success) {
-  RunCallbackAndroid(*j_callback, success);
+  RunBooleanCallbackAndroid(*j_callback, success);
 }
 
 void MediaDrmStorageBridge::OnInitialized(
@@ -147,7 +148,7 @@
     const std::string& session_id,
     std::unique_ptr<MediaDrmStorage::SessionData> session_data) {
   if (!session_data) {
-    RunCallbackAndroid(*j_callback, ScopedJavaLocalRef<jobject>());
+    RunObjectCallbackAndroid(*j_callback, ScopedJavaLocalRef<jobject>());
     return;
   }
 
@@ -158,8 +159,9 @@
   ScopedJavaLocalRef<jstring> j_mime =
       ConvertUTF8ToJavaString(env, session_data->mime_type);
 
-  RunCallbackAndroid(*j_callback, Java_PersistentInfo_create(
-                                      env, j_eme_id, j_key_set_id, j_mime));
+  RunObjectCallbackAndroid(
+      *j_callback,
+      Java_PersistentInfo_create(env, j_eme_id, j_key_set_id, j_mime));
 }
 
 }  // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index daa15d7..11736c8 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -354,7 +354,7 @@
 #if defined(OS_ANDROID)
 // Enable a gesture to make the media controls expaned into the display cutout.
 const base::Feature kMediaControlsExpandGesture{
-    "MediaControlsExpandGesture", base::FEATURE_DISABLED_BY_DEFAULT};
+    "MediaControlsExpandGesture", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Lock the screen orientation when a video goes fullscreen.
 const base::Feature kVideoFullscreenOrientationLock{
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc
index 2cb330f..efb9234 100644
--- a/media/renderers/video_resource_updater.cc
+++ b/media/renderers/video_resource_updater.cc
@@ -675,7 +675,6 @@
       hardware_resource->mailbox(), GL_LINEAR, GL_TEXTURE_2D, sync_token);
   transferable_resource.color_space = resource_color_space;
   transferable_resource.format = copy_resource_format;
-  transferable_resource.buffer_format = viz::BufferFormat(copy_resource_format);
   external_resources->resources.push_back(std::move(transferable_resource));
 
   external_resources->release_callbacks.push_back(base::BindOnce(
@@ -705,6 +704,7 @@
   external_resources.type = ExternalResourceTypeForHardwarePlanes(
       video_frame->format(), target, video_frame->NumTextures(), &buffer_format,
       use_stream_video_draw_quad_);
+
   if (external_resources.type == VideoFrameResourceType::NONE) {
     DLOG(ERROR) << "Unsupported Texture format"
                 << VideoPixelFormatToString(video_frame->format());
@@ -734,7 +734,8 @@
       transfer_resource.read_lock_fences_enabled =
           video_frame->metadata()->IsTrue(
               VideoFrameMetadata::READ_LOCK_FENCES_ENABLED);
-      transfer_resource.buffer_format = buffer_format;
+      transfer_resource.format = viz::GetResourceFormat(buffer_format);
+
 #if defined(OS_ANDROID)
       transfer_resource.is_backed_by_surface_texture =
           video_frame->metadata()->IsTrue(VideoFrameMetadata::TEXTURE_OWNER);
@@ -915,8 +916,6 @@
 
     transferable_resource.color_space = output_color_space;
     transferable_resource.format = viz::ResourceFormat::RGBA_8888;
-    transferable_resource.buffer_format =
-        viz::BufferFormat(viz::ResourceFormat::RGBA_8888);
     external_resources.resources.push_back(std::move(transferable_resource));
     external_resources.release_callbacks.push_back(base::BindOnce(
         &VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
@@ -1039,6 +1038,7 @@
     auto* gl = context_provider_->ContextGL();
     gl->BindTexture(plane_resource->texture_target(),
                     plane_resource->texture_id());
+    DCHECK(GLSupportsFormat(plane_resource_format));
     gl->TexSubImage2D(
         plane_resource->texture_target(), 0, 0, 0, resource_size_pixels.width(),
         resource_size_pixels.height(), GLDataFormat(plane_resource_format),
@@ -1059,8 +1059,6 @@
         plane_resource->overlay_candidate());
     transferable_resource.color_space = output_color_space;
     transferable_resource.format = output_resource_format;
-    transferable_resource.buffer_format =
-        viz::BufferFormat(output_resource_format);
     external_resources.resources.push_back(std::move(transferable_resource));
     external_resources.release_callbacks.push_back(base::BindOnce(
         &VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
diff --git a/media/renderers/video_resource_updater_unittest.cc b/media/renderers/video_resource_updater_unittest.cc
index c82d7018..02743bd 100644
--- a/media/renderers/video_resource_updater_unittest.cc
+++ b/media/renderers/video_resource_updater_unittest.cc
@@ -705,8 +705,7 @@
   EXPECT_EQ(1u, resources.resources.size());
   EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
             resources.resources[0].mailbox_holder.texture_target);
-  EXPECT_EQ(gfx::BufferFormat::YUV_420_BIPLANAR,
-            resources.resources[0].buffer_format);
+  EXPECT_EQ(viz::YUV_420_BIPLANAR, resources.resources[0].format);
 
   video_frame = CreateTestYuvHardwareVideoFrame(media::PIXEL_FORMAT_NV12, 1,
                                                 GL_TEXTURE_RECTANGLE_ARB);
@@ -715,8 +714,7 @@
   EXPECT_EQ(1u, resources.resources.size());
   EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB,
             resources.resources[0].mailbox_holder.texture_target);
-  EXPECT_EQ(gfx::BufferFormat::YUV_420_BIPLANAR,
-            resources.resources[0].buffer_format);
+  EXPECT_EQ(viz::YUV_420_BIPLANAR, resources.resources[0].format);
 
   EXPECT_EQ(0, gl_->TextureCreationCount());
 }
@@ -736,7 +734,7 @@
   EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
             resources.resources[0].mailbox_holder.texture_target);
   // |updater| doesn't set |buffer_format| in this case.
-  EXPECT_EQ(gfx::BufferFormat::RGBA_8888, resources.resources[0].buffer_format);
+  EXPECT_EQ(viz::RGBA_8888, resources.resources[0].format);
 
   video_frame = CreateTestYuvHardwareVideoFrame(media::PIXEL_FORMAT_NV12, 2,
                                                 GL_TEXTURE_RECTANGLE_ARB);
@@ -745,7 +743,7 @@
   EXPECT_EQ(2u, resources.resources.size());
   EXPECT_EQ((GLenum)GL_TEXTURE_RECTANGLE_ARB,
             resources.resources[0].mailbox_holder.texture_target);
-  EXPECT_EQ(gfx::BufferFormat::RGBA_8888, resources.resources[0].buffer_format);
+  EXPECT_EQ(viz::RGBA_8888, resources.resources[0].format);
   EXPECT_EQ(0, gl_->TextureCreationCount());
 }
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 30c0f2f..2f1e3c11 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -269,8 +269,6 @@
     "der/parser.h",
     "der/tag.cc",
     "der/tag.h",
-    "extras/preload_data/decoder.cc",
-    "extras/preload_data/decoder.h",
     "http/http_auth_challenge_tokenizer.cc",
     "http/http_auth_challenge_tokenizer.h",
     "http/http_auth_scheme.cc",
@@ -2133,6 +2131,7 @@
   public_deps = [
     ":constants",
     ":net_resources",
+    ":preload_decoder",
     "//base",
     "//net/base/registry_controlled_domains",
     "//third_party/protobuf:protobuf_lite",
@@ -2248,17 +2247,6 @@
   extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
-proto_library("net_quic_trace_proto") {
-  visibility = [ ":simple_quic_tools" ]
-
-  sources = [
-    "third_party/quic/core/proto/quic_trace.proto",
-  ]
-  component_build_force_source_set = true
-
-  extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
-}
-
 if (!is_proto_quic) {
   static_library("extras") {
     sources = [
@@ -2277,6 +2265,16 @@
   }
 }
 
+static_library("preload_decoder") {
+  sources = [
+    "extras/preload_data/decoder.cc",
+    "extras/preload_data/decoder.h",
+  ]
+  deps = [
+    "//base",
+  ]
+}
+
 if (!is_ios) {
   executable("dump_cache") {
     testonly = true
@@ -3050,6 +3048,8 @@
   testonly = true
   sources = [
     "quic/chromium/crypto_test_utils_chromium.cc",
+    "third_party/quic/core/quic_trace_visitor.cc",
+    "third_party/quic/core/quic_trace_visitor.h",
     "third_party/quic/platform/api/quic_hkdf_test.cc",
     "third_party/quic/platform/api/quic_mock_log.h",
     "third_party/quic/platform/api/quic_test.h",
@@ -3169,6 +3169,7 @@
     "//testing/gtest",
     "//third_party/boringssl",
     "//third_party/protobuf:protobuf_lite",
+    "//third_party/quic_trace:quic_trace_proto",
   ]
 
   if (is_linux) {
@@ -3222,8 +3223,6 @@
     "third_party/quic/core/quic_spdy_server_stream_base.h",
     "third_party/quic/core/quic_time_wait_list_manager.cc",
     "third_party/quic/core/quic_time_wait_list_manager.h",
-    "third_party/quic/core/quic_trace_visitor.cc",
-    "third_party/quic/core/quic_trace_visitor.h",
     "third_party/quic/core/stateless_rejector.cc",
     "third_party/quic/core/stateless_rejector.h",
     "third_party/quic/tools/quic_backend_response.cc",
@@ -3268,9 +3267,6 @@
     "//third_party/protobuf:protobuf_lite",
     "//url",
   ]
-  public_deps = [
-    ":net_quic_trace_proto",
-  ]
 }
 
 if (!is_ios) {
@@ -3335,17 +3331,6 @@
       "//build/win:default_exe_manifest",
     ]
   }
-  executable("quic_trace_to_time_sequence_gnuplot") {
-    sources = [
-      "third_party/quic/tools/trace/quic_trace_to_time_sequence_gnuplot.cc",
-    ]
-    deps = [
-      ":net",
-      ":simple_quic_tools",
-      "//base",
-      "//build/win:default_exe_manifest",
-    ]
-  }
 }
 
 # This section can be updated from globbing rules using:
@@ -5111,6 +5096,7 @@
     "third_party/quic/core/quic_sustained_bandwidth_recorder_test.cc",
     "third_party/quic/core/quic_tag_test.cc",
     "third_party/quic/core/quic_time_test.cc",
+    "third_party/quic/core/quic_time_wait_list_manager_test.cc",
     "third_party/quic/core/quic_trace_visitor_test.cc",
     "third_party/quic/core/quic_unacked_packet_map_test.cc",
     "third_party/quic/core/quic_utils_test.cc",
@@ -5301,7 +5287,6 @@
       "third_party/quic/core/quic_spdy_client_session_test.cc",
       "third_party/quic/core/quic_spdy_client_stream_test.cc",
       "third_party/quic/core/quic_spdy_server_stream_base_test.cc",
-      "third_party/quic/core/quic_time_wait_list_manager_test.cc",
       "third_party/quic/core/stateless_rejector_test.cc",
       "third_party/quic/platform/impl/quic_epoll_clock_test.cc",
       "third_party/quic/platform/impl/quic_socket_utils_test.cc",
diff --git a/net/cert/caching_cert_verifier.cc b/net/cert/caching_cert_verifier.cc
index 82f83ca4..f0f5cc93 100644
--- a/net/cert/caching_cert_verifier.cc
+++ b/net/cert/caching_cert_verifier.cc
@@ -63,25 +63,6 @@
   return result;
 }
 
-bool CachingCertVerifier::AddEntry(const RequestParams& params,
-                                   int error,
-                                   const CertVerifyResult& verify_result,
-                                   base::Time verification_time) {
-  // If the cache is full, don't bother.
-  if (cache_.size() == cache_.max_entries())
-    return false;
-
-  // If there is an existing entry, don't bother updating it.
-  const CertVerificationCache::value_type* entry =
-      cache_.Get(params, CacheValidityPeriod(base::Time::Now()));
-  if (entry)
-    return false;
-
-  // Otherwise, go and add it.
-  AddResultToCache(params, verification_time, verify_result, error);
-  return true;
-}
-
 CachingCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
 
 CachingCertVerifier::CachedResult::~CachedResult() = default;
diff --git a/net/cert/caching_cert_verifier.h b/net/cert/caching_cert_verifier.h
index b634af6..e74a915 100644
--- a/net/cert/caching_cert_verifier.h
+++ b/net/cert/caching_cert_verifier.h
@@ -49,18 +49,6 @@
              std::unique_ptr<Request>* out_req,
              const NetLogWithSource& net_log) override;
 
-  // Opportunistically attempts to add |error| and |verify_result| as the
-  // result for |params|, which was obtained at |verification_time| and
-  // expires at |expiration_time|.
-  // This is opportunistic because it is not guaranteed that the entry
-  // will be added (such as if the cache is full or an entry already
-  // exists).
-  // Returns true if the entry was added.
-  bool AddEntry(const RequestParams& params,
-                int error,
-                const CertVerifyResult& verify_result,
-                base::Time verification_time);
-
  private:
   FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, CacheHit);
   FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, Visitor);
diff --git a/net/cert/caching_cert_verifier_unittest.cc b/net/cert/caching_cert_verifier_unittest.cc
index a178b14..d63352e 100644
--- a/net/cert/caching_cert_verifier_unittest.cc
+++ b/net/cert/caching_cert_verifier_unittest.cc
@@ -74,66 +74,6 @@
   ASSERT_EQ(1u, verifier_.GetCacheSize());
 }
 
-TEST_F(CachingCertVerifierTest, AddsEntries) {
-  base::FilePath certs_dir = GetTestCertsDirectory();
-  scoped_refptr<X509Certificate> test_cert(
-      ImportCertFromFile(certs_dir, "ok_cert.pem"));
-  ASSERT_TRUE(test_cert.get());
-
-  CertVerifyResult result_1;
-  result_1.verified_cert = test_cert;
-  result_1.cert_status = CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
-  result_1.has_md2 = true;
-  result_1.is_issued_by_known_root = false;
-
-  CertVerifyResult result_2;
-  result_2.verified_cert = test_cert;
-  result_2.cert_status = CERT_STATUS_IS_EV;
-  result_2.is_issued_by_known_root = true;
-
-  CertVerifier::RequestParams params(test_cert, "www.example.com", 0,
-                                     std::string(), CertificateList());
-
-  base::Time now = base::Time::Now();
-
-  // On an empty cache, it should be fine to add an entry.
-  EXPECT_TRUE(verifier_.AddEntry(params, ERR_CERT_WEAK_KEY, result_1, now));
-  ASSERT_EQ(0u, verifier_.requests());
-  ASSERT_EQ(0u, verifier_.cache_hits());
-  ASSERT_EQ(1u, verifier_.GetCacheSize());
-
-  TestCompletionCallback callback;
-  std::unique_ptr<CertVerifier::Request> request;
-
-  CertVerifyResult cached_result;
-  int error = callback.GetResult(
-      verifier_.Verify(params, nullptr, &cached_result, callback.callback(),
-                       &request, NetLogWithSource()));
-  ASSERT_THAT(error, IsError(ERR_CERT_WEAK_KEY));
-  EXPECT_TRUE(cached_result.has_md2);
-  EXPECT_FALSE(cached_result.is_issued_by_known_root);
-
-  ASSERT_EQ(1u, verifier_.requests());
-  ASSERT_EQ(1u, verifier_.cache_hits());
-  ASSERT_EQ(1u, verifier_.GetCacheSize());
-
-  // But it should not be fine to replace it with an existing entry, even
-  // if that entry is 'newer'.
-  EXPECT_FALSE(verifier_.AddEntry(params, OK, result_2,
-                                  now + base::TimeDelta::FromMinutes(1)));
-
-  error = callback.GetResult(verifier_.Verify(params, nullptr, &cached_result,
-                                              callback.callback(), &request,
-                                              NetLogWithSource()));
-  ASSERT_THAT(error, IsError(ERR_CERT_WEAK_KEY));
-  EXPECT_TRUE(cached_result.has_md2);
-  EXPECT_FALSE(cached_result.is_issued_by_known_root);
-
-  ASSERT_EQ(2u, verifier_.requests());
-  ASSERT_EQ(2u, verifier_.cache_hits());
-  ASSERT_EQ(1u, verifier_.GetCacheSize());
-}
-
 // Tests the same server certificate with different intermediate CA
 // certificates.  These should be treated as different certificate chains even
 // though the two X509Certificate objects contain the same server certificate.
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index a89292e..1e7d3a4 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -82,22 +82,24 @@
 };
 
 // TODO(eroman): The path building code in this file enforces its idea of weak
-// keys, and separately cert_verify_proc.cc also checks the chains with its
-// own policy. These policies should be aligned, to give path building the
-// best chance of finding a good path.
+// keys, and signature algorithms, but separately cert_verify_proc.cc also
+// checks the chains with its own policy. These policies must be aligned to
+// give path building the best chance of finding a good path.
 class PathBuilderDelegateImpl : public SimplePathBuilderDelegate {
  public:
   // Uses the default policy from SimplePathBuilderDelegate, which requires RSA
-  // keys to be at least 1024-bits large, and accepts SHA1 certificates.
+  // keys to be at least 1024-bits large, and optionally accepts SHA1
+  // certificates.
   PathBuilderDelegateImpl(const CRLSet* crl_set,
                           CertNetFetcher* net_fetcher,
                           VerificationType verification_type,
+                          SimplePathBuilderDelegate::DigestPolicy digest_policy,
                           int flags,
                           const SystemTrustStore* ssl_trust_store,
                           base::StringPiece stapled_leaf_ocsp_response,
                           const EVRootCAMetadata* ev_metadata,
                           bool* checked_revocation_for_some_path)
-      : SimplePathBuilderDelegate(1024),
+      : SimplePathBuilderDelegate(1024, digest_policy),
         crl_set_(crl_set),
         net_fetcher_(net_fetcher),
         verification_type_(verification_type),
@@ -390,11 +392,28 @@
   return result;
 }
 
+// Describes the parameters for a single path building attempt. Path building
+// may be re-tried with different parameters for EV and for accepting SHA1
+// certificates.
+struct BuildPathAttempt {
+  BuildPathAttempt(VerificationType verification_type,
+                   SimplePathBuilderDelegate::DigestPolicy digest_policy)
+      : verification_type(verification_type), digest_policy(digest_policy) {}
+
+  explicit BuildPathAttempt(VerificationType verification_type)
+      : BuildPathAttempt(verification_type,
+                         SimplePathBuilderDelegate::DigestPolicy::kStrong) {}
+
+  VerificationType verification_type;
+  SimplePathBuilderDelegate::DigestPolicy digest_policy;
+};
+
 void TryBuildPath(const scoped_refptr<ParsedCertificate>& target,
                   CertIssuerSourceStatic* intermediates,
                   SystemTrustStore* ssl_trust_store,
                   base::Time verification_time,
                   VerificationType verification_type,
+                  SimplePathBuilderDelegate::DigestPolicy digest_policy,
                   int flags,
                   const std::string& ocsp_response,
                   const CRLSet* crl_set,
@@ -421,8 +440,8 @@
   }
 
   PathBuilderDelegateImpl path_builder_delegate(
-      crl_set, net_fetcher, verification_type, flags, ssl_trust_store,
-      ocsp_response, ev_metadata, checked_revocation);
+      crl_set, net_fetcher, verification_type, digest_policy, flags,
+      ssl_trust_store, ocsp_response, ev_metadata, checked_revocation);
 
   // Initialize the path builder.
   CertPathBuilder path_builder(
@@ -455,7 +474,10 @@
                        bool checked_revocation_for_some_path,
                        SystemTrustStore* ssl_trust_store,
                        CertVerifyResult* verify_result) {
-  if (result.best_result_index >= result.paths.size()) {
+  const CertPathBuilderResultPath* best_path_possibly_invalid =
+      result.GetBestPathPossiblyInvalid();
+
+  if (!best_path_possibly_invalid) {
     // TODO(crbug.com/634443): What errors to communicate? Maybe the path
     // builder should always return some partial path (even if just containing
     // the target), then there is a CertErrors to test.
@@ -463,10 +485,7 @@
     return ERR_CERT_AUTHORITY_INVALID;
   }
 
-  // Use the best path that was built. This could be a partial path, or it could
-  // be a valid complete path.
-  const CertPathBuilderResultPath& partial_path =
-      *result.paths[result.best_result_index].get();
+  const CertPathBuilderResultPath& partial_path = *best_path_possibly_invalid;
 
   AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
 
@@ -523,6 +542,22 @@
              : OK;
 }
 
+// Returns true if retrying path building with a less stringent signature
+// algorithm *might* successfully build a path, based on the earlier failed
+// |result|.
+//
+// This implementation is simplistic, and looks only for the presence of the
+// kUnacceptableSignatureAlgorithm error somewhere among the built paths.
+bool CanTryAgainWithWeakerDigestPolicy(const CertPathBuilder::Result& result) {
+  for (const auto& path : result.paths) {
+    if (path->errors.ContainsError(
+            cert_errors::kUnacceptableSignatureAlgorithm))
+      return true;
+  }
+
+  return false;
+}
+
 int CertVerifyProcBuiltin::VerifyInternal(
     X509Certificate* input_cert,
     const std::string& hostname,
@@ -571,31 +606,59 @@
   // setting output flag CERT_STATUS_REV_CHECKING_ENABLED).
   bool checked_revocation_for_some_path = false;
 
-  // Only attempt to build EV paths if the target could possibly be an EV
-  // certificate.
-  const bool should_try_ev = IsEVCandidate(ev_metadata, target.get());
-
   // Run path building with the different parameters (attempts) until a valid
   // path is found. Earlier successful attempts have priority over later
   // attempts.
+  //
+  // Attempts are enqueued into |attempts| and drained in FIFO order.
+  std::vector<BuildPathAttempt> attempts;
+
+  // First try EV validation. Can skip this if the leaf certificate has no
+  // chance of verifying as EV (lacks an EV policy).
+  if (IsEVCandidate(ev_metadata, target.get()))
+    attempts.emplace_back(VerificationType::kEV);
+
+  // Next try DV validation.
+  attempts.emplace_back(VerificationType::kDV);
 
   CertPathBuilder::Result result;
   VerificationType verification_type = VerificationType::kDV;
 
-  for (VerificationType cur_attempt :
-       {VerificationType::kEV, VerificationType::kDV}) {
-    // Only attempt EV if it was requested.
-    if (cur_attempt == VerificationType::kEV && !should_try_ev)
-      continue;
+  // Iterate over |attempts| until there are none left to try, or an attempt
+  // succeeded.
+  for (size_t cur_attempt_index = 0; cur_attempt_index < attempts.size();
+       ++cur_attempt_index) {
+    const auto& cur_attempt = attempts[cur_attempt_index];
+    verification_type = cur_attempt.verification_type;
 
-    verification_type = cur_attempt;
+    // Run the attempt through the path builder.
     TryBuildPath(target, &intermediates, ssl_trust_store.get(),
-                 verification_time, verification_type, flags, ocsp_response,
-                 crl_set, net_fetcher, ev_metadata, &result,
+                 verification_time, cur_attempt.verification_type,
+                 cur_attempt.digest_policy, flags, ocsp_response, crl_set,
+                 net_fetcher, ev_metadata, &result,
                  &checked_revocation_for_some_path);
 
     if (result.HasValidPath())
       break;
+
+    // If this path building attempt (may have) failed due to the chain using a
+    // weak signature algorithm, enqueue a similar attempt but with weaker
+    // signature algorithms (SHA1) permitted.
+    //
+    // This fallback is necessary because the CertVerifyProc layer may decide to
+    // allow SHA1 based on its own policy, so path building should return
+    // possibly weak chains too.
+    //
+    // TODO(eroman): Would be better for the SHA1 policy to be part of the
+    // delegate instead so it can interact with path building.
+    if (cur_attempt.digest_policy ==
+            SimplePathBuilderDelegate::DigestPolicy::kStrong &&
+        CanTryAgainWithWeakerDigestPolicy(result)) {
+      BuildPathAttempt sha1_fallback_attempt = cur_attempt;
+      sha1_fallback_attempt.digest_policy =
+          SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
+      attempts.push_back(sha1_fallback_attempt);
+    }
   }
 
   // Write the results to |*verify_result|.
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 39fe675b2..902eea9 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -2393,6 +2393,38 @@
     SetExtension(SubjectAltNameOid(), FinishCBB(cbb.get()));
   }
 
+  // Sets the signature algorithm for the certificate to either
+  // sha256WithRSAEncryption or sha1WithRSAEncryption.
+  void SetSignatureAlgorithmRsaPkca1(DigestAlgorithm digest) {
+    switch (digest) {
+      case DigestAlgorithm::Sha256: {
+        const uint8_t kSha256WithRSAEncryption[] = {
+            0x30, 0x0D, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+            0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
+        SetSignatureAlgorithm(std::string(std::begin(kSha256WithRSAEncryption),
+                                          std::end(kSha256WithRSAEncryption)));
+        break;
+      }
+
+      case DigestAlgorithm::Sha1: {
+        const uint8_t kSha1WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a,
+                                                  0x86, 0x48, 0x86, 0xf7, 0x0d,
+                                                  0x01, 0x01, 0x05, 0x05, 0x00};
+        SetSignatureAlgorithm(std::string(std::begin(kSha1WithRSAEncryption),
+                                          std::end(kSha1WithRSAEncryption)));
+        break;
+      }
+
+      default:
+        ASSERT_TRUE(false);
+    }
+  }
+
+  void SetSignatureAlgorithm(std::string algorithm_tlv) {
+    signature_algorithm_tlv_ = std::move(algorithm_tlv);
+    Invalidate();
+  }
+
   void SetRandomSerialNumber() {
     serial_number_ = base::RandUint64();
     Invalidate();
@@ -2831,6 +2863,95 @@
   EXPECT_THAT(error, IsOk());
 }
 
+// Tries verifying a certificate chain that uses a SHA1 intermediate,
+// however, chasing the AIA can discover a SHA256 version of the intermediate.
+//
+// Path building should discover the stronger intermediate and use it.
+TEST_P(CertVerifyProcInternalWithNetFetchingTest,
+       Sha1IntermediateButAIAHasSha256) {
+  const char kHostname[] = "www.example.com";
+
+  base::FilePath certs_dir =
+      GetTestNetDataDirectory()
+          .AppendASCII("verify_certificate_chain_unittest")
+          .AppendASCII("target-and-intermediate");
+
+  CertificateList orig_certs = CreateCertificateListFromFile(
+      certs_dir, "chain.pem", X509Certificate::FORMAT_AUTO);
+  ASSERT_EQ(3U, orig_certs.size());
+
+  // Build slightly modified variants of |orig_certs|.
+  CertBuilder root(orig_certs[2]->cert_buffer(), nullptr);
+  CertBuilder intermediate(orig_certs[1]->cert_buffer(), &root);
+  CertBuilder leaf(orig_certs[0]->cert_buffer(), &intermediate);
+
+  // Make the leaf certificate have an AIA (CA Issuers) that points to the
+  // embedded test server. This uses a random URL for predictable behavior in
+  // the presence of global caching.
+  std::string ca_issuers_relative_path = MakeRandomPath(".cer");
+  GURL ca_issuers_url = GetTestServerAbsoluteUrl(ca_issuers_relative_path);
+  leaf.SetCaIssuersUrl(ca_issuers_url);
+  leaf.SetSubjectAltName(kHostname);
+
+  // Make two versions of the intermediate - one that is SHA256 signed, and one
+  // that is SHA1 signed.
+  intermediate.SetSignatureAlgorithmRsaPkca1(DigestAlgorithm::Sha256);
+  intermediate.SetRandomSerialNumber();
+  auto intermediate_sha256 = intermediate.DupCertBuffer();
+
+  intermediate.SetSignatureAlgorithmRsaPkca1(DigestAlgorithm::Sha1);
+  intermediate.SetRandomSerialNumber();
+  auto intermediate_sha1 = intermediate.DupCertBuffer();
+
+  // Trust the root certificate.
+  auto root_cert = root.GetX509Certificate();
+  ScopedTestRoot scoped_root(root_cert.get());
+
+  // Setup the test server to reply with the SHA256 intermediate.
+  RegisterSimpleTestServerHandler(
+      ca_issuers_relative_path, "application/pkix-cert",
+      x509_util::CryptoBufferAsStringPiece(intermediate_sha256.get())
+          .as_string());
+
+  // Build a chain to verify that includes the SHA1 intermediate.
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
+  intermediates.push_back(x509_util::DupCryptoBuffer(intermediate_sha1.get()));
+  scoped_refptr<X509Certificate> chain_sha1 = X509Certificate::CreateFromBuffer(
+      leaf.DupCertBuffer(), std::move(intermediates));
+  ASSERT_TRUE(chain_sha1.get());
+
+  const int flags = 0;
+  CertVerifyResult verify_result;
+  int error = Verify(chain_sha1.get(), kHostname, flags, nullptr,
+                     CertificateList(), &verify_result);
+
+  if (verify_proc_type() == CERT_VERIFY_PROC_BUILTIN ||
+      verify_proc_type() == CERT_VERIFY_PROC_MAC) {
+    // Should have built a chain through the SHA256 intermediate. This was only
+    // available via AIA, and not the (SHA1) one provided directly to path
+    // building.
+    ASSERT_EQ(2u, verify_result.verified_cert->intermediate_buffers().size());
+    EXPECT_TRUE(x509_util::CryptoBufferEqual(
+        verify_result.verified_cert->intermediate_buffers()[0].get(),
+        intermediate_sha256.get()));
+    ASSERT_EQ(2u, verify_result.verified_cert->intermediate_buffers().size());
+
+    EXPECT_FALSE(verify_result.has_sha1);
+    EXPECT_THAT(error, IsOk());
+  } else if (verify_proc_type() == CERT_VERIFY_PROC_WIN) {
+    // TODO(eroman): Make these test expectations exact.
+    // This seemed to be working on Windows when !AreSHA1IntermediatesAllowed()
+    // from previous testing, but then failed on the Windows 10 bot.
+    if (error != OK) {
+      EXPECT_TRUE(verify_result.has_sha1);
+      EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
+    }
+  } else {
+    EXPECT_TRUE(verify_result.has_sha1);
+    EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
+  }
+}
+
 TEST(CertVerifyProcTest, RejectsMD2) {
   scoped_refptr<X509Certificate> cert(
       ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
diff --git a/net/cert/internal/path_builder.cc b/net/cert/internal/path_builder.cc
index 969aae9..44e6636 100644
--- a/net/cert/internal/path_builder.cc
+++ b/net/cert/internal/path_builder.cc
@@ -478,17 +478,23 @@
 
 const CertPathBuilderResultPath* CertPathBuilder::Result::GetBestValidPath()
     const {
+  const CertPathBuilderResultPath* result_path = GetBestPathPossiblyInvalid();
+
+  if (result_path && result_path->IsValid())
+    return result_path;
+
+  return nullptr;
+}
+
+const CertPathBuilderResultPath*
+CertPathBuilder::Result::GetBestPathPossiblyInvalid() const {
   DCHECK((paths.empty() && best_result_index == 0) ||
          best_result_index < paths.size());
 
   if (best_result_index >= paths.size())
     return nullptr;
 
-  const CertPathBuilderResultPath* result_path = paths[best_result_index].get();
-  if (result_path->IsValid())
-    return result_path;
-
-  return nullptr;
+  return paths[best_result_index].get();
 }
 
 void CertPathBuilder::Result::Clear() {
diff --git a/net/cert/internal/path_builder.h b/net/cert/internal/path_builder.h
index 3ac0464..21dcb24 100644
--- a/net/cert/internal/path_builder.h
+++ b/net/cert/internal/path_builder.h
@@ -115,6 +115,9 @@
     // if there was none.
     const CertPathBuilderResultPath* GetBestValidPath() const;
 
+    // Returns the best CertPathBuilderResultPath or nullptr if there was none.
+    const CertPathBuilderResultPath* GetBestPathPossiblyInvalid() const;
+
     // Resets to the initial value.
     void Clear();
 
diff --git a/net/cert/internal/path_builder_pkits_unittest.cc b/net/cert/internal/path_builder_pkits_unittest.cc
index d5fbe859..5bec8a6 100644
--- a/net/cert/internal/path_builder_pkits_unittest.cc
+++ b/net/cert/internal/path_builder_pkits_unittest.cc
@@ -56,7 +56,8 @@
 
     scoped_refptr<ParsedCertificate> target_cert(certs.back());
 
-    SimplePathBuilderDelegate path_builder_delegate(1024);
+    SimplePathBuilderDelegate path_builder_delegate(
+        1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
     CertPathBuilder::Result result;
     CertPathBuilder path_builder(
diff --git a/net/cert/internal/path_builder_unittest.cc b/net/cert/internal/path_builder_unittest.cc
index 81c253c9..f45ede2 100644
--- a/net/cert/internal/path_builder_unittest.cc
+++ b/net/cert/internal/path_builder_unittest.cc
@@ -117,7 +117,9 @@
 
 class PathBuilderMultiRootTest : public ::testing::Test {
  public:
-  PathBuilderMultiRootTest() : delegate_(1024) {}
+  PathBuilderMultiRootTest()
+      : delegate_(1024,
+                  SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
 
   void SetUp() override {
     ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b_));
@@ -449,7 +451,9 @@
 
 class PathBuilderKeyRolloverTest : public ::testing::Test {
  public:
-  PathBuilderKeyRolloverTest() : delegate_(1024) {}
+  PathBuilderKeyRolloverTest()
+      : delegate_(1024,
+                  SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
 
   void SetUp() override {
     ParsedCertificateList path;
@@ -1182,7 +1186,8 @@
     CertIssuerSourceStatic intermediates;
     intermediates.AddCert(test_.chain[1]);
 
-    SimplePathBuilderDelegate default_delegate(1024);
+    SimplePathBuilderDelegate default_delegate(
+        1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
     CertPathBuilderDelegate* delegate =
         optional_delegate ? optional_delegate : &default_delegate;
 
@@ -1294,7 +1299,10 @@
 
 class CertPathBuilderDelegateBase : public SimplePathBuilderDelegate {
  public:
-  CertPathBuilderDelegateBase() : SimplePathBuilderDelegate(1024) {}
+  CertPathBuilderDelegateBase()
+      : SimplePathBuilderDelegate(
+            1024,
+            SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
   void CheckPathAfterVerification(CertPathBuilderResultPath* path) override {
     ADD_FAILURE() << "Tests must override this";
   }
diff --git a/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc b/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
index 9ef6631..3fb8451 100644
--- a/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
+++ b/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
@@ -17,7 +17,8 @@
  public:
   static void Verify(const VerifyCertChainTest& test,
                      const std::string& test_file_path) {
-    SimplePathBuilderDelegate path_builder_delegate(1024);
+    SimplePathBuilderDelegate path_builder_delegate(
+        1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
     ASSERT_FALSE(test.chain.empty());
 
     TrustStoreInMemory trust_store;
diff --git a/net/cert/internal/simple_path_builder_delegate.cc b/net/cert/internal/simple_path_builder_delegate.cc
index 65508c97..584eeed 100644
--- a/net/cert/internal/simple_path_builder_delegate.cc
+++ b/net/cert/internal/simple_path_builder_delegate.cc
@@ -28,24 +28,6 @@
 DEFINE_CERT_ERROR_ID(kUnacceptableCurveForEcdsa,
                      "Only P-256, P-384, P-521 are supported for ECDSA");
 
-// Whitelist of default permitted signature digest algorithms.
-WARN_UNUSED_RESULT bool IsAcceptableDigest(DigestAlgorithm digest) {
-  switch (digest) {
-    case DigestAlgorithm::Md2:
-    case DigestAlgorithm::Md4:
-    case DigestAlgorithm::Md5:
-      return false;
-
-    case DigestAlgorithm::Sha1:
-    case DigestAlgorithm::Sha256:
-    case DigestAlgorithm::Sha384:
-    case DigestAlgorithm::Sha512:
-      return true;
-  }
-
-  return false;
-}
-
 bool IsAcceptableCurveForEcdsa(int curve_nid) {
   // Whitelist default permitted named curves.
   switch (curve_nid) {
@@ -61,8 +43,10 @@
 }  // namespace
 
 SimplePathBuilderDelegate::SimplePathBuilderDelegate(
-    size_t min_rsa_modulus_length_bits)
-    : min_rsa_modulus_length_bits_(min_rsa_modulus_length_bits) {}
+    size_t min_rsa_modulus_length_bits,
+    DigestPolicy digest_policy)
+    : min_rsa_modulus_length_bits_(min_rsa_modulus_length_bits),
+      digest_policy_(digest_policy) {}
 
 void SimplePathBuilderDelegate::CheckPathAfterVerification(
     CertPathBuilderResultPath* path) {
@@ -77,13 +61,6 @@
   //    RSA PKCS#1 v1.5
   //    RSASSA-PSS
   //    ECDSA
-  //
-  // When used with digest algorithms:
-  //
-  //    SHA1
-  //    SHA256
-  //    SHA384
-  //    SHA512
   switch (algorithm.algorithm()) {
     case SignatureAlgorithmId::Dsa:
       return false;
@@ -138,4 +115,30 @@
   return false;
 }
 
+// Restricted signature digest algorithms to:
+//
+//    SHA1 (if digest_policy_ == kWeakAllowSha1)
+//    SHA256
+//    SHA384
+//    SHA512
+bool SimplePathBuilderDelegate::IsAcceptableDigest(
+    DigestAlgorithm digest) const {
+  switch (digest) {
+    case DigestAlgorithm::Md2:
+    case DigestAlgorithm::Md4:
+    case DigestAlgorithm::Md5:
+      return false;
+
+    case DigestAlgorithm::Sha1:
+      return digest_policy_ ==
+             SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
+    case DigestAlgorithm::Sha256:
+    case DigestAlgorithm::Sha384:
+    case DigestAlgorithm::Sha512:
+      return true;
+  }
+
+  return false;
+}
+
 }  // namespace net
diff --git a/net/cert/internal/simple_path_builder_delegate.h b/net/cert/internal/simple_path_builder_delegate.h
index 4b43870..ede49e5 100644
--- a/net/cert/internal/simple_path_builder_delegate.h
+++ b/net/cert/internal/simple_path_builder_delegate.h
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "net/base/net_export.h"
 #include "net/cert/internal/path_builder.h"
+#include "net/cert/internal/signature_algorithm.h"
 
 namespace net {
 
@@ -21,15 +22,26 @@
 //
 //   * RSA public keys must be >= |min_rsa_modulus_length_bits|.
 //   * Signature algorithm can be RSA PKCS#1, RSASSA-PSS or ECDSA
-//   * Hash algorithm can be SHA1, SHA256, SHA348 or SHA512
+//   * Digest algorithm can be SHA256, SHA348 or SHA512.
+//       * If the |digest_policy| was set to kAllowSha1, then SHA1 is
+//         additionally accepted.
 //   * EC named curve can be P-256, P-384, P-521.
 class NET_EXPORT SimplePathBuilderDelegate : public CertPathBuilderDelegate {
  public:
+  enum class DigestPolicy {
+    // Accepts digests of SHA256, SHA348 or SHA512
+    kStrong,
+
+    // Accepts everything that kStrong does, plus SHA1.
+    kWeakAllowSha1,
+  };
+
   // Error emitted when a public key is rejected because it is an RSA key with a
   // modulus size that is too small.
   static const CertErrorId kRsaModulusTooSmall;
 
-  explicit SimplePathBuilderDelegate(size_t min_rsa_modulus_length_bits);
+  SimplePathBuilderDelegate(size_t min_rsa_modulus_length_bits,
+                            DigestPolicy digest_policy);
 
   // Accepts RSA PKCS#1, RSASSA-PSS or ECDA using any of the SHA* digests
   // (including SHA1).
@@ -44,7 +56,10 @@
   void CheckPathAfterVerification(CertPathBuilderResultPath* path) override;
 
  private:
+  bool IsAcceptableDigest(DigestAlgorithm digest) const WARN_UNUSED_RESULT;
+
   const size_t min_rsa_modulus_length_bits_;
+  const DigestPolicy digest_policy_;
 };
 
 }  // namespace net
diff --git a/net/cert/internal/simple_path_builder_delegate_unittest.cc b/net/cert/internal/simple_path_builder_delegate_unittest.cc
index 507b115..dd222a4 100644
--- a/net/cert/internal/simple_path_builder_delegate_unittest.cc
+++ b/net/cert/internal/simple_path_builder_delegate_unittest.cc
@@ -72,7 +72,8 @@
   ASSERT_TRUE(public_key);
 
   CertErrors errors;
-  SimplePathBuilderDelegate delegate(1024);
+  SimplePathBuilderDelegate delegate(
+      1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
   EXPECT_TRUE(
       delegate.IsSignatureAlgorithmAcceptable(*signature_algorithm, &errors));
@@ -98,7 +99,8 @@
   ASSERT_TRUE(public_key);
 
   CertErrors errors;
-  SimplePathBuilderDelegate delegate(2048);
+  SimplePathBuilderDelegate delegate(
+      2048, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
   EXPECT_TRUE(
       delegate.IsSignatureAlgorithmAcceptable(*signature_algorithm, &errors));
diff --git a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
index 4443dd7..1040f3c3 100644
--- a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
@@ -42,7 +42,8 @@
           << parsing_errors.ToDebugString();
     }
 
-    SimplePathBuilderDelegate path_builder_delegate(1024);
+    SimplePathBuilderDelegate path_builder_delegate(
+        1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
     std::set<der::Input> user_constrained_policy_set;
 
diff --git a/net/cert/internal/verify_certificate_chain_unittest.cc b/net/cert/internal/verify_certificate_chain_unittest.cc
index 70595839..0a53bef 100644
--- a/net/cert/internal/verify_certificate_chain_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_unittest.cc
@@ -17,7 +17,8 @@
  public:
   static void Verify(const VerifyCertChainTest& test,
                      const std::string& test_file_path) {
-    SimplePathBuilderDelegate delegate(1024);
+    SimplePathBuilderDelegate delegate(
+        1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
 
     CertPathErrors errors;
     // TODO(eroman): Check user_constrained_policy_set.
diff --git a/net/extras/preload_data/decoder.cc b/net/extras/preload_data/decoder.cc
index ad0d18f5..b91cc48 100644
--- a/net/extras/preload_data/decoder.cc
+++ b/net/extras/preload_data/decoder.cc
@@ -5,52 +5,6 @@
 #include "net/extras/preload_data/decoder.h"
 #include "base/logging.h"
 
-namespace {
-
-// HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
-// simply encoded as a series of two-byte structures. The first byte determines
-// the "0" pointer for that node and the second the "1" pointer. Each byte
-// either has the MSB set, in which case the bottom 7 bits are the value for
-// that position, or else the bottom seven bits contain the index of a node.
-//
-// The tree is decoded by walking rather than a table-driven approach.
-class HuffmanDecoder {
- public:
-  HuffmanDecoder(const uint8_t* tree, size_t tree_bytes)
-      : tree_(tree), tree_bytes_(tree_bytes) {}
-
-  bool Decode(net::extras::PreloadDecoder::BitReader* reader, char* out) {
-    const uint8_t* current = &tree_[tree_bytes_ - 2];
-
-    for (;;) {
-      bool bit;
-      if (!reader->Next(&bit)) {
-        return false;
-      }
-
-      uint8_t b = current[bit];
-      if (b & 0x80) {
-        *out = static_cast<char>(b & 0x7f);
-        return true;
-      }
-
-      unsigned offset = static_cast<unsigned>(b) * 2;
-      DCHECK_LT(offset, tree_bytes_);
-      if (offset >= tree_bytes_) {
-        return false;
-      }
-
-      current = &tree_[offset];
-    }
-  }
-
- private:
-  const uint8_t* const tree_;
-  const size_t tree_bytes_;
-};
-
-}  // namespace
-
 namespace net {
 
 namespace extras {
@@ -131,26 +85,49 @@
   return true;
 }
 
+PreloadDecoder::HuffmanDecoder::HuffmanDecoder(const uint8_t* tree,
+                                               size_t tree_bytes)
+    : tree_(tree), tree_bytes_(tree_bytes) {}
+
+bool PreloadDecoder::HuffmanDecoder::Decode(PreloadDecoder::BitReader* reader,
+                                            char* out) const {
+  const uint8_t* current = &tree_[tree_bytes_ - 2];
+
+  for (;;) {
+    bool bit;
+    if (!reader->Next(&bit)) {
+      return false;
+    }
+
+    uint8_t b = current[bit];
+    if (b & 0x80) {
+      *out = static_cast<char>(b & 0x7f);
+      return true;
+    }
+
+    unsigned offset = static_cast<unsigned>(b) * 2;
+    DCHECK_LT(offset, tree_bytes_);
+    if (offset >= tree_bytes_) {
+      return false;
+    }
+
+    current = &tree_[offset];
+  }
+}
+
 PreloadDecoder::PreloadDecoder(const uint8_t* huffman_tree,
                                size_t huffman_tree_size,
                                const uint8_t* trie,
                                size_t trie_bits,
                                size_t trie_root_position)
-    : huffman_tree_(huffman_tree),
-      huffman_tree_size_(huffman_tree_size),
-      trie_(trie),
-      trie_bits_(trie_bits),
+    : huffman_decoder_(huffman_tree, huffman_tree_size),
+      bit_reader_(trie, trie_bits),
       trie_root_position_(trie_root_position) {}
 
 PreloadDecoder::~PreloadDecoder() {}
 
 bool PreloadDecoder::Decode(const std::string& search, bool* out_found) {
-  HuffmanDecoder huffman(huffman_tree_, huffman_tree_size_);
-  BitReader reader(trie_, trie_bits_);
   size_t bit_offset = trie_root_position_;
-  static const char kEndOfString = 0;
-  static const char kEndOfTable = 127;
-
   *out_found = false;
 
   // current_search_offset contains one more than the index of the current
@@ -161,13 +138,13 @@
 
   for (;;) {
     // Seek to the desired location.
-    if (!reader.Seek(bit_offset)) {
+    if (!bit_reader_.Seek(bit_offset)) {
       return false;
     }
 
     // Decode the unary length of the common prefix.
     size_t prefix_length;
-    if (!reader.Unary(&prefix_length)) {
+    if (!bit_reader_.Unary(&prefix_length)) {
       return false;
     }
 
@@ -179,7 +156,7 @@
       }
 
       char c;
-      if (!huffman.Decode(&reader, &c)) {
+      if (!huffman_decoder_.Decode(&bit_reader_, &c)) {
         return false;
       }
       if (search[current_search_offset - 1] != c) {
@@ -194,7 +171,7 @@
     // Next is the dispatch table.
     for (;;) {
       char c;
-      if (!huffman.Decode(&reader, &c)) {
+      if (!huffman_decoder_.Decode(&bit_reader_, &c)) {
         return false;
       }
       if (c == kEndOfTable) {
@@ -203,7 +180,8 @@
       }
 
       if (c == kEndOfString) {
-        if (!ReadEntry(&reader, search, current_search_offset, out_found)) {
+        if (!ReadEntry(&bit_reader_, search, current_search_offset,
+                       out_found)) {
           return false;
         }
         if (current_search_offset == 0) {
@@ -223,8 +201,8 @@
         // The first offset is backwards from the current position.
         uint32_t jump_delta_bits;
         uint32_t jump_delta;
-        if (!reader.Read(5, &jump_delta_bits) ||
-            !reader.Read(jump_delta_bits, &jump_delta)) {
+        if (!bit_reader_.Read(5, &jump_delta_bits) ||
+            !bit_reader_.Read(jump_delta_bits, &jump_delta)) {
           return false;
         }
 
@@ -237,19 +215,19 @@
       } else {
         // Subsequent offsets are forward from the target of the first offset.
         uint32_t is_long_jump;
-        if (!reader.Read(1, &is_long_jump)) {
+        if (!bit_reader_.Read(1, &is_long_jump)) {
           return false;
         }
 
         uint32_t jump_delta;
         if (!is_long_jump) {
-          if (!reader.Read(7, &jump_delta)) {
+          if (!bit_reader_.Read(7, &jump_delta)) {
             return false;
           }
         } else {
           uint32_t jump_delta_bits;
-          if (!reader.Read(4, &jump_delta_bits) ||
-              !reader.Read(jump_delta_bits + 8, &jump_delta)) {
+          if (!bit_reader_.Read(4, &jump_delta_bits) ||
+              !bit_reader_.Read(jump_delta_bits + 8, &jump_delta)) {
             return false;
           }
         }
diff --git a/net/extras/preload_data/decoder.h b/net/extras/preload_data/decoder.h
index b31c97e..6afa7a7 100644
--- a/net/extras/preload_data/decoder.h
+++ b/net/extras/preload_data/decoder.h
@@ -5,8 +5,12 @@
 #ifndef NET_EXTRAS_PRELOAD_DATA_DECODER_H_
 #define NET_EXTRAS_PRELOAD_DATA_DECODER_H_
 
+#include <stdint.h>
+
 #include <string>
 
+#include "base/macros.h"
+
 namespace net {
 
 namespace extras {
@@ -16,6 +20,9 @@
 // they are interested in.
 class PreloadDecoder {
  public:
+  // These must match the values in net/tools/huffman_trie/trie/trie_writer.h.
+  enum : char { kEndOfString = 0, kEndOfTable = 127 };
+
   // BitReader is a class that allows a bytestring to be read bit-by-bit.
   class BitReader {
    public:
@@ -51,6 +58,29 @@
     // num_bits_used_ contains the number of bits of |current_byte_| that have
     // been read.
     unsigned num_bits_used_;
+
+    DISALLOW_COPY_AND_ASSIGN(BitReader);
+  };
+
+  // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
+  // simply encoded as a series of two-byte structures. The first byte
+  // determines the "0" pointer for that node and the second the "1" pointer.
+  // Each byte either has the MSB set, in which case the bottom 7 bits are the
+  // value for that position, or else the bottom seven bits contain the index of
+  // a node.
+  //
+  // The tree is decoded by walking rather than a table-driven approach.
+  class HuffmanDecoder {
+   public:
+    HuffmanDecoder(const uint8_t* tree, size_t tree_bytes);
+
+    bool Decode(PreloadDecoder::BitReader* reader, char* out) const;
+
+   private:
+    const uint8_t* const tree_;
+    const size_t tree_bytes_;
+
+    DISALLOW_COPY_AND_ASSIGN(HuffmanDecoder);
   };
 
   PreloadDecoder(const uint8_t* huffman_tree,
@@ -84,17 +114,21 @@
   // value always comes before an entry for '.'.
   bool Decode(const std::string& search, bool* out_found);
 
+ protected:
   virtual bool ReadEntry(BitReader* reader,
                          const std::string& search,
                          size_t current_search_offset,
                          bool* out_found) = 0;
 
+  const HuffmanDecoder& huffman_decoder() const { return huffman_decoder_; }
+
  private:
-  const uint8_t* huffman_tree_;
-  const size_t huffman_tree_size_;
-  const uint8_t* trie_;
-  const size_t trie_bits_;
+  HuffmanDecoder huffman_decoder_;
+  BitReader bit_reader_;
+
   const size_t trie_root_position_;
+
+  DISALLOW_COPY_AND_ASSIGN(PreloadDecoder);
 };
 
 }  // namespace extras
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index aba283a..62dfecd 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -1304,7 +1304,7 @@
   base::Time expiration1;
   ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
   quic::QuicTransportVersionVector advertised_versions = {
-      quic::QUIC_VERSION_37, quic::QUIC_VERSION_35};
+      quic::QUIC_VERSION_41, quic::QUIC_VERSION_35};
   alternative_service_info_vector.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions));
@@ -1352,7 +1352,7 @@
       "{\"quic_servers\":{\"https://mail.google.com:80\":{"
       "\"server_info\":\"quic_server_info1\"}},\"servers\":["
       "{\"https://www.google.com:80\":{\"alternative_service\":[{"
-      "\"advertised_versions\":[35,37],\"expiration\":\"13756212000000000\","
+      "\"advertised_versions\":[35,41],\"expiration\":\"13756212000000000\","
       "\"port\":443,\"protocol_str\":\"quic\"},{\"advertised_versions\":[],"
       "\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\","
       "\"port\":1234,\"protocol_str\":\"h2\"}]}},"
@@ -1376,7 +1376,7 @@
       "{\"port\":443,\"protocol_str\":\"quic\"},"
       "{\"port\":123,\"protocol_str\":\"quic\","
       "\"expiration\":\"9223372036854775807\","
-      "\"advertised_versions\":[37,35]}]}");
+      "\"advertised_versions\":[41,35]}]}");
   ASSERT_TRUE(server_value);
   base::DictionaryValue* server_dict;
   ASSERT_TRUE(server_value->GetAsDictionary(&server_dict));
@@ -1414,7 +1414,7 @@
       alternative_service_info_vector[1].advertised_versions();
   EXPECT_EQ(2u, loaded_advertised_versions.size());
   EXPECT_EQ(quic::QUIC_VERSION_35, loaded_advertised_versions[0]);
-  EXPECT_EQ(quic::QUIC_VERSION_37, loaded_advertised_versions[1]);
+  EXPECT_EQ(quic::QUIC_VERSION_41, loaded_advertised_versions[1]);
 }
 
 TEST_P(HttpServerPropertiesManagerTest,
@@ -1424,7 +1424,7 @@
   // #1: Set alternate protocol.
   AlternativeServiceInfoVector alternative_service_info_vector;
   // Quic alternative service set with a single QUIC version:
-  // quic::QUIC_VERSION_37.
+  // quic::QUIC_VERSION_41.
   AlternativeService quic_alternative_service1(kProtoQUIC, "", 443);
   base::Time expiration1;
   ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
@@ -1472,7 +1472,7 @@
   AlternativeServiceInfoVector alternative_service_info_vector_2;
   // Quic alternative service set with two advertised QUIC versions.
   quic::QuicTransportVersionVector advertised_versions = {
-      quic::QUIC_VERSION_37, quic::QUIC_VERSION_35};
+      quic::QUIC_VERSION_41, quic::QUIC_VERSION_35};
   alternative_service_info_vector_2.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions));
@@ -1490,7 +1490,7 @@
       "{\"quic_servers\":{\"https://mail.google.com:80\":"
       "{\"server_info\":\"quic_server_info1\"}},\"servers\":["
       "{\"https://www.google.com:80\":"
-      "{\"alternative_service\":[{\"advertised_versions\":[35,37],"
+      "{\"alternative_service\":[{\"advertised_versions\":[35,41],"
       "\"expiration\":\"13756212000000000\",\"port\":443,"
       "\"protocol_str\":\"quic\"}]}}],\"supports_quic\":"
       "{\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":5}";
@@ -1502,7 +1502,7 @@
   AlternativeServiceInfoVector alternative_service_info_vector_3;
   // A same set of QUIC versions but listed in a different order.
   quic::QuicTransportVersionVector advertised_versions_2 = {
-      quic::QUIC_VERSION_35, quic::QUIC_VERSION_37};
+      quic::QUIC_VERSION_35, quic::QUIC_VERSION_41};
   alternative_service_info_vector_3.push_back(
       AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
           quic_alternative_service1, expiration1, advertised_versions_2));
diff --git a/net/quic/chromium/quic_chromium_packet_writer.cc b/net/quic/chromium/quic_chromium_packet_writer.cc
index 50fb70c5..a892e1b 100644
--- a/net/quic/chromium/quic_chromium_packet_writer.cc
+++ b/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -204,8 +204,11 @@
     // HandleWriteError returns the outcome of that rewrite attempt.
     rv = delegate_->HandleWriteError(rv, std::move(packet_));
     DCHECK(packet_ == nullptr);
-    if (rv == ERR_IO_PENDING)
+    if (rv == ERR_IO_PENDING) {
+      // Set write blocked back as HandleWriteError hasn't complete migration.
+      write_blocked_ = true;
       return;
+    }
   }
   if (retry_count_ != 0) {
     RecordRetryCount(retry_count_);
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index 4b45a17..cefedde 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -82,10 +82,6 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
     case quic::QUIC_VERSION_35:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_35;
-    case quic::QUIC_VERSION_37:
-      return HttpResponseInfo::CONNECTION_INFO_QUIC_37;
-    case quic::QUIC_VERSION_38:
-      return HttpResponseInfo::CONNECTION_INFO_QUIC_38;
     case quic::QUIC_VERSION_39:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_39;
     case quic::QUIC_VERSION_41:
diff --git a/net/quic/chromium/quic_http_utils_test.cc b/net/quic/chromium/quic_http_utils_test.cc
index 416604f..e50f364bd 100644
--- a/net/quic/chromium/quic_http_utils_test.cc
+++ b/net/quic/chromium/quic_http_utils_test.cc
@@ -39,18 +39,16 @@
 
 TEST(QuicHttpUtilsTest, FilterSupportedAltSvcVersions) {
   quic::QuicTransportVersionVector supported_versions = {
-      quic::QUIC_VERSION_37, quic::QUIC_VERSION_38, quic::QUIC_VERSION_39,
-      quic::QUIC_VERSION_41};
+      quic::QUIC_VERSION_35, quic::QUIC_VERSION_39, quic::QUIC_VERSION_41};
 
-  std::vector<uint32_t> alt_svc_versions_google = {
-      quic::QUIC_VERSION_38, quic::QUIC_VERSION_41, quic::QUIC_VERSION_42};
+  std::vector<uint32_t> alt_svc_versions_google = {quic::QUIC_VERSION_41,
+                                                   quic::QUIC_VERSION_42};
   std::vector<uint32_t> alt_svc_versions_ietf = {
-      QuicVersionToQuicVersionLabel(quic::QUIC_VERSION_38),
       QuicVersionToQuicVersionLabel(quic::QUIC_VERSION_41),
       QuicVersionToQuicVersionLabel(quic::QUIC_VERSION_42)};
 
   quic::QuicTransportVersionVector supported_alt_svc_versions = {
-      quic::QUIC_VERSION_38, quic::QUIC_VERSION_41};
+      quic::QUIC_VERSION_41};
   spdy::SpdyAltSvcWireFormat::AlternativeService altsvc;
 
   altsvc.protocol_id = "quic";
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 76ad708..8e1022e 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -436,6 +436,7 @@
   std::unique_ptr<quic::QuicEncryptedPacket> ConstructGetRequestPacket(
       quic::QuicPacketNumber packet_number,
       quic::QuicStreamId stream_id,
+      quic::QuicStreamId parent_stream_id,
       bool should_include_version,
       bool fin,
       quic::QuicStreamOffset* offset) {
@@ -446,7 +447,18 @@
     size_t spdy_headers_frame_len;
     return client_maker_.MakeRequestHeadersPacket(
         packet_number, stream_id, should_include_version, fin, priority,
-        std::move(headers), 0, &spdy_headers_frame_len, offset);
+        std::move(headers), parent_stream_id, &spdy_headers_frame_len, offset);
+  }
+
+  std::unique_ptr<quic::QuicEncryptedPacket> ConstructGetRequestPacket(
+      quic::QuicPacketNumber packet_number,
+      quic::QuicStreamId stream_id,
+      bool should_include_version,
+      bool fin,
+      quic::QuicStreamOffset* offset) {
+    return ConstructGetRequestPacket(packet_number, stream_id,
+                                     /*parent_stream_id=*/0,
+                                     should_include_version, fin, offset);
   }
 
   std::unique_ptr<quic::QuicEncryptedPacket> ConstructOkResponsePacket(
@@ -3830,6 +3842,145 @@
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
 }
 
+// Regression test for http://crbug.com/791886.
+// This test verifies that the old packet writer which encountered an
+// asynchronous write error will be blocked during migration on write error. New
+// packets would not be written until the one with write error is rewritten on
+// the new network.
+TEST_P(QuicStreamFactoryTest, MigrateSessionOnAysncWriteError) {
+  InitializeConnectionMigrationV2Test(
+      {kDefaultNetworkForTests, kNewNetworkForTests});
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  // Using a testing task runner so that we can control time.
+  // base::RunLoop() controls mocked socket writes and reads.
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+  QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get());
+
+  MockQuicData socket_data;
+  quic::QuicStreamOffset header_stream_offset = 0;
+  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data.AddWrite(
+      SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset));
+  socket_data.AddWrite(ASYNC, ERR_ADDRESS_UNREACHABLE);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  // Set up second socket data provider that is used after
+  // migration. The request is rewritten to this new socket, and the
+  // response to the request is read on this new socket.
+  MockQuicData socket_data1;
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructGetRequestPacket(
+                                         2, GetNthClientInitiatedStreamId(0),
+                                         true, true, &header_stream_offset));
+  socket_data1.AddWrite(SYNCHRONOUS, ConstructGetRequestPacket(
+                                         3, GetNthClientInitiatedStreamId(1),
+                                         GetNthClientInitiatedStreamId(0), true,
+                                         true, &header_stream_offset));
+  socket_data1.AddRead(
+      ASYNC, ConstructOkResponsePacket(1, GetNthClientInitiatedStreamId(0),
+                                       false, false));
+  socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
+  socket_data1.AddWrite(SYNCHRONOUS,
+                        client_maker_.MakeAckAndRstPacket(
+                            4, false, GetNthClientInitiatedStreamId(0),
+                            quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true));
+  socket_data1.AddWrite(
+      SYNCHRONOUS,
+      client_maker_.MakeRstPacket(5, false, GetNthClientInitiatedStreamId(1),
+                                  quic::QUIC_STREAM_CANCELLED, 0));
+
+  socket_data1.AddSocketDataToFactory(socket_factory_.get());
+
+  // Create request #1 and QuicHttpStream.
+  QuicStreamRequest request1(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request1.Request(host_port_pair_, version_, privacy_mode_,
+                             DEFAULT_PRIORITY, SocketTag(),
+                             /*cert_verify_flags=*/0, url_, net_log_,
+                             &net_error_details_, callback_.callback()));
+  EXPECT_THAT(callback_.WaitForResult(), IsOk());
+  std::unique_ptr<HttpStream> stream1 = CreateStream(&request1);
+  EXPECT_TRUE(stream1.get());
+
+  HttpRequestInfo request_info1;
+  request_info1.method = "GET";
+  request_info1.url = GURL("https://www.example.org/");
+  request_info1.traffic_annotation =
+      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+  EXPECT_EQ(OK,
+            stream1->InitializeStream(&request_info1, true, DEFAULT_PRIORITY,
+                                      net_log_, CompletionOnceCallback()));
+
+  // Request #2 returns synchronously because it pools to existing session.
+  TestCompletionCallback callback2;
+  QuicStreamRequest request2(factory_.get());
+  EXPECT_EQ(OK, request2.Request(host_port_pair_, version_, privacy_mode_,
+                                 DEFAULT_PRIORITY, SocketTag(),
+                                 /*cert_verify_flags=*/0, url_, net_log_,
+                                 &net_error_details_, callback2.callback()));
+  std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
+  EXPECT_TRUE(stream2.get());
+
+  HttpRequestInfo request_info2;
+  request_info2.method = "GET";
+  request_info2.url = GURL("https://www.example.org/");
+  request_info2.traffic_annotation =
+      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+  EXPECT_EQ(OK,
+            stream2->InitializeStream(&request_info2, true, DEFAULT_PRIORITY,
+                                      net_log_, CompletionOnceCallback()));
+
+  // Ensure that session is alive and active.
+  QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+  EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+  EXPECT_TRUE(HasActiveSession(host_port_pair_));
+  EXPECT_EQ(2u, session->GetNumActiveStreams());
+
+  // Send GET request on stream1. This should cause an async write error.
+  HttpResponseInfo response;
+  HttpRequestHeaders request_headers;
+  EXPECT_EQ(OK, stream1->SendRequest(request_headers, &response,
+                                     callback_.callback()));
+  EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+
+  // Run the message loop so that asynchronous write completes and a connection
+  // migration on write error attempt is posted in QuicStreamFactory's task
+  // runner.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
+
+  // Send GET request on stream. This will cause another write attempt before
+  // migration on write error is exectued.
+  HttpResponseInfo response2;
+  HttpRequestHeaders request_headers2;
+  EXPECT_EQ(OK, stream2->SendRequest(request_headers2, &response2,
+                                     callback2.callback()));
+
+  // Run the task runner so that migration on write error is finally executed.
+  task_runner->RunUntilIdle();
+
+  // The session should now be marked as going away. Ensure that
+  // while it is still alive, it is no longer active.
+  EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+  EXPECT_FALSE(HasActiveSession(host_port_pair_));
+  EXPECT_EQ(2u, session->GetNumActiveStreams());
+
+  // Verify that response headers on the migrated socket were delivered to the
+  // stream.
+  EXPECT_EQ(OK, stream1->ReadResponseHeaders(callback_.callback()));
+  EXPECT_EQ(200, response.headers->response_code());
+
+  stream1.reset();
+  stream2.reset();
+
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+  EXPECT_TRUE(socket_data1.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
+}
+
 void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
     IoMode write_error_mode) {
   InitializeConnectionMigrationV2Test(
@@ -3838,6 +3989,8 @@
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
   crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
 
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+
   MockQuicData socket_data;
   quic::QuicStreamOffset header_stream_offset = 0;
   socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
diff --git a/net/reporting/reporting_cache.cc b/net/reporting/reporting_cache.cc
index f6db40c4..3f30793 100644
--- a/net/reporting/reporting_cache.cc
+++ b/net/reporting/reporting_cache.cc
@@ -197,27 +197,19 @@
     context_->NotifyCacheUpdated();
   }
 
-  void IncrementEndpointDeliveries(
-      const GURL& endpoint,
-      const std::vector<const ReportingReport*>& reports,
-      bool successful) override {
-    std::unordered_map<const ReportingClient*, int> reports_per_client;
-    for (const ReportingReport* report : reports) {
-      DCHECK(base::ContainsKey(reports_, report));
-      url::Origin origin = url::Origin::Create(report->url);
-      const ReportingClient* client =
-          GetClientByOriginAndEndpoint(origin, endpoint);
-      DCHECK(client);
-      reports_per_client[client]++;
-    }
-
-    for (const auto& client_and_report_count : reports_per_client) {
-      auto& metadata = client_metadata_[client_and_report_count.first];
+  void IncrementEndpointDeliveries(const url::Origin& origin,
+                                   const GURL& endpoint,
+                                   int reports_delivered,
+                                   bool successful) override {
+    const ReportingClient* client =
+        GetClientByOriginAndEndpoint(origin, endpoint);
+    if (client) {
+      auto& metadata = client_metadata_[client];
       metadata.stats.attempted_uploads++;
-      metadata.stats.attempted_reports += client_and_report_count.second;
+      metadata.stats.attempted_reports += reports_delivered;
       if (successful) {
         metadata.stats.successful_uploads++;
-        metadata.stats.successful_reports += client_and_report_count.second;
+        metadata.stats.successful_reports += reports_delivered;
       }
     }
   }
@@ -292,10 +284,7 @@
     context_->NotifyCacheUpdated();
   }
 
-  void MarkClientUsed(const url::Origin& origin,
-                      const GURL& endpoint) override {
-    const ReportingClient* client =
-        GetClientByOriginAndEndpoint(origin, endpoint);
+  void MarkClientUsed(const ReportingClient* client) override {
     DCHECK(client);
     client_metadata_[client].last_used = tick_clock()->NowTicks();
   }
diff --git a/net/reporting/reporting_cache.h b/net/reporting/reporting_cache.h
index 1c19b98..eda09b3 100644
--- a/net/reporting/reporting_cache.h
+++ b/net/reporting/reporting_cache.h
@@ -104,10 +104,10 @@
 
   // Records that we attempted (and possibly succeeded at) delivering |reports|
   // to |endpoint|.
-  virtual void IncrementEndpointDeliveries(
-      const GURL& endpoint,
-      const std::vector<const ReportingReport*>& reports,
-      bool successful) = 0;
+  virtual void IncrementEndpointDeliveries(const url::Origin& origin,
+                                           const GURL& endpoint,
+                                           int reports_delivered,
+                                           bool successful) = 0;
 
   // Removes a set of reports. Any reports that are pending will not be removed
   // immediately, but rather marked doomed and removed once they are no longer
@@ -134,8 +134,7 @@
                          int priority,
                          int client) = 0;
 
-  virtual void MarkClientUsed(const url::Origin& origin,
-                              const GURL& endpoint) = 0;
+  virtual void MarkClientUsed(const ReportingClient* client) = 0;
 
   // Gets all of the clients in the cache, regardless of origin or group.
   //
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc
index a2fbb9e..6d4dd30 100644
--- a/net/reporting/reporting_cache_unittest.cc
+++ b/net/reporting/reporting_cache_unittest.cc
@@ -411,18 +411,8 @@
   SetClient(kOrigin1_, kEndpoint1_, false, kGroup1_, expires);
   SetClient(kOrigin2_, kEndpoint2_, true, kGroup1_, expires);
 
-  // Add some reports so that we can test the upload counts.
-  const ReportingReport* report1a = AddAndReturnReport(
-      kUrl1_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0,
-      expires, 0);
-  const ReportingReport* report1b = AddAndReturnReport(
-      kUrl1_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0,
-      expires, 1);
-  const ReportingReport* report2 = AddAndReturnReport(
-      kUrl2_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0,
-      expires, 1);
-  cache()->IncrementEndpointDeliveries(kEndpoint1_, {report1a, report1b}, true);
-  cache()->IncrementEndpointDeliveries(kEndpoint2_, {report2}, false);
+  cache()->IncrementEndpointDeliveries(kOrigin1_, kEndpoint1_, 2, true);
+  cache()->IncrementEndpointDeliveries(kOrigin2_, kEndpoint2_, 1, false);
 
   base::Value actual = cache()->GetClientsAsValue();
   std::unique_ptr<base::Value> expected = base::test::ParseJson(R"json(
@@ -651,7 +641,9 @@
 
   // Use clients in reverse order, so client (max_client_count - 1) is LRU.
   for (size_t i = 1; i <= max_client_count; ++i) {
-    cache()->MarkClientUsed(kOrigin1_, MakeEndpoint(max_client_count - i));
+    const ReportingClient* client = FindClientInCache(
+        cache(), kOrigin1_, MakeEndpoint(max_client_count - i));
+    cache()->MarkClientUsed(client);
     tick_clock()->Advance(base::TimeDelta::FromSeconds(1));
   }
 
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc
index 238d37d..9d3105a 100644
--- a/net/reporting/reporting_delivery_agent.cc
+++ b/net/reporting/reporting_delivery_agent.cc
@@ -80,13 +80,19 @@
  private:
   class Delivery {
    public:
-    Delivery(const GURL& endpoint, std::vector<const ReportingReport*> reports)
-        : endpoint(endpoint), reports(std::move(reports)) {}
+    Delivery(const GURL& endpoint) : endpoint(endpoint) {}
 
     ~Delivery() = default;
 
+    void AddReports(const ReportingClient* client,
+                    const std::vector<const ReportingReport*>& to_add) {
+      reports_per_client[client->origin][client->endpoint] += to_add.size();
+      reports.insert(reports.end(), to_add.begin(), to_add.end());
+    }
+
     const GURL endpoint;
     std::vector<const ReportingReport*> reports;
+    std::map<url::Origin, std::map<GURL, int>> reports_per_client;
   };
 
   using OriginGroup = std::pair<url::Origin, std::string>;
@@ -146,24 +152,32 @@
     // Find endpoint for each (origin, group) bucket and sort reports into
     // endpoint buckets. Don't allow concurrent deliveries to the same (origin,
     // group) bucket.
-    std::map<GURL, std::vector<const ReportingReport*>> endpoint_reports;
+    std::map<GURL, std::unique_ptr<Delivery>> deliveries;
     for (auto& it : origin_group_reports) {
       const OriginGroup& origin_group = it.first;
 
       if (base::ContainsKey(pending_origin_groups_, origin_group))
         continue;
 
-      GURL endpoint_url;
-      if (!endpoint_manager()->FindEndpointForOriginAndGroup(
-              origin_group.first, origin_group.second, &endpoint_url)) {
+      const ReportingClient* client =
+          endpoint_manager()->FindClientForOriginAndGroup(origin_group.first,
+                                                          origin_group.second);
+      if (client == nullptr) {
         continue;
       }
+      cache()->MarkClientUsed(client);
 
-      cache()->MarkClientUsed(origin_group.first, endpoint_url);
+      Delivery* delivery;
+      auto delivery_it = deliveries.find(client->endpoint);
+      if (delivery_it == deliveries.end()) {
+        auto new_delivery = std::make_unique<Delivery>(client->endpoint);
+        delivery = new_delivery.get();
+        deliveries[client->endpoint] = std::move(new_delivery);
+      } else {
+        delivery = delivery_it->second.get();
+      }
 
-      endpoint_reports[endpoint_url].insert(
-          endpoint_reports[endpoint_url].end(), it.second.begin(),
-          it.second.end());
+      delivery->AddReports(client, it.second);
       pending_origin_groups_.insert(origin_group);
     }
 
@@ -172,18 +186,18 @@
     std::unordered_set<const ReportingReport*> undelivered_reports(
         reports.begin(), reports.end());
 
-    // Start a delivery to each endpoint.
-    for (auto& it : endpoint_reports) {
+    // Start an upload for each delivery.
+    for (auto& it : deliveries) {
       const GURL& endpoint = it.first;
-      const std::vector<const ReportingReport*>& reports = it.second;
+      std::unique_ptr<Delivery>& delivery = it.second;
 
       endpoint_manager()->SetEndpointPending(endpoint);
 
       std::string json;
-      SerializeReports(reports, tick_clock()->NowTicks(), &json);
+      SerializeReports(delivery->reports, tick_clock()->NowTicks(), &json);
 
       int max_depth = 0;
-      for (const ReportingReport* report : reports) {
+      for (const ReportingReport* report : delivery->reports) {
         undelivered_reports.erase(report);
         if (report->depth > max_depth)
           max_depth = report->depth;
@@ -192,10 +206,8 @@
       // TODO: Calculate actual max depth.
       uploader()->StartUpload(
           endpoint, json, max_depth,
-          base::BindOnce(
-              &ReportingDeliveryAgentImpl::OnUploadComplete,
-              weak_factory_.GetWeakPtr(),
-              std::make_unique<Delivery>(endpoint, std::move(reports))));
+          base::BindOnce(&ReportingDeliveryAgentImpl::OnUploadComplete,
+                         weak_factory_.GetWeakPtr(), std::move(delivery)));
     }
 
     cache()->ClearReportsPending(
@@ -204,9 +216,16 @@
 
   void OnUploadComplete(const std::unique_ptr<Delivery>& delivery,
                         ReportingUploader::Outcome outcome) {
-    cache()->IncrementEndpointDeliveries(
-        delivery->endpoint, delivery->reports,
-        outcome == ReportingUploader::Outcome::SUCCESS);
+    for (const auto& origin_and_pair : delivery->reports_per_client) {
+      const url::Origin& origin = origin_and_pair.first;
+      for (const auto& endpoint_and_count : origin_and_pair.second) {
+        const GURL& endpoint = endpoint_and_count.first;
+        int report_count = endpoint_and_count.second;
+        cache()->IncrementEndpointDeliveries(
+            origin, endpoint, report_count,
+            outcome == ReportingUploader::Outcome::SUCCESS);
+      }
+    }
 
     if (outcome == ReportingUploader::Outcome::SUCCESS) {
       cache()->RemoveReports(delivery->reports,
diff --git a/net/reporting/reporting_delivery_agent_unittest.cc b/net/reporting/reporting_delivery_agent_unittest.cc
index 6bf623a8..976ed4f 100644
--- a/net/reporting/reporting_delivery_agent_unittest.cc
+++ b/net/reporting/reporting_delivery_agent_unittest.cc
@@ -44,13 +44,16 @@
 
   void SetClient(const url::Origin& origin,
                  const GURL& endpoint,
-                 const std::string& group) {
-    cache()->SetClient(origin, endpoint, ReportingClient::Subdomains::EXCLUDE,
-                       group, tomorrow(), ReportingClient::kDefaultPriority,
+                 const std::string& group,
+                 ReportingClient::Subdomains subdomains =
+                     ReportingClient::Subdomains::EXCLUDE) {
+    cache()->SetClient(origin, endpoint, subdomains, group, tomorrow(),
+                       ReportingClient::kDefaultPriority,
                        ReportingClient::kDefaultWeight);
   }
 
   const GURL kUrl_ = GURL("https://origin/path");
+  const GURL kSubdomainUrl_ = GURL("https://sub.origin/path");
   const url::Origin kOrigin_ = url::Origin::Create(GURL("https://origin/"));
   const GURL kEndpoint_ = GURL("https://endpoint/");
   const std::string kGroup_ = "group";
@@ -92,7 +95,70 @@
   cache()->GetReports(&reports);
   EXPECT_TRUE(reports.empty());
 
-  // TODO(juliatuttle): Check that BackoffEntry was informed of success.
+  // TODO(dcreager): Check that BackoffEntry was informed of success.
+}
+
+TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateSubdomainUpload) {
+  base::DictionaryValue body;
+  body.SetString("key", "value");
+
+  SetClient(kOrigin_, kEndpoint_, kGroup_,
+            ReportingClient::Subdomains::INCLUDE);
+  cache()->AddReport(kSubdomainUrl_, kGroup_, kType_, body.CreateDeepCopy(), 0,
+                     tick_clock()->NowTicks(), 0);
+
+  // Upload is automatically started when cache is modified.
+
+  ASSERT_EQ(1u, pending_uploads().size());
+  EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
+  {
+    auto value = pending_uploads()[0]->GetValue();
+
+    base::ListValue* list;
+    ASSERT_TRUE(value->GetAsList(&list));
+    EXPECT_EQ(1u, list->GetSize());
+
+    base::DictionaryValue* report;
+    ASSERT_TRUE(list->GetDictionary(0, &report));
+    EXPECT_EQ(4u, report->size());
+
+    ExpectDictIntegerValue(0, *report, "age");
+    ExpectDictStringValue(kType_, *report, "type");
+    ExpectDictStringValue(kSubdomainUrl_.spec(), *report, "url");
+    ExpectDictDictionaryValue(body, *report, "report");
+  }
+  pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
+
+  // Successful upload should remove delivered reports.
+  std::vector<const ReportingReport*> reports;
+  cache()->GetReports(&reports);
+  EXPECT_TRUE(reports.empty());
+
+  // TODO(dcreager): Check that BackoffEntry was informed of success.
+}
+
+TEST_F(ReportingDeliveryAgentTest,
+       SuccessfulImmediateSubdomainUploadWithEvictedClient) {
+  base::DictionaryValue body;
+  body.SetString("key", "value");
+
+  SetClient(kOrigin_, kEndpoint_, kGroup_,
+            ReportingClient::Subdomains::INCLUDE);
+  cache()->AddReport(kSubdomainUrl_, kGroup_, kType_, body.CreateDeepCopy(), 0,
+                     tick_clock()->NowTicks(), 0);
+
+  // Upload is automatically started when cache is modified.
+
+  ASSERT_EQ(1u, pending_uploads().size());
+  // Evict the client
+  SetClient(kOrigin_, kEndpoint_, kGroup_,
+            ReportingClient::Subdomains::EXCLUDE);
+  pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
+
+  // Successful upload should remove delivered reports.
+  std::vector<const ReportingReport*> reports;
+  cache()->GetReports(&reports);
+  EXPECT_TRUE(reports.empty());
 }
 
 TEST_F(ReportingDeliveryAgentTest, SuccessfulDelayedUpload) {
diff --git a/net/reporting/reporting_endpoint_manager.cc b/net/reporting/reporting_endpoint_manager.cc
index b5aec56..4284648 100644
--- a/net/reporting/reporting_endpoint_manager.cc
+++ b/net/reporting/reporting_endpoint_manager.cc
@@ -35,9 +35,9 @@
 
   ~ReportingEndpointManagerImpl() override = default;
 
-  bool FindEndpointForOriginAndGroup(const url::Origin& origin,
-                                     const std::string& group,
-                                     GURL* endpoint_url_out) override {
+  const ReportingClient* FindClientForOriginAndGroup(
+      const url::Origin& origin,
+      const std::string& group) override {
     std::vector<const ReportingClient*> clients;
     cache()->GetClientsForOriginAndGroup(origin, group, &clients);
 
@@ -79,8 +79,7 @@
     }
 
     if (available_clients.empty()) {
-      *endpoint_url_out = GURL();
-      return false;
+      return nullptr;
     }
 
     int random_index = rand_callback_.Run(0, total_weight - 1);
@@ -89,14 +88,13 @@
       const ReportingClient* client = available_clients[i];
       weight_so_far += client->weight;
       if (random_index < weight_so_far) {
-        *endpoint_url_out = client->endpoint;
-        return true;
+        return client;
       }
     }
 
     // TODO(juliatuttle): Can we reach this in some weird overflow case?
     NOTREACHED();
-    return false;
+    return nullptr;
   }
 
   void SetEndpointPending(const GURL& endpoint) override {
diff --git a/net/reporting/reporting_endpoint_manager.h b/net/reporting/reporting_endpoint_manager.h
index 6df5f38..7d18da0 100644
--- a/net/reporting/reporting_endpoint_manager.h
+++ b/net/reporting/reporting_endpoint_manager.h
@@ -21,6 +21,8 @@
 
 namespace net {
 
+struct ReportingClient;
+
 // Keeps track of which endpoints are pending (have active delivery attempts to
 // them) or in exponential backoff after one or more failures, and chooses an
 // endpoint from an endpoint group to receive reports for an origin.
@@ -39,12 +41,11 @@
   // Deliberately chooses an endpoint randomly to ensure sites aren't relying on
   // any sort of fallback ordering.
   //
-  // Returns true and sets |*endpoint_url_out| to the endpoint URL if an
-  // endpoint was chosen; returns false (and leaves |*endpoint_url_out| invalid)
-  // if no endpoint was found.
-  virtual bool FindEndpointForOriginAndGroup(const url::Origin& origin,
-                                             const std::string& group,
-                                             GURL* endpoint_url_out) = 0;
+  // Returns the endpoint's |ReportingClient| if endpoint was chosen; returns
+  // nullptr if no endpoint was found.
+  virtual const ReportingClient* FindClientForOriginAndGroup(
+      const url::Origin& origin,
+      const std::string& group) = 0;
 
   // Adds |endpoint| to the set of pending endpoints, preventing it from being
   // chosen for a second parallel delivery attempt.
diff --git a/net/reporting/reporting_endpoint_manager_unittest.cc b/net/reporting/reporting_endpoint_manager_unittest.cc
index de26c00..26b6f32 100644
--- a/net/reporting/reporting_endpoint_manager_unittest.cc
+++ b/net/reporting/reporting_endpoint_manager_unittest.cc
@@ -33,21 +33,19 @@
 };
 
 TEST_F(ReportingEndpointManagerTest, NoEndpoint) {
-  GURL endpoint_url;
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 }
 
 TEST_F(ReportingEndpointManagerTest, Endpoint) {
   SetClient(kEndpoint_, ReportingClient::kDefaultPriority,
             ReportingClient::kDefaultWeight);
 
-  GURL endpoint_url;
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_TRUE(found_endpoint);
-  EXPECT_EQ(kEndpoint_, endpoint_url);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kEndpoint_, client->endpoint);
 }
 
 TEST_F(ReportingEndpointManagerTest, ExpiredEndpoint) {
@@ -57,10 +55,9 @@
   // Default expiration is "tomorrow", so make sure we're past that.
   tick_clock()->Advance(base::TimeDelta::FromDays(2));
 
-  GURL endpoint_url;
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 }
 
 TEST_F(ReportingEndpointManagerTest, PendingEndpoint) {
@@ -69,17 +66,15 @@
 
   endpoint_manager()->SetEndpointPending(kEndpoint_);
 
-  GURL endpoint_url;
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 
   endpoint_manager()->ClearEndpointPending(kEndpoint_);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_TRUE(found_endpoint);
-  EXPECT_EQ(kEndpoint_, endpoint_url);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kEndpoint_, client->endpoint);
 }
 
 TEST_F(ReportingEndpointManagerTest, BackedOffEndpoint) {
@@ -94,40 +89,35 @@
   endpoint_manager()->InformOfEndpointRequest(kEndpoint_, false);
 
   // After one failure, endpoint is in exponential backoff.
-  GURL endpoint_url;
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 
   // After initial delay, endpoint is usable again.
   tick_clock()->Advance(initial_delay);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_TRUE(found_endpoint);
-  EXPECT_EQ(kEndpoint_, endpoint_url);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kEndpoint_, client->endpoint);
 
   endpoint_manager()->InformOfEndpointRequest(kEndpoint_, false);
 
   // After a second failure, endpoint is backed off again.
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 
   tick_clock()->Advance(initial_delay);
 
   // Next backoff is longer -- 2x the first -- so endpoint isn't usable yet.
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 
   tick_clock()->Advance(initial_delay);
 
   // After 2x the initial delay, the endpoint is usable again.
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_TRUE(found_endpoint);
-  EXPECT_EQ(kEndpoint_, endpoint_url);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kEndpoint_, client->endpoint);
 
   endpoint_manager()->InformOfEndpointRequest(kEndpoint_, true);
   endpoint_manager()->InformOfEndpointRequest(kEndpoint_, true);
@@ -136,15 +126,13 @@
   // again.
   endpoint_manager()->InformOfEndpointRequest(kEndpoint_, false);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_FALSE(found_endpoint);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client == nullptr);
 
   tick_clock()->Advance(initial_delay);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  EXPECT_TRUE(found_endpoint);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  EXPECT_TRUE(client != nullptr);
 }
 
 // Make sure that multiple endpoints will all be returned at some point, to
@@ -163,15 +151,15 @@
   bool endpoint2_seen = false;
 
   for (int i = 0; i < kMaxAttempts; ++i) {
-    GURL endpoint_url;
-    bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-        kOrigin_, kGroup_, &endpoint_url);
-    ASSERT_TRUE(found_endpoint);
-    ASSERT_TRUE(endpoint_url == kEndpoint1 || endpoint_url == kEndpoint2);
+    const ReportingClient* client =
+        endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+    ASSERT_TRUE(client != nullptr);
+    ASSERT_TRUE(client->endpoint == kEndpoint1 ||
+                client->endpoint == kEndpoint2);
 
-    if (endpoint_url == kEndpoint1)
+    if (client->endpoint == kEndpoint1)
       endpoint1_seen = true;
-    else if (endpoint_url == kEndpoint2)
+    else if (client->endpoint == kEndpoint2)
       endpoint2_seen = true;
 
     if (endpoint1_seen && endpoint2_seen)
@@ -189,26 +177,22 @@
   SetClient(kPrimaryEndpoint, 10, ReportingClient::kDefaultWeight);
   SetClient(kBackupEndpoint, 20, ReportingClient::kDefaultWeight);
 
-  GURL endpoint_url;
-
-  bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  ASSERT_TRUE(found_endpoint);
-  EXPECT_EQ(kPrimaryEndpoint, endpoint_url);
+  const ReportingClient* client =
+      endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kPrimaryEndpoint, client->endpoint);
 
   endpoint_manager()->SetEndpointPending(kPrimaryEndpoint);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  ASSERT_TRUE(found_endpoint);
-  EXPECT_EQ(kBackupEndpoint, endpoint_url);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kBackupEndpoint, client->endpoint);
 
   endpoint_manager()->ClearEndpointPending(kPrimaryEndpoint);
 
-  found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-      kOrigin_, kGroup_, &endpoint_url);
-  ASSERT_TRUE(found_endpoint);
-  EXPECT_EQ(kPrimaryEndpoint, endpoint_url);
+  client = endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+  ASSERT_TRUE(client != nullptr);
+  EXPECT_EQ(kPrimaryEndpoint, client->endpoint);
 }
 
 // Note: This test depends on the deterministic mock RandIntCallback set up in
@@ -229,15 +213,15 @@
   int endpoint2_count = 0;
 
   for (int i = 0; i < kTotalEndpointWeight; ++i) {
-    GURL endpoint_url;
-    bool found_endpoint = endpoint_manager()->FindEndpointForOriginAndGroup(
-        kOrigin_, kGroup_, &endpoint_url);
-    ASSERT_TRUE(found_endpoint);
-    ASSERT_TRUE(endpoint_url == kEndpoint1 || endpoint_url == kEndpoint2);
+    const ReportingClient* client =
+        endpoint_manager()->FindClientForOriginAndGroup(kOrigin_, kGroup_);
+    ASSERT_TRUE(client != nullptr);
+    ASSERT_TRUE(client->endpoint == kEndpoint1 ||
+                client->endpoint == kEndpoint2);
 
-    if (endpoint_url == kEndpoint1)
+    if (client->endpoint == kEndpoint1)
       ++endpoint1_count;
-    else if (endpoint_url == kEndpoint2)
+    else if (client->endpoint == kEndpoint2)
       ++endpoint2_count;
   }
 
diff --git a/net/third_party/quic/core/chlo_extractor.cc b/net/third_party/quic/core/chlo_extractor.cc
index 9278c67..d299f2c 100644
--- a/net/third_party/quic/core/chlo_extractor.cc
+++ b/net/third_party/quic/core/chlo_extractor.cc
@@ -38,7 +38,6 @@
   void OnDecryptedPacket(EncryptionLevel level) override {}
   bool OnPacketHeader(const QuicPacketHeader& header) override;
   bool OnStreamFrame(const QuicStreamFrame& frame) override;
-  bool OnAckFrame(const QuicAckFrame& frame) override;
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override;
   bool OnAckRange(QuicPacketNumber start,
@@ -140,10 +139,6 @@
   return true;
 }
 
-bool ChloFramerVisitor::OnAckFrame(const QuicAckFrame& frame) {
-  return true;
-}
-
 bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
                                         QuicTime::Delta /*ack_delay_time*/) {
   return true;
diff --git a/net/third_party/quic/core/congestion_control/bandwidth_sampler.cc b/net/third_party/quic/core/congestion_control/bandwidth_sampler.cc
index e7fe2cf..d765575 100644
--- a/net/third_party/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/net/third_party/quic/core/congestion_control/bandwidth_sampler.cc
@@ -9,6 +9,7 @@
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
+#include "net/third_party/quic/platform/api/quic_logging.h"
 
 namespace quic {
 BandwidthSampler::BandwidthSampler()
@@ -119,10 +120,11 @@
   // always larger than the time of the previous packet, otherwise division by
   // zero or integer underflow can occur.
   if (ack_time <= sent_packet.last_acked_packet_ack_time) {
-    QUIC_BUG << "Time of the previously acked packet:"
-             << sent_packet.last_acked_packet_ack_time.ToDebuggingValue()
-             << " is larger than the ack time of the current packet:"
-             << ack_time.ToDebuggingValue();
+    QUIC_LOG(DFATAL)
+        << "Time of the previously acked packet:"
+        << sent_packet.last_acked_packet_ack_time.ToDebuggingValue()
+        << " is larger than the ack time of the current packet:"
+        << ack_time.ToDebuggingValue();
     return BandwidthSample();
   }
   QuicBandwidth ack_rate = QuicBandwidth::FromBytesAndTimeDelta(
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.cc b/net/third_party/quic/core/congestion_control/bbr_sender.cc
index 094f683..7bd00e7 100644
--- a/net/third_party/quic/core/congestion_control/bbr_sender.cc
+++ b/net/third_party/quic/core/congestion_control/bbr_sender.cc
@@ -25,13 +25,11 @@
 const QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;
 
 // The gain used for the slow start, equal to 2/ln(2).
-const float kHighGain = 2.885f;
+const float kDefaultHighGain = 2.885f;
 // The gain used in STARTUP after loss has been detected.
 // 1.5 is enough to allow for 25% exogenous loss and still observe a 25% growth
 // in measured bandwidth.
 const float kStartupAfterLossGain = 1.5f;
-// The gain used to drain the queue after the slow start.
-const float kDrainGain = 1.f / kHighGain;
 // The cycle of gains used during the PROBE_BW stage.
 const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1};
 
@@ -99,13 +97,13 @@
                                  kDefaultTCPMSS),
       max_congestion_window_(max_tcp_congestion_window * kDefaultTCPMSS),
       min_congestion_window_(kDefaultMinimumCongestionWindow),
+      high_gain_(kDefaultHighGain),
+      drain_gain_(1.f / kDefaultHighGain),
       pacing_rate_(QuicBandwidth::Zero()),
       pacing_gain_(1),
       congestion_window_gain_(1),
       congestion_window_gain_constant_(
           static_cast<float>(FLAGS_quic_bbr_cwnd_gain)),
-      rtt_variance_weight_(
-          static_cast<float>(FLAGS_quic_bbr_rtt_variation_weight)),
       num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup),
       exit_startup_on_loss_(false),
       cycle_current_offset_(0),
@@ -117,11 +115,11 @@
       exit_probe_rtt_at_(QuicTime::Zero()),
       probe_rtt_round_passed_(false),
       last_sample_is_app_limited_(false),
-      has_non_app_limited_sample_(
-          !GetQuicReloadableFlag(quic_bbr_slower_startup2)),
+      has_non_app_limited_sample_(false),
       recovery_state_(NOT_IN_RECOVERY),
       end_recovery_at_(0),
       recovery_window_(max_congestion_window_),
+      is_app_limited_recovery_(false),
       slower_startup_(false),
       rate_based_startup_(false),
       initial_conservation_in_startup_(CONSERVATION),
@@ -131,9 +129,6 @@
       probe_rtt_disabled_if_app_limited_(false),
       app_limited_since_last_probe_rtt_(false),
       min_rtt_since_last_probe_rtt_(QuicTime::Delta::Infinite()) {
-  if (!has_non_app_limited_sample_) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_slower_startup2);
-  }
   EnterStartupMode();
 }
 
@@ -176,8 +171,8 @@
 
 QuicBandwidth BbrSender::PacingRate(QuicByteCount bytes_in_flight) const {
   if (pacing_rate_.IsZero()) {
-    return kHighGain * QuicBandwidth::FromBytesAndTimeDelta(
-                           initial_congestion_window_, GetMinRtt());
+    return high_gain_ * QuicBandwidth::FromBytesAndTimeDelta(
+                            initial_congestion_window_, GetMinRtt());
   }
   return pacing_rate_;
 }
@@ -359,8 +354,8 @@
 
 void BbrSender::EnterStartupMode() {
   mode_ = STARTUP;
-  pacing_gain_ = kHighGain;
-  congestion_window_gain_ = kHighGain;
+  pacing_gain_ = high_gain_;
+  congestion_window_gain_ = high_gain_;
 }
 
 void BbrSender::EnterProbeBandwidthMode(QuicTime now) {
@@ -400,8 +395,7 @@
     const AckedPacketVector& acked_packets) {
   QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
   for (const auto& packet : acked_packets) {
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4) &&
-        packet.bytes_acked == 0) {
+    if (packet.bytes_acked == 0) {
       // Skip acked packets with 0 in flight bytes when updating bandwidth.
       continue;
     }
@@ -469,11 +463,7 @@
 void BbrSender::UpdateGainCyclePhase(QuicTime now,
                                      QuicByteCount prior_in_flight,
                                      bool has_losses) {
-  QuicByteCount bytes_in_flight = prior_in_flight;
-  if (GetQuicReloadableFlag(quic_bbr_fix_probe_bw)) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_fix_probe_bw);
-    bytes_in_flight = unacked_packets_->bytes_in_flight();
-  }
+  const QuicByteCount bytes_in_flight = unacked_packets_->bytes_in_flight();
   // In most cases, the cycle is advanced after an RTT passes.
   bool should_advance_gain_cycling = now - last_cycle_start_ > GetMinRtt();
 
@@ -532,8 +522,8 @@
 void BbrSender::MaybeExitStartupOrDrain(QuicTime now) {
   if (mode_ == STARTUP && is_at_full_bandwidth_) {
     mode_ = DRAIN;
-    pacing_gain_ = kDrainGain;
-    congestion_window_gain_ = kHighGain;
+    pacing_gain_ = drain_gain_;
+    congestion_window_gain_ = high_gain_;
   }
   if (mode_ == DRAIN &&
       unacked_packets_->bytes_in_flight() <= GetTargetCongestionWindow(1)) {
@@ -605,6 +595,11 @@
         // Since the conservation phase is meant to be lasting for a whole
         // round, extend the current round as if it were started right now.
         current_round_trip_end_ = last_sent_packet_;
+        if (GetQuicReloadableFlag(quic_bbr_app_limited_recovery) &&
+            last_sample_is_app_limited_) {
+          QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_app_limited_recovery);
+          is_app_limited_recovery_ = true;
+        }
       }
       break;
 
@@ -619,10 +614,14 @@
       // Exit recovery if appropriate.
       if (!has_losses && last_acked_packet > end_recovery_at_) {
         recovery_state_ = NOT_IN_RECOVERY;
+        is_app_limited_recovery_ = false;
       }
 
       break;
   }
+  if (recovery_state_ != NOT_IN_RECOVERY && is_app_limited_recovery_) {
+    sampler_->OnAppLimited();
+  }
 }
 
 // TODO(ianswett): Move this logic into BandwidthSampler.
@@ -685,11 +684,8 @@
 
   QuicByteCount target_window =
       GetTargetCongestionWindow(congestion_window_gain_);
-
-  if (rtt_variance_weight_ > 0.f && !BandwidthEstimate().IsZero()) {
-    target_window += rtt_variance_weight_ * rtt_stats_->mean_deviation() *
-                     BandwidthEstimate();
-  } else if (is_at_full_bandwidth_) {
+  if (is_at_full_bandwidth_) {
+    // Add the max recently measured ack aggregation to CWND.
     target_window += max_ack_height_.GetBest();
   }
 
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.h b/net/third_party/quic/core/congestion_control/bbr_sender.h
index 9656aed..ee2bae7 100644
--- a/net/third_party/quic/core/congestion_control/bbr_sender.h
+++ b/net/third_party/quic/core/congestion_control/bbr_sender.h
@@ -139,6 +139,18 @@
     return has_non_app_limited_sample_;
   }
 
+  // Sets the pacing and CWND gain used in STARTUP.  Must be greater than 1.
+  void set_high_gain(float high_gain) {
+    DCHECK_LT(1.0f, high_gain);
+    high_gain_ = high_gain;
+  }
+
+  // Sets the gain used in DRAIN.  Must be less than 1.
+  void set_drain_gain(float drain_gain) {
+    DCHECK_GT(1.0f, drain_gain);
+    drain_gain_ = drain_gain;
+  }
+
   DebugState ExportDebugState() const;
 
  private:
@@ -148,12 +160,6 @@
                          QuicRoundTripCount>
       MaxBandwidthFilter;
 
-  typedef WindowedFilter<QuicTime::Delta,
-                         MaxFilter<QuicTime::Delta>,
-                         QuicRoundTripCount,
-                         QuicRoundTripCount>
-      MaxAckDelayFilter;
-
   typedef WindowedFilter<QuicByteCount,
                          MaxFilter<QuicByteCount>,
                          QuicRoundTripCount,
@@ -269,6 +275,12 @@
   // The smallest value the |congestion_window_| can achieve.
   QuicByteCount min_congestion_window_;
 
+  // The pacing and CWND gain applied during the STARTUP phase.
+  float high_gain_;
+
+  // The pacing gain applied during the DRAIN phase.
+  float drain_gain_;
+
   // The current pacing rate of the connection.
   QuicBandwidth pacing_rate_;
 
@@ -280,9 +292,6 @@
   // The gain used for the congestion window during PROBE_BW.  Latched from
   // quic_bbr_cwnd_gain flag.
   const float congestion_window_gain_constant_;
-  // The coefficient by which mean RTT variance is added to the congestion
-  // window.  Latched from quic_bbr_rtt_variation_weight flag.
-  const float rtt_variance_weight_;
   // The number of RTTs to stay in STARTUP mode.  Defaults to 3.
   QuicRoundTripCount num_startup_rtts_;
   // If true, exit startup if 1RTT has passed with no bandwidth increase and
@@ -326,6 +335,8 @@
   QuicPacketNumber end_recovery_at_;
   // A window used to limit the number of bytes in flight during loss recovery.
   QuicByteCount recovery_window_;
+  // If true, consider all samples in recovery app-limited.
+  bool is_app_limited_recovery_;
 
   // When true, pace at 1.5x and disable packet conservation in STARTUP.
   bool slower_startup_;
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc
index 854d055..c173686 100644
--- a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc
@@ -684,6 +684,48 @@
   EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
 }
 
+// Verify that the first sample after PROBE_RTT is not used as the bandwidth,
+// because the round counter doesn't advance during PROBE_RTT.
+TEST_F(BbrSenderTest, AppLimitedRecoveryNoBandwidthDecrease) {
+  SetQuicReloadableFlag(quic_bbr_app_limited_recovery, true);
+  CreateDefaultSetup();
+  DriveOutOfStartup();
+
+  // We have no intention of ever finishing this transfer.
+  bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
+
+  // Wait until the connection enters PROBE_RTT.
+  const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(12);
+  bool simulator_result = simulator_.RunUntilOrTimeout(
+      [this]() {
+        return sender_->ExportDebugState().mode == BbrSender::PROBE_RTT;
+      },
+      timeout);
+  ASSERT_TRUE(simulator_result);
+  ASSERT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
+
+  const QuicBandwidth beginning_bw = sender_->BandwidthEstimate();
+
+  // Run for most of PROBE_RTT.
+  const QuicTime probe_rtt_start = clock_->Now();
+  const QuicTime::Delta time_to_exit_probe_rtt =
+      kTestRtt + QuicTime::Delta::FromMilliseconds(200);
+  simulator_.RunFor(0.60 * time_to_exit_probe_rtt);
+  EXPECT_EQ(BbrSender::PROBE_RTT, sender_->ExportDebugState().mode);
+  EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
+  // Lose a packet before exiting PROBE_RTT, which puts us in packet
+  // conservation and then continue there for a while and ensure the bandwidth
+  // estimate doesn't decrease.
+  for (int i = 0; i < 20; ++i) {
+    receiver_.DropNextIncomingPacket();
+    simulator_.RunFor(0.9 * kTestRtt);
+    // Ensure the bandwidth didn't decrease and the samples are app limited.
+    EXPECT_LE(beginning_bw, sender_->BandwidthEstimate());
+    EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
+  }
+  EXPECT_GE(sender_->ExportDebugState().min_rtt_timestamp, probe_rtt_start);
+}
+
 // Verify that the connection enters and exits PROBE_RTT correctly.
 TEST_F(BbrSenderTest, ProbeRttBDPBasedCWNDTarget) {
   CreateDefaultSetup();
diff --git a/net/third_party/quic/core/congestion_control/cubic_bytes_test.cc b/net/third_party/quic/core/congestion_control/cubic_bytes_test.cc
index 681c08c..d45f0001 100644
--- a/net/third_party/quic/core/congestion_control/cubic_bytes_test.cc
+++ b/net/third_party/quic/core/congestion_control/cubic_bytes_test.cc
@@ -11,8 +11,6 @@
 #include "net/third_party/quic/platform/api/quic_test.h"
 #include "net/third_party/quic/test_tools/mock_clock.h"
 
-using std::string;
-
 namespace quic {
 namespace test {
 namespace {
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
index 517b343..6324815 100644
--- a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -49,8 +49,8 @@
 
   void VerifyLosses(QuicPacketNumber largest_newly_acked,
                     const std::vector<QuicPacketNumber>& losses_expected) {
-    if (largest_newly_acked > unacked_packets_.largest_observed()) {
-      unacked_packets_.IncreaseLargestObserved(largest_newly_acked);
+    if (largest_newly_acked > unacked_packets_.largest_acked()) {
+      unacked_packets_.IncreaseLargestAcked(largest_newly_acked);
     }
     LostPacketVector lost_packets;
     loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
@@ -173,7 +173,7 @@
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
 
   // Early retransmit when the final packet gets acked and the first is nacked.
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   unacked_packets_.RemoveFromInFlight(2);
   VerifyLosses(2, std::vector<QuicPacketNumber>{});
   EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
@@ -188,7 +188,7 @@
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
 
   // Early retransmit when the final packet gets acked and the first is nacked.
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   unacked_packets_.RemoveFromInFlight(2);
   VerifyLosses(2, std::vector<QuicPacketNumber>{});
   EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
@@ -212,7 +212,7 @@
 
   // Wait another RTT and ack 2.
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   unacked_packets_.RemoveFromInFlight(2);
   VerifyLosses(2, {1});
 }
diff --git a/net/third_party/quic/core/congestion_control/pacing_sender.cc b/net/third_party/quic/core/congestion_control/pacing_sender.cc
index 157bf87..afedefb 100644
--- a/net/third_party/quic/core/congestion_control/pacing_sender.cc
+++ b/net/third_party/quic/core/congestion_control/pacing_sender.cc
@@ -24,7 +24,12 @@
       initial_burst_size_(kInitialUnpacedBurst),
       lumpy_tokens_(0),
       alarm_granularity_(QuicTime::Delta::FromMilliseconds(1)),
-      pacing_limited_(false) {}
+      pacing_limited_(false) {
+  if (GetQuicReloadableFlag(quic_donot_reset_ideal_next_packet_send_time)) {
+    QUIC_FLAG_COUNT(
+        quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time);
+  }
+}
 
 PacingSender::~PacingSender() {}
 
@@ -70,7 +75,9 @@
   }
   if (burst_tokens_ > 0) {
     --burst_tokens_;
-    ideal_next_packet_send_time_ = QuicTime::Zero();
+    if (!GetQuicReloadableFlag(quic_donot_reset_ideal_next_packet_send_time)) {
+      ideal_next_packet_send_time_ = QuicTime::Zero();
+    }
     pacing_limited_ = false;
     return;
   }
diff --git a/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc b/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
index 814927d..5e4b471 100644
--- a/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
@@ -33,7 +33,7 @@
                            initial_congestion_window, max_congestion_window,
                            random);
     case kPCC:
-      if (GetQuicReloadableFlag(quic_enable_pcc2)) {
+      if (GetQuicReloadableFlag(quic_enable_pcc3)) {
         return CreatePccSender(clock, rtt_stats, unacked_packets, random, stats,
                                initial_congestion_window,
                                max_congestion_window);
diff --git a/net/third_party/quic/core/crypto/crypto_protocol.h b/net/third_party/quic/core/crypto/crypto_protocol.h
index 5faeb36..886697c 100644
--- a/net/third_party/quic/core/crypto/crypto_protocol.h
+++ b/net/third_party/quic/core/crypto/crypto_protocol.h
@@ -142,13 +142,12 @@
 const QuicTag kSSLR = TAG('S', 'S', 'L', 'R');   // Slow Start Large Reduction.
 const QuicTag kNPRR = TAG('N', 'P', 'R', 'R');   // Pace at unity instead of PRR
 const QuicTag k5RTO = TAG('5', 'R', 'T', 'O');   // Close connection on 5 RTOs
-const QuicTag k3RTO = TAG('3', 'R', 'T', 'O');   // Close connection on 3 RTOs
 const QuicTag kCONH = TAG('C', 'O', 'N', 'H');   // Conservative Handshake
                                                  // Retransmissions.
 const QuicTag kLFAK = TAG('L', 'F', 'A', 'K');   // Don't invoke FACK on the
                                                  // first ack.
-// TODO(fayang): Remove this connection option in QUIC_VERSION_37, in which
-// MAX_HEADER_LIST_SIZE settings frame should be supported.
+// TODO(fayang): Remove this connection option when QUIC_VERSION_35, is removed
+// Since MAX_HEADER_LIST_SIZE settings frame is supported instead.
 const QuicTag kSMHL = TAG('S', 'M', 'H', 'L');   // Support MAX_HEADER_LIST_SIZE
                                                  // settings frame.
 const QuicTag kNSTP = TAG('N', 'S', 'T', 'P');   // No stop waiting frames.
diff --git a/net/third_party/quic/core/crypto/crypto_utils.cc b/net/third_party/quic/core/crypto/crypto_utils.cc
index 7a4bbd5..67b30762 100644
--- a/net/third_party/quic/core/crypto/crypto_utils.cc
+++ b/net/third_party/quic/core/crypto/crypto_utils.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "crypto/hkdf.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_encrypter.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake.h"
diff --git a/net/third_party/quic/core/crypto/null_decrypter_test.cc b/net/third_party/quic/core/crypto/null_decrypter_test.cc
index a6c48124..f0d05a0 100644
--- a/net/third_party/quic/core/crypto/null_decrypter_test.cc
+++ b/net/third_party/quic/core/crypto/null_decrypter_test.cc
@@ -24,7 +24,7 @@
   NullDecrypter decrypter(Perspective::IS_SERVER);
   char buffer[256];
   size_t length = 0;
-  ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_37, 0, "hello world!",
+  ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_39, 0, "hello world!",
                                       QuicStringPiece(data, len), buffer,
                                       &length, 256));
   EXPECT_LT(0u, length);
@@ -43,7 +43,7 @@
   NullDecrypter decrypter(Perspective::IS_CLIENT);
   char buffer[256];
   size_t length = 0;
-  ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_37, 0, "hello world!",
+  ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_39, 0, "hello world!",
                                       QuicStringPiece(data, len), buffer,
                                       &length, 256));
   EXPECT_LT(0u, length);
diff --git a/net/third_party/quic/core/crypto/null_encrypter_test.cc b/net/third_party/quic/core/crypto/null_encrypter_test.cc
index db0ce358..143e84f7 100644
--- a/net/third_party/quic/core/crypto/null_encrypter_test.cc
+++ b/net/third_party/quic/core/crypto/null_encrypter_test.cc
@@ -22,7 +22,7 @@
   char encrypted[256];
   size_t encrypted_len = 0;
   NullEncrypter encrypter(Perspective::IS_CLIENT);
-  ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_37, 0, "hello world!",
+  ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_39, 0, "hello world!",
                                       "goodbye!", encrypted, &encrypted_len,
                                       256));
   test::CompareCharArraysWithHexError(
@@ -40,7 +40,7 @@
   char encrypted[256];
   size_t encrypted_len = 0;
   NullEncrypter encrypter(Perspective::IS_SERVER);
-  ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_37, 0, "hello world!",
+  ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_39, 0, "hello world!",
                                       "goodbye!", encrypted, &encrypted_len,
                                       256));
   test::CompareCharArraysWithHexError(
diff --git a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
index 6e51958..e41a69d4 100644
--- a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
+++ b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
@@ -10,7 +10,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "crypto/hkdf.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/third_party/quic/core/crypto/cert_compressor.h"
diff --git a/net/third_party/quic/core/crypto/quic_decrypter.cc b/net/third_party/quic/core/crypto/quic_decrypter.cc
index df130aa..1bf4b37 100644
--- a/net/third_party/quic/core/crypto/quic_decrypter.cc
+++ b/net/third_party/quic/core/crypto/quic_decrypter.cc
@@ -4,7 +4,6 @@
 
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 
-#include "crypto/hkdf.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h"
 #include "net/third_party/quic/core/crypto/aes_256_gcm_decrypter.h"
diff --git a/net/third_party/quic/core/crypto/quic_random.cc b/net/third_party/quic/core/crypto/quic_random.cc
index f912c57..a7a9569 100644
--- a/net/third_party/quic/core/crypto/quic_random.cc
+++ b/net/third_party/quic/core/crypto/quic_random.cc
@@ -5,7 +5,6 @@
 #include "net/third_party/quic/core/crypto/quic_random.h"
 
 #include "base/macros.h"
-#include "base/memory/singleton.h"
 #include "crypto/random.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_singleton.h"
@@ -21,7 +20,6 @@
   // QuicRandom implementation
   void RandBytes(void* data, size_t len) override;
   uint64_t RandUint64() override;
-  void Reseed(const void* additional_entropy, size_t entropy_len) override;
 
  private:
   DefaultRandom() {}
@@ -45,10 +43,6 @@
   return value;
 }
 
-void DefaultRandom::Reseed(const void* additional_entropy, size_t entropy_len) {
-  // No such function exists in crypto/random.h.
-}
-
 }  // namespace
 
 // static
diff --git a/net/third_party/quic/core/crypto/quic_random.h b/net/third_party/quic/core/crypto/quic_random.h
index 659a2e48..1e31a6e 100644
--- a/net/third_party/quic/core/crypto/quic_random.h
+++ b/net/third_party/quic/core/crypto/quic_random.h
@@ -26,11 +26,6 @@
 
   // Returns a random number in the range [0, kuint64max].
   virtual uint64_t RandUint64() = 0;
-
-  // Reseeds the random number generator with additional entropy input.
-  // NOTE: the constructor of a QuicRandom object is responsible for seeding
-  // itself with enough entropy input.
-  virtual void Reseed(const void* additional_entropy, size_t entropy_len) = 0;
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/quic_random_test.cc b/net/third_party/quic/core/crypto/quic_random_test.cc
index 6e25cd6..8621be1 100644
--- a/net/third_party/quic/core/crypto/quic_random_test.cc
+++ b/net/third_party/quic/core/crypto/quic_random_test.cc
@@ -30,13 +30,5 @@
   EXPECT_NE(value1, value2);
 }
 
-TEST_F(QuicRandomTest, Reseed) {
-  char buf[1024];
-  memset(buf, 0xaf, sizeof(buf));
-
-  QuicRandom* rng = QuicRandom::GetInstance();
-  rng->Reseed(buf, sizeof(buf));
-}
-
 }  // namespace test
 }  // namespace quic
diff --git a/net/third_party/quic/core/end_to_end_test.cc b/net/third_party/quic/core/end_to_end_test.cc
index 8fd7c73c..d26e7ec 100644
--- a/net/third_party/quic/core/end_to_end_test.cc
+++ b/net/third_party/quic/core/end_to_end_test.cc
@@ -70,8 +70,14 @@
 #include "net/tools/epoll_server/epoll_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::IntToString;
-using base::WaitableEvent;
+using net::EpollEvent;
+using net::EpollServer;
+using spdy::kV3LowestPriority;
+using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
+using spdy::SpdyFramer;
+using spdy::SpdyHeaderBlock;
+using spdy::SpdySerializedFrame;
+using spdy::SpdySettingsIR;
 
 namespace quic {
 namespace test {
@@ -259,7 +265,7 @@
   explicit ClientDelegate(QuicClient* client) : client_(client) {}
   ~ClientDelegate() override = default;
   void OnCanWrite() override {
-    net::EpollEvent event(EPOLLOUT);
+    EpollEvent event(EPOLLOUT);
     client_->epoll_network_helper()->OnEvent(client_->GetLatestFD(), &event);
   }
 
@@ -394,7 +400,7 @@
     // client as well according to the test parameter.
     copt.push_back(GetParam().congestion_control_tag);
     if (GetParam().congestion_control_tag == kTPCC &&
-        GetQuicReloadableFlag(quic_enable_pcc2)) {
+        GetQuicReloadableFlag(quic_enable_pcc3)) {
       copt.push_back(kTPCC);
     }
 
@@ -411,7 +417,7 @@
     StartServer();
 
     CreateClientWithWriter();
-    static net::EpollEvent event(EPOLLOUT);
+    static EpollEvent event(EPOLLOUT);
     if (client_writer_ != nullptr) {
       client_writer_->Initialize(
           QuicConnectionPeer::GetHelper(
@@ -688,7 +694,7 @@
   ASSERT_TRUE(Initialize());
 
   // Send a request in two parts: the request and then an empty packet with FIN.
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -723,7 +729,7 @@
 
   const int kNumRequests = 10;
 
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -746,7 +752,7 @@
   ASSERT_TRUE(Initialize());
   std::unique_ptr<QuicTestClient> client2(CreateQuicClient(nullptr));
 
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -797,7 +803,7 @@
   ASSERT_TRUE(Initialize());
 
   // Add a content length header with no body.
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -819,7 +825,7 @@
 
   // 1 MB body.
   QuicString body(1024 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -840,7 +846,7 @@
 
   // 100 KB body.
   QuicString body(100 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -868,7 +874,7 @@
 
   // 10 KB body.
   QuicString body(1024 * 10, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -896,7 +902,7 @@
 
   // 10 KB body.
   QuicString body(1024 * 10, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -916,7 +922,7 @@
 
   // 1 MB body.
   QuicString body(1024 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -932,7 +938,7 @@
   ASSERT_TRUE(Initialize());
 
   QuicString body(20480, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1042,7 +1048,7 @@
   ASSERT_TRUE(Initialize());
 
   QuicString body(20480, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1142,7 +1148,7 @@
 
   // 1 MB body.
   QuicString body(1024 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1159,7 +1165,7 @@
   // Regression test for b/14677858.
   // Test that the resume write alarm is not set in QuicConnection::OnCanWrite
   // if currently connection level flow control blocked. If set, this results in
-  // an infinite loop in the net::EpollServer, as the alarm fires and is
+  // an infinite loop in the EpollServer, as the alarm fires and is
   // immediately rescheduled.
   ASSERT_TRUE(Initialize());
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
@@ -1203,7 +1209,7 @@
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   QuicString body(kMaxPacketSize, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1226,7 +1232,7 @@
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   QuicString body(kMaxPacketSize, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1245,7 +1251,7 @@
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   QuicString large_body(1024 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1309,7 +1315,7 @@
   QuicSessionPeer::SetMaxOpenOutgoingStreams(
       client_->client()->client_session(), kServerMaxStreams + 1);
 
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -1675,7 +1681,7 @@
 
   // Register the new FD for epoll events.
   int new_fd = client_->client()->GetLatestFD();
-  net::EpollServer* eps = client_->epoll_server();
+  EpollServer* eps = client_->epoll_server();
   eps->RegisterFD(new_fd, client_->client()->epoll_network_helper(),
                   EPOLLIN | EPOLLOUT | EPOLLET);
 
@@ -1873,56 +1879,46 @@
           ->flow_controller(),
       QuicSessionPeer::GetMutableCryptoStream(server_session)
           ->flow_controller());
-  spdy::SpdyFramer spdy_framer(spdy::SpdyFramer::ENABLE_COMPRESSION);
-  spdy::SpdySettingsIR settings_frame;
-  settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE,
+  SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
+  SpdySettingsIR settings_frame;
+  settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
                             kDefaultMaxUncompressedHeaderSize);
-  spdy::SpdySerializedFrame frame(spdy_framer.SerializeFrame(settings_frame));
+  SpdySerializedFrame frame(spdy_framer.SerializeFrame(settings_frame));
   QuicFlowController* client_header_stream_flow_controller =
       QuicSpdySessionPeer::GetHeadersStream(client_session)->flow_controller();
   QuicFlowController* server_header_stream_flow_controller =
       QuicSpdySessionPeer::GetHeadersStream(server_session)->flow_controller();
-  if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
-    // Both client and server are sending this SETTINGS frame, and the send
-    // window is consumed. But because of timing issue, the server may send or
-    // not send the frame, and the client may send/ not send / receive / not
-    // receive the frame.
-    // TODO(fayang): Rewrite this part because it is hacky.
-    QuicByteCount win_difference1 = QuicFlowControllerPeer::ReceiveWindowSize(
-                                        server_header_stream_flow_controller) -
-                                    QuicFlowControllerPeer::SendWindowSize(
-                                        client_header_stream_flow_controller);
-    QuicByteCount win_difference2 = QuicFlowControllerPeer::ReceiveWindowSize(
-                                        client_header_stream_flow_controller) -
-                                    QuicFlowControllerPeer::SendWindowSize(
-                                        server_header_stream_flow_controller);
-    EXPECT_TRUE(win_difference1 == 0 || win_difference1 == frame.size());
-    EXPECT_TRUE(win_difference2 == 0 || win_difference2 == frame.size());
-  } else {
-    ExpectFlowControlsSynced(
-        QuicSpdySessionPeer::GetHeadersStream(client_session)
-            ->flow_controller(),
-        QuicSpdySessionPeer::GetHeadersStream(server_session)
-            ->flow_controller());
-  }
+  // Both client and server are sending this SETTINGS frame, and the send
+  // window is consumed. But because of timing issue, the server may send or
+  // not send the frame, and the client may send/ not send / receive / not
+  // receive the frame.
+  // TODO(fayang): Rewrite this part because it is hacky.
+  QuicByteCount win_difference1 = QuicFlowControllerPeer::ReceiveWindowSize(
+                                      server_header_stream_flow_controller) -
+                                  QuicFlowControllerPeer::SendWindowSize(
+                                      client_header_stream_flow_controller);
+  QuicByteCount win_difference2 = QuicFlowControllerPeer::ReceiveWindowSize(
+                                      client_header_stream_flow_controller) -
+                                  QuicFlowControllerPeer::SendWindowSize(
+                                      server_header_stream_flow_controller);
+  EXPECT_TRUE(win_difference1 == 0 || win_difference1 == frame.size());
+  EXPECT_TRUE(win_difference2 == 0 || win_difference2 == frame.size());
 
-  if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
-    // Client *may* have received the SETTINGs frame.
-    // TODO(fayang): Rewrite this part because it is hacky.
-    float ratio1 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
-                       client_session->flow_controller())) /
-                   QuicFlowControllerPeer::ReceiveWindowSize(
-                       QuicSpdySessionPeer::GetHeadersStream(client_session)
-                           ->flow_controller());
-    float ratio2 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
-                       client_session->flow_controller())) /
-                   (QuicFlowControllerPeer::ReceiveWindowSize(
-                        QuicSpdySessionPeer::GetHeadersStream(client_session)
-                            ->flow_controller()) +
-                    frame.size());
-    EXPECT_TRUE(ratio1 == kSessionToStreamRatio ||
-                ratio2 == kSessionToStreamRatio);
-  }
+  // Client *may* have received the SETTINGs frame.
+  // TODO(fayang): Rewrite this part because it is hacky.
+  float ratio1 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
+                     client_session->flow_controller())) /
+                 QuicFlowControllerPeer::ReceiveWindowSize(
+                     QuicSpdySessionPeer::GetHeadersStream(client_session)
+                         ->flow_controller());
+  float ratio2 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize(
+                     client_session->flow_controller())) /
+                 (QuicFlowControllerPeer::ReceiveWindowSize(
+                      QuicSpdySessionPeer::GetHeadersStream(client_session)
+                          ->flow_controller()) +
+                  frame.size());
+  EXPECT_TRUE(ratio1 == kSessionToStreamRatio ||
+              ratio2 == kSessionToStreamRatio);
 
   server_thread_->Resume();
 }
@@ -1973,7 +1969,7 @@
 class TestResponseListener : public QuicSpdyClientBase::ResponseListener {
  public:
   void OnCompleteResponse(QuicStreamId id,
-                          const spdy::SpdyHeaderBlock& response_headers,
+                          const SpdyHeaderBlock& response_headers,
                           const QuicString& response_body) override {
     QUIC_DVLOG(1) << "response for stream " << id << " "
                   << response_headers.DebugString() << "\n"
@@ -1999,7 +1995,7 @@
   client_writer_->set_fake_blocked_socket_percentage(10);
 
   // Create a POST request and send the headers only.
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -2315,7 +2311,7 @@
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
   // Lose the request.
   SetPacketLossPercentage(100);
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -2347,7 +2343,7 @@
  protected:
   void SendErrorResponse() override {
     QUIC_DLOG(INFO) << "Sending error response for stream " << id();
-    spdy::SpdyHeaderBlock headers;
+    SpdyHeaderBlock headers;
     headers[":status"] = "500";
     headers["content-length"] =
         QuicTextUtils::Uint64ToString(response_body_.size());
@@ -2510,7 +2506,7 @@
   // and before the body is received, due to invalid content-length.
   // Set an invalid content-length, so the request will receive an early 500
   // response.
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/garbage";
   headers[":scheme"] = "https";
@@ -2561,12 +2557,12 @@
   // Add a response with headers, body, and trailers.
   const QuicString kBody = "body content";
 
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":status"] = "200";
   headers[":version"] = "HTTP/1.1";
   headers["content-length"] = QuicTextUtils::Uint64ToString(kBody.size());
 
-  spdy::SpdyHeaderBlock trailers;
+  SpdyHeaderBlock trailers;
   trailers["some-trailing-header"] = "trailing-header-value";
 
   memory_cache_backend_.AddResponse(server_hostname_, "/trailer_url",
@@ -2614,14 +2610,13 @@
           use_large_response
               ? large_resource
               : QuicStrCat("This is server push response body for ", url);
-      spdy::SpdyHeaderBlock response_headers;
+      SpdyHeaderBlock response_headers;
       response_headers[":version"] = "HTTP/1.1";
       response_headers[":status"] = "200";
       response_headers["content-length"] =
           QuicTextUtils::Uint64ToString(body.size());
       push_resources.push_back(QuicBackendResponse::ServerPushInfo(
-          resource_url, std::move(response_headers), spdy::kV3LowestPriority,
-          body));
+          resource_url, std::move(response_headers), kV3LowestPriority, body));
     }
 
     memory_cache_backend_.AddSimpleResponseWithServerPushResources(
@@ -2872,7 +2867,7 @@
   ASSERT_LT(INT64_C(4294967296), request_body_size_bytes);
   QuicString body(kSizeBytes, 'a');
 
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -2912,7 +2907,7 @@
   client->UseWriter(client_writer_);
   client->Connect();
   client_.reset(client);
-  static net::EpollEvent event(EPOLLOUT);
+  static EpollEvent event(EPOLLOUT);
   client_writer_->Initialize(
       QuicConnectionPeer::GetHelper(
           client_->client()->client_session()->connection()),
@@ -2945,7 +2940,7 @@
 
 TEST_P(EndToEndTest, WayTooLongRequestHeaders) {
   ASSERT_TRUE(Initialize());
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "GET";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -2988,7 +2983,7 @@
   QuicTransportVersion version = client_connection->transport_version();
   // 100KB body.
   QuicString body(100 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -2997,7 +2992,7 @@
   EXPECT_EQ(kFooResponseBody,
             client_->SendCustomSynchronousRequest(headers, body));
   client_->Disconnect();
-  if (version > QUIC_VERSION_38) {
+  if (version != QUIC_VERSION_35) {
     EXPECT_LT(0u, observer.num_window_update_frames());
     EXPECT_EQ(0u, observer.num_ping_frames());
   } else {
@@ -3025,7 +3020,7 @@
 
   // 1 MB body.
   QuicString body(1024 * 1024, 'a');
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/foo";
   headers[":scheme"] = "https";
@@ -3112,7 +3107,7 @@
   // INCOMPLETE_RESPONSE will cause the server to not to send the trailer
   // (and the FIN) after the response body.
   QuicString response_body(1305, 'a');
-  spdy::SpdyHeaderBlock response_headers;
+  SpdyHeaderBlock response_headers;
   response_headers[":status"] = QuicTextUtils::Uint64ToString(200);
   response_headers["content-length"] =
       QuicTextUtils::Uint64ToString(response_body.length());
@@ -3143,7 +3138,7 @@
 class EndToEndPacketReorderingTest : public EndToEndTest {
  public:
   void CreateClientWithWriter() override {
-    QUIC_LOG(ERROR) << "create client with reorder_writer_ ";
+    QUIC_LOG(ERROR) << "create client with reorder_writer_";
     reorder_writer_ = new PacketReorderingWriter();
     client_.reset(EndToEndTest::CreateQuicClient(reorder_writer_));
   }
@@ -3223,7 +3218,7 @@
   ASSERT_TRUE(client_->client()->connected());
 
   // Send a request before handshake finishes.
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
   headers[":method"] = "POST";
   headers[":path"] = "/bar";
   headers[":scheme"] = "https";
diff --git a/net/third_party/quic/core/proto/quic_trace.proto b/net/third_party/quic/core/proto/quic_trace.proto
deleted file mode 100644
index c6aa954..0000000
--- a/net/third_party/quic/core/proto/quic_trace.proto
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file describes a format for a trace containing all events related to the
-// QUIC connection.  It is primarily focused on representing information related
-// to congestion control and loss recovery.  It's entirely up to implementation
-// which fields to populate; the consumers of the data should not assume all of
-// the frames are recorded in either direction.
-//
-// This format is intended to be usable by any QUIC implementation.  It is
-// primarily based on IETF QUIC (draft 11), but has a few legacy gQUIC entries,
-// and can be potentially extended in the future.
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package quic_trace;
-
-enum FrameType {
-  UNKNOWN_FRAME = 0;
-
-  STREAM = 1;
-  ACK = 2;
-  RESET_STREAM = 3;
-  CONNECTION_CLOSE = 4;
-  MAX_DATA = 5;
-  MAX_STREAM_DATA = 6;
-  PING = 7;
-  BLOCKED = 8;
-  STREAM_BLOCKED = 9;
-  PADDING = 10;
-};
-
-// Metadata for STREAM frames.
-message StreamFrameInfo {
-  optional uint64 stream_id = 1;
-  optional bool fin = 2;
-  optional uint64 length = 3;
-  optional uint64 offset = 4;
-};
-
-// The intervals are closed, i.e. the interval represented here is
-// [first_packet, last_packet].
-message AckBlock {
-  optional uint64 first_packet = 1;
-  optional uint64 last_packet = 2;
-};
-
-// Metadata for ACK frames.
-message AckInfo {
-  repeated AckBlock acked_packets = 1;
-  optional uint64 ack_delay_us = 2;
-};
-
-// Metadata for RST_STREAM frames.
-message ResetStreamInfo {
-  optional uint64 stream_id = 1;
-  optional uint32 application_error_code = 2;
-  optional uint64 final_offset = 3;
-};
-
-// Metadata for CONNECTION_CLOSE/APPLICATION_CLOSE frames.
-message CloseInfo {
-  optional uint32 error_code = 1;
-  optional string reason_phrase = 2;
-};
-
-// Metadata for MAX_DATA/MAX_STREAM_DATA frames.
-message FlowControlInfo {
-  optional uint64 max_data = 1;
-  optional uint64 stream_id = 2;
-};
-
-// A message representing a frame, either sent or received.
-message Frame {
-  optional FrameType frame_type = 1;
-
-  optional StreamFrameInfo stream_frame_info = 2;
-  optional AckInfo ack_info = 3;
-  optional ResetStreamInfo reset_stream_info = 4;
-  optional CloseInfo close_info = 5;
-  optional FlowControlInfo flow_control_info = 6;
-};
-
-// Metadata that represents transport stack's understanding of the current state
-// of the transport channel.
-message TransportState {
-  optional uint64 min_rtt_us = 1;
-  // Smoothed RTT, usually computed using EWMA.
-  optional uint64 smoothed_rtt_us = 2;
-  // The latest RTT measureent available.
-  optional uint64 last_rtt_us = 3;
-
-  optional uint64 in_flight_bytes = 4;
-  optional uint64 cwnd_bytes = 5;
-  // Pacing rate, in bits per second.
-  optional uint64 pacing_rate_bps = 6;
-
-  // Any arbitrary information about congestion control state that is not
-  // representable via parameters above.
-  optional string congestion_control_state = 7;
-};
-
-enum EncryptionLevel {
-  ENCRYPTION_UNKNOWN = 0;
-
-  ENCRYPTION_INITIAL = 1;
-  ENCRYPTION_0RTT = 2;
-  ENCRYPTION_1RTT = 3;
-};
-
-enum EventType {
-  UNKNOWN_EVENT = 0;
-
-  PACKET_SENT = 1;
-  PACKET_RECEIVED = 2;
-  PACKET_LOST = 3;
-};
-
-// An event that has occurred over duration of the connection.
-message Event {
-  optional uint64 time_us = 1;
-  optional EventType event_type = 2;
-
-  optional uint64 packet_number = 3;
-  repeated Frame frames = 4;
-  optional uint64 packet_size = 5;
-  optional EncryptionLevel encryption_level = 6;
-  // State of the transport stack after the event has happened.
-  optional TransportState transport_state = 7;
-};
-
-message Trace {
-  // QUIC version tag, as represented on wire.  Should be always 4 bytes long.
-  optional bytes protocol_version = 1;
-
-  // Source and destination connection ID.  If multiple connection IDs are used,
-  // record the first one used with short-form header.
-  optional bytes source_connection_id = 2;
-  optional bytes destination_connection_id = 3;
-
-  repeated Event events = 4;
-};
diff --git a/net/third_party/quic/core/quic_config.cc b/net/third_party/quic/core/quic_config.cc
index b516ac8..23fe58e 100644
--- a/net/third_party/quic/core/quic_config.cc
+++ b/net/third_party/quic/core/quic_config.cc
@@ -668,9 +668,7 @@
 
   SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
   SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
-  if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
-    SetSupportMaxHeaderListSize();
-  }
+  SetSupportMaxHeaderListSize();
 }
 
 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc
index 94393e0..12892037 100644
--- a/net/third_party/quic/core/quic_connection.cc
+++ b/net/third_party/quic/core/quic_connection.cc
@@ -49,7 +49,7 @@
 const QuicPacketNumber kMaxPacketGap = 5000;
 
 // Maximum number of acks received before sending an ack in response.
-// TODO(fayang): Remove this constant when deprecating QUIC_VERSION_38.
+// TODO(fayang): Remove this constant when deprecating QUIC_VERSION_35.
 const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20;
 
 // Maximum number of consecutive sent nonretransmittable packets.
@@ -239,7 +239,6 @@
       idle_timeout_connection_close_behavior_(
           ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET),
       close_connection_after_five_rtos_(false),
-      close_connection_after_three_rtos_(false),
       received_packet_manager_(&stats_),
       ack_queued_(false),
       num_retransmittable_packets_received_since_last_ack_sent_(0),
@@ -321,7 +320,10 @@
       deprecate_scheduler_(
           GetQuicReloadableFlag(quic_deprecate_scoped_scheduler2)),
       add_to_blocked_list_if_writer_blocked_(
-          GetQuicReloadableFlag(quic_add_to_blocked_list_if_writer_blocked)) {
+          GetQuicReloadableFlag(quic_add_to_blocked_list_if_writer_blocked)),
+      ack_reordered_packets_(GetQuicReloadableFlag(quic_ack_reordered_packets)),
+      retransmissions_app_limited_(
+          GetQuicReloadableFlag(quic_retransmissions_app_limited)) {
   if (ack_mode_ == ACK_DECIMATION) {
     QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_ack_decimation);
   }
@@ -431,12 +433,7 @@
   if (config.HasClientSentConnectionOption(k5RTO, perspective_)) {
     close_connection_after_five_rtos_ = true;
   }
-  if (GetQuicReloadableFlag(quic_enable_3rtos) &&
-      config.HasClientSentConnectionOption(k3RTO, perspective_)) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_3rtos);
-    close_connection_after_three_rtos_ = true;
-  }
-  if (transport_version() > QUIC_VERSION_37 &&
+  if (transport_version() != QUIC_VERSION_35 &&
       config.HasClientSentConnectionOption(kNSTP, perspective_)) {
     no_stop_waiting_frames_ = true;
   }
@@ -864,59 +861,9 @@
   return connected_;
 }
 
-bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
-  DCHECK(connected_);
-  DCHECK(!framer_.use_incremental_ack_processing());
-
-  // Since an ack frame was received, this is not a connectivity probe.
-  // A probe only contains a PING and full padding.
-  UpdatePacketContent(NOT_PADDED_PING);
-
-  if (debug_visitor_ != nullptr) {
-    debug_visitor_->OnAckFrame(incoming_ack);
-  }
-  QUIC_DVLOG(1) << ENDPOINT << "OnAckFrame: " << incoming_ack;
-
-  if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
-    QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
-    return true;
-  }
-
-  const char* error = ValidateAckFrame(incoming_ack);
-  if (error != nullptr) {
-    CloseConnection(QUIC_INVALID_ACK_DATA, error,
-                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-    return false;
-  }
-
-  if (send_alarm_->IsSet()) {
-    send_alarm_->Cancel();
-  }
-
-  if (LargestAcked(incoming_ack) > sent_packet_manager_.GetLargestObserved()) {
-    visitor_->OnForwardProgressConfirmed();
-  }
-
-  largest_seen_packet_with_ack_ = last_header_.packet_number;
-  bool acked_new_packet = sent_packet_manager_.OnIncomingAck(
-      incoming_ack, time_of_last_received_packet_);
-  // If the incoming ack's packets set expresses missing packets: peer is still
-  // waiting for a packet lower than a packet that we are no longer planning to
-  // send.
-  // If the incoming ack's packets set expresses received packets: peer is still
-  // acking packets which we never care about.
-  // Send an ack to raise the high water mark.
-  PostProcessAfterAckFrame(!incoming_ack.packets.Empty() &&
-                               GetLeastUnacked() > incoming_ack.packets.Min(),
-                           acked_new_packet);
-
-  return connected_;
-}
-
 bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
                                      QuicTime::Delta ack_delay_time) {
   DCHECK(connected_);
-  DCHECK(framer_.use_incremental_ack_processing());
 
   if (processing_ack_frame_) {
     CloseConnection(QUIC_INVALID_ACK_DATA,
@@ -977,7 +924,6 @@
                                 QuicPacketNumber end,
                                 bool last_range) {
   DCHECK(connected_);
-  DCHECK(framer_.use_incremental_ack_processing());
   QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end
                 << "), last_range: " << last_range;
 
@@ -992,6 +938,9 @@
   }
   bool acked_new_packet =
       sent_packet_manager_.OnAckFrameEnd(time_of_last_received_packet_);
+  // Cancel the send alarm because new packets likely have been acked, which
+  // may change the congestion window and/or pacing rate.  Canceling the alarm
+  // causes CanWrite to recalculate the next send time.
   if (send_alarm_->IsSet()) {
     send_alarm_->Cancel();
   }
@@ -1336,7 +1285,7 @@
   ++num_packets_received_since_last_ack_sent_;
   // Always send an ack every 20 packets in order to allow the peer to discard
   // information from the SentPacketManager and provide an RTT measurement.
-  if (transport_version() <= QUIC_VERSION_38 &&
+  if (transport_version() == QUIC_VERSION_35 &&
       num_packets_received_since_last_ack_sent_ >=
           kMaxPacketsReceivedBeforeAckSend) {
     ack_queued_ = true;
@@ -1344,11 +1293,24 @@
 
   // Determine whether the newly received packet was missing before recording
   // the received packet.
-  // Ack decimation with reordering relies on the timer to send an ack, but if
-  // missing packets we reported in the previous ack, send an ack immediately.
-  if (was_missing && (ack_mode_ != ACK_DECIMATION_WITH_REORDERING ||
-                      last_ack_had_missing_packets_)) {
-    ack_queued_ = true;
+  if (was_missing) {
+    if (ack_reordered_packets_) {
+      QUIC_FLAG_COUNT(quic_reloadable_flag_quic_ack_reordered_packets);
+      // Only ack immediately if an ACK frame was sent with a larger
+      // largest acked than the newly received packet number.
+      if (last_header_.packet_number <
+          sent_packet_manager_.unacked_packets().largest_sent_largest_acked()) {
+        ack_queued_ = true;
+      }
+    } else {
+      // Ack decimation with reordering relies on the timer to send an ack,
+      // but if missing packets we reported in the previous ack, send an ack
+      // immediately.
+      if (ack_mode_ != ACK_DECIMATION_WITH_REORDERING ||
+          last_ack_had_missing_packets_) {
+        ack_queued_ = true;
+      }
+    }
   }
 
   if (should_last_packet_instigate_acks_ && !ack_queued_) {
@@ -1726,11 +1688,22 @@
 void QuicConnection::OnCanWrite() {
   DCHECK(!writer_->IsWriteBlocked());
 
+  std::unique_ptr<ScopedPacketFlusher> flusher;
+  if (retransmissions_app_limited_) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_retransmissions_app_limited);
+    // Add a flusher to ensure the connection is marked app-limited.
+    flusher.reset(new ScopedPacketFlusher(this, NO_ACK));
+  }
+
   WriteQueuedPackets();
   if (!session_decides_what_to_write()) {
     WritePendingRetransmissions();
   }
 
+  WriteNewData();
+}
+
+void QuicConnection::WriteNewData() {
   // Sending queued packets may have caused the socket to become write blocked,
   // or the congestion manager to prohibit sending.  If we've sent everything
   // we had queued and we're still not blocked, let the visitor know it can
@@ -1907,12 +1880,10 @@
   DCHECK(!session_decides_what_to_write());
   // Keep writing as long as there's a pending retransmission which can be
   // written.
-  while (sent_packet_manager_.HasPendingRetransmissions()) {
+  while (sent_packet_manager_.HasPendingRetransmissions() &&
+         CanWrite(HAS_RETRANSMITTABLE_DATA)) {
     const QuicPendingRetransmission pending =
         sent_packet_manager_.NextPendingRetransmission();
-    if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
-      break;
-    }
 
     // Re-packetize the frames with a new packet number for retransmission.
     // Retransmitted packets use the same packet number length as the
@@ -1927,6 +1898,7 @@
       ScopedPacketFlusher flusher(this, NO_ACK);
       packet_generator_.FlushAllQueuedFrames();
     }
+    DCHECK(!packet_generator_.HasQueuedFrames());
     char buffer[kMaxPacketSize];
     packet_generator_.ReserializeAllFrames(pending, buffer, kMaxPacketSize);
   }
@@ -2270,7 +2242,7 @@
     return;
   }
 
-  if (transport_version() > QUIC_VERSION_38) {
+  if (transport_version() != QUIC_VERSION_35) {
     if (serialized_packet->retransmittable_frames.empty() &&
         serialized_packet->original_packet_number == 0) {
       // Increment consecutive_num_packets_with_no_retransmittable_frames_ if
@@ -2350,7 +2322,10 @@
   ack_queued_ = false;
   stop_waiting_count_ = 0;
   num_retransmittable_packets_received_since_last_ack_sent_ = 0;
-  last_ack_had_missing_packets_ = received_packet_manager_.HasMissingPackets();
+  if (!ack_reordered_packets_) {
+    last_ack_had_missing_packets_ =
+        received_packet_manager_.HasMissingPackets();
+  }
   num_packets_received_since_last_ack_sent_ = 0;
 
   packet_generator_.SetShouldSendAck(!no_stop_waiting_frames_);
@@ -2374,15 +2349,6 @@
 
 void QuicConnection::OnRetransmissionTimeout() {
   DCHECK(sent_packet_manager_.HasUnackedPackets());
-
-  if (close_connection_after_three_rtos_ &&
-      sent_packet_manager_.GetConsecutiveRtoCount() >= 2 &&
-      !visitor_->HasOpenDynamicStreams()) {
-    // Close on the 3rd consecutive RTO, so after 2 previous RTOs have occurred.
-    CloseConnection(QUIC_TOO_MANY_RTOS, "3 consecutive retransmission timeouts",
-                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-    return;
-  }
   if (close_connection_after_five_rtos_ &&
       sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
     // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h
index 1fd4e0e..404a8902 100644
--- a/net/third_party/quic/core/quic_connection.h
+++ b/net/third_party/quic/core/quic_connection.h
@@ -416,7 +416,7 @@
 
   // Called when an error occurs while attempting to write a packet to the
   // network.
-  void OnWriteError(int error_code);
+  virtual void OnWriteError(int error_code);
 
   // Whether |result| represents a MSG TOO BIG write error.
   bool IsMsgTooBig(const WriteResult& result);
@@ -468,7 +468,6 @@
   void OnDecryptedPacket(EncryptionLevel level) override;
   bool OnPacketHeader(const QuicPacketHeader& header) override;
   bool OnStreamFrame(const QuicStreamFrame& frame) override;
-  bool OnAckFrame(const QuicAckFrame& frame) override;
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override;
   bool OnAckRange(QuicPacketNumber start,
@@ -927,6 +926,9 @@
   // Writes as many pending retransmissions as possible.
   void WritePendingRetransmissions();
 
+  // Writes new data if congestion control allows.
+  void WriteNewData();
+
   // Queues |packet| in the hopes that it can be decrypted in the
   // future, when a new key is installed.
   void QueueUndecryptablePacket(const QuicEncryptedPacket& packet);
@@ -1106,9 +1108,6 @@
   // When true, close the QUIC connection after 5 RTOs.  Due to the min rto of
   // 200ms, this is over 5 seconds.
   bool close_connection_after_five_rtos_;
-  // When true, close the QUIC connection when there are no open streams after
-  // 3 consecutive RTOs.
-  bool close_connection_after_three_rtos_;
 
   QuicReceivedPacketManager received_packet_manager_;
 
@@ -1117,6 +1116,8 @@
   // How many retransmittable packets have arrived without sending an ack.
   QuicPacketCount num_retransmittable_packets_received_since_last_ack_sent_;
   // Whether there were missing packets in the last sent ack.
+  // TODO(ianswett): Deprecate with
+  // quic_reloadable_flag_quic_ack_reordered_packets.
   bool last_ack_had_missing_packets_;
   // How many consecutive packets have arrived without sending an ack.
   QuicPacketCount num_packets_received_since_last_ack_sent_;
@@ -1317,6 +1318,12 @@
   // gfe2_reloadable_flag_quic_add_to_blocked_list_if_writer_blocked.
   const bool add_to_blocked_list_if_writer_blocked_;
 
+  // Latched value of quic_reloadable_flag_quic_ack_reordered_packets.
+  const bool ack_reordered_packets_;
+
+  // Latched value of quic_reloadable_flag_quic_retransmissions_app_limited.
+  const bool retransmissions_app_limited_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicConnection);
 };
 
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc
index 5848e41..72afe38 100644
--- a/net/third_party/quic/core/quic_connection_test.cc
+++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -2155,7 +2155,7 @@
 }
 
 TEST_P(QuicConnectionTest, 20AcksCausesAckSend) {
-  if (connection_.version().transport_version > QUIC_VERSION_38) {
+  if (connection_.version().transport_version != QUIC_VERSION_35) {
     return;
   }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -2177,7 +2177,7 @@
 }
 
 TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
-  if (connection_.version().transport_version <= QUIC_VERSION_38) {
+  if (connection_.version().transport_version == QUIC_VERSION_35) {
     return;
   }
 
@@ -2843,6 +2843,12 @@
   // Ensure that the data is still in flight, but the retransmission alarm is no
   // longer set.
   EXPECT_GT(QuicSentPacketManagerPeer::GetBytesInFlight(manager_), 0u);
+  if (GetQuicReloadableFlag(quic_optimize_inflight_check)) {
+    EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+    // Firing the alarm should remove all bytes_in_flight.
+    connection_.GetRetransmissionAlarm()->Fire();
+    EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
+  }
   EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
 }
 
@@ -2957,9 +2963,7 @@
 
   // Now, ack the previous transmission.
   EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _));
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    EXPECT_CALL(*send_algorithm_, OnCongestionEvent(false, _, _, _, _));
-  }
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(false, _, _, _, _));
   QuicAckFrame ack_all = InitAckFrame(3);
   ProcessAckPacket(&ack_all);
 
@@ -3084,6 +3088,12 @@
   writer_->SetWritable();
   connection_.OnCanWrite();
   // There is now a pending packet, but with no retransmittable frames.
+  if (GetQuicReloadableFlag(quic_optimize_inflight_check)) {
+    EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+    // Firing the alarm should remove all bytes_in_flight.
+    connection_.GetRetransmissionAlarm()->Fire();
+    EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
+  }
   EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
   EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, 2));
 }
@@ -4482,39 +4492,6 @@
   EXPECT_FALSE(connection_.connected());
 }
 
-TEST_P(QuicConnectionTest, TimeoutAfter3ClientRTOs) {
-  SetQuicReloadableFlag(quic_enable_3rtos, true);
-  connection_.SetMaxTailLossProbes(2);
-  EXPECT_TRUE(connection_.connected());
-  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
-  QuicConfig config;
-  QuicTagVector connection_options;
-  connection_options.push_back(k3RTO);
-  config.SetConnectionOptionsToSend(connection_options);
-  connection_.SetFromConfig(config);
-
-  // Send stream data.
-  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr);
-
-  // Fire the retransmission alarm 4 times, twice for TLP and 2 times for RTO.
-  for (int i = 0; i < 4; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
-    connection_.GetRetransmissionAlarm()->Fire();
-    EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
-    EXPECT_TRUE(connection_.connected());
-  }
-
-  EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
-  EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
-  // This time, we should time out.
-  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_TOO_MANY_RTOS, _,
-                                           ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
-  connection_.GetRetransmissionAlarm()->Fire();
-  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
-  EXPECT_FALSE(connection_.connected());
-}
-
 TEST_P(QuicConnectionTest, SendScheduler) {
   // Test that if we send a packet without delay, it is not queued.
   QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
@@ -5102,41 +5079,42 @@
     ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
   }
   EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
-  // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
-  // instead of ENCRYPTION_NONE.
-  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
-  ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
-                           ENCRYPTION_INITIAL);
 
-  // Check if delayed ack timer is running for the expected interval.
-  EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
-  EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
-
-  // Process packet 10 first and ensure the alarm is one eighth min_rtt.
-  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
-  ProcessDataPacketAtLevel(kFirstDecimatedPacket + 9, !kHasStopWaiting,
-                           ENCRYPTION_INITIAL);
-  ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
-  EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
-  EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
-
-  // The 10th received packet causes an ack to be sent.
-  for (int i = 0; i < 8; ++i) {
-    EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+  // Receive one packet out of order and then the rest in order.
+  // The loop leaves a one packet gap between acks sent to simulate some loss.
+  for (int j = 0; j < 3; ++j) {
+    // Process packet 10 first and ensure the alarm is one eighth min_rtt.
     EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
-    ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
-                             ENCRYPTION_INITIAL);
+    ProcessDataPacketAtLevel(kFirstDecimatedPacket + 9 + (j * 11),
+                             !kHasStopWaiting, ENCRYPTION_INITIAL);
+    ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
+    EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+    EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+
+    // The 10th received packet causes an ack to be sent.
+    writer_->Reset();
+    for (int i = 0; i < 9; ++i) {
+      EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+      EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+      // The ACK shouldn't be sent until the 10th packet is processed.
+      EXPECT_TRUE(writer_->ack_frames().empty());
+      ProcessDataPacketAtLevel(kFirstDecimatedPacket + i + (j * 11),
+                               !kHasStopWaiting, ENCRYPTION_INITIAL);
+    }
+    // Check that ack is sent and that delayed ack alarm is reset.
+    if (GetParam().no_stop_waiting) {
+      EXPECT_EQ(1u, writer_->frame_count());
+      EXPECT_TRUE(writer_->stop_waiting_frames().empty());
+    } else {
+      EXPECT_EQ(2u, writer_->frame_count());
+      EXPECT_FALSE(writer_->stop_waiting_frames().empty());
+    }
+    EXPECT_FALSE(writer_->ack_frames().empty());
+    EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+    if (!GetQuicReloadableFlag(quic_ack_reordered_packets)) {
+      break;
+    }
   }
-  // Check that ack is sent and that delayed ack alarm is reset.
-  if (GetParam().no_stop_waiting) {
-    EXPECT_EQ(1u, writer_->frame_count());
-    EXPECT_TRUE(writer_->stop_waiting_frames().empty());
-  } else {
-    EXPECT_EQ(2u, writer_->frame_count());
-    EXPECT_FALSE(writer_->stop_waiting_frames().empty());
-  }
-  EXPECT_FALSE(writer_->ack_frames().empty());
-  EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
 }
 
 TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
@@ -5514,7 +5492,7 @@
   }
   EXPECT_EQ(1u, writer_->stream_frames().size());
   EXPECT_EQ(1u, writer_->padding_frames().size());
-  EXPECT_FALSE(writer_->ack_frames().empty());
+  ASSERT_FALSE(writer_->ack_frames().empty());
   EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front()));
   EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
 }
@@ -5543,7 +5521,7 @@
   }
   EXPECT_EQ(1u, writer_->stream_frames().size());
   EXPECT_EQ(1u, writer_->padding_frames().size());
-  EXPECT_FALSE(writer_->ack_frames().empty());
+  ASSERT_FALSE(writer_->ack_frames().empty());
   EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front()));
   EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
 }
@@ -6650,6 +6628,21 @@
   BlockOnNextWrite();
 
   connection_.SendStreamData3();
+
+  if (!GetQuicReloadableFlag(quic_retransmissions_app_limited)) {
+    return;
+  }
+  // Now unblock the writer, become congestion control blocked,
+  // and ensure we become app-limited after writing.
+  writer_->SetWritable();
+  CongestionBlockWrites();
+  EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false));
+  {
+    InSequence seq;
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+    EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1);
+  }
+  connection_.OnCanWrite();
 }
 
 // Test the mode in which the link is filled up with probing retransmissions if
diff --git a/net/third_party/quic/core/quic_crypto_server_stream_test.cc b/net/third_party/quic/core/quic_crypto_server_stream_test.cc
index 933105b..4365e058 100644
--- a/net/third_party/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/third_party/quic/core/quic_crypto_server_stream_test.cc
@@ -449,12 +449,6 @@
 }
 
 TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
-  // Do not send MAX_HEADER_LIST_SIZE SETTING frame.
-  // TODO(fayang): This SETTING frame cannot be decrypted and
-  // crypto_test_utils::MovePackets stops processing parsing following packets.
-  // Actually, crypto stream test should use QuicSession instead of
-  // QuicSpdySession (b/32366134).
-  SetQuicReloadableFlag(quic_send_max_header_list_size, false);
   Initialize();
 
   InitializeFakeClient(/* supports_stateless_rejects= */ false);
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc
index b3a0523..77d7d46 100644
--- a/net/third_party/quic/core/quic_dispatcher.cc
+++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -702,11 +702,6 @@
   return false;
 }
 
-bool QuicDispatcher::OnAckFrame(const QuicAckFrame& /*frame*/) {
-  DCHECK(false);
-  return false;
-}
-
 bool QuicDispatcher::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
                                      QuicTime::Delta /*ack_delay_time*/) {
   DCHECK(false);
@@ -875,7 +870,7 @@
 }
 
 QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
-  return new QuicTimeWaitListManager(writer_.get(), this, helper_.get(),
+  return new QuicTimeWaitListManager(writer_.get(), this, helper_->GetClock(),
                                      alarm_factory_.get());
 }
 
@@ -1080,17 +1075,14 @@
     const QuicSocketAddress& current_self_address,
     std::unique_ptr<QuicReceivedPacket> current_packet,
     ParsedQuicVersion first_version) {
-  const bool enable_l1_munge = GetQuicRestartFlag(quic_enable_l1_munge);
-  if (enable_l1_munge) {
-    // Reset current_* to correspond to the packet which initiated the stateless
-    // reject logic.
-    current_client_address_ = current_client_address;
-    current_peer_address_ = current_peer_address;
-    current_self_address_ = current_self_address;
-    current_packet_ = current_packet.get();
-    current_connection_id_ = rejector->connection_id();
-    framer_.set_version(first_version);
-  }
+  // Reset current_* to correspond to the packet which initiated the stateless
+  // reject logic.
+  current_client_address_ = current_client_address;
+  current_peer_address_ = current_peer_address;
+  current_self_address_ = current_self_address;
+  current_packet_ = current_packet.get();
+  current_connection_id_ = rejector->connection_id();
+  framer_.set_version(first_version);
 
   // Stop buffering packets on this connection
   const auto num_erased =
@@ -1108,17 +1100,6 @@
     return;
   }
 
-  if (!enable_l1_munge) {
-    // Reset current_* to correspond to the packet which initiated the stateless
-    // reject logic.
-    current_client_address_ = current_client_address;
-    current_peer_address_ = current_peer_address;
-    current_self_address_ = current_self_address;
-    current_packet_ = current_packet.get();
-    current_connection_id_ = rejector->connection_id();
-    framer_.set_version(first_version);
-  }
-
   ProcessStatelessRejectorState(std::move(rejector),
                                 first_version.transport_version);
 }
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h
index 7cb5349..1e993440 100644
--- a/net/third_party/quic/core/quic_dispatcher.h
+++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -134,7 +134,6 @@
   void OnDecryptedPacket(EncryptionLevel level) override;
   bool OnPacketHeader(const QuicPacketHeader& header) override;
   bool OnStreamFrame(const QuicStreamFrame& frame) override;
-  bool OnAckFrame(const QuicAckFrame& frame) override;
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override;
   bool OnAckRange(QuicPacketNumber start,
diff --git a/net/third_party/quic/core/quic_dispatcher_test.cc b/net/third_party/quic/core/quic_dispatcher_test.cc
index 1ea814d..0d269186 100644
--- a/net/third_party/quic/core/quic_dispatcher_test.cc
+++ b/net/third_party/quic/core/quic_dispatcher_test.cc
@@ -330,7 +330,7 @@
   void CreateTimeWaitListManager() {
     time_wait_list_manager_ = new MockTimeWaitListManager(
         QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
-        &helper_, &alarm_factory_);
+        helper_.GetClock(), &alarm_factory_);
     // dispatcher_ takes the ownership of time_wait_list_manager_.
     QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
                                                time_wait_list_manager_);
@@ -648,11 +648,9 @@
 }
 
 TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 9u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
   SetQuicReloadableFlag(quic_enable_version_43, true);
   SetQuicReloadableFlag(quic_enable_version_44, true);
   SetQuicFlag(&FLAGS_quic_enable_version_99, true);
@@ -774,7 +772,7 @@
                 PACKET_4BYTE_PACKET_NUMBER, 1);
 
   // Turn off version 41.
-  SetQuicReloadableFlag(quic_disable_version_41, true);
+  SetQuicReloadableFlag(quic_disable_version_41_2, true);
   ++connection_id;
   EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
                                               QuicStringPiece("hq")))
@@ -785,7 +783,7 @@
                 PACKET_4BYTE_PACKET_NUMBER, 1);
 
   // Turn on version 41.
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
   ++connection_id;
   EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
                                               QuicStringPiece("hq")))
@@ -805,72 +803,6 @@
                 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41),
                 SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
                 PACKET_4BYTE_PACKET_NUMBER, 1);
-
-  // Turn off version 38.
-  SetQuicReloadableFlag(quic_disable_version_38, true);
-  ++connection_id;
-  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
-                                              QuicStringPiece("hq")))
-      .Times(0);
-  ProcessPacket(client_address, connection_id, true,
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
-                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
-                PACKET_4BYTE_PACKET_NUMBER, 1);
-
-  // Turn on version 38.
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  ++connection_id;
-  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
-                                              QuicStringPiece("hq")))
-      .WillOnce(testing::Return(CreateSession(
-          dispatcher_.get(), config_, connection_id, client_address,
-          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
-          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
-  EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
-              ProcessUdpPacket(_, _, _))
-      .WillOnce(WithArg<2>(
-          Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
-            ValidatePacket(connection_id, packet);
-          })));
-  EXPECT_CALL(*dispatcher_,
-              ShouldCreateOrBufferPacketForConnection(connection_id));
-  ProcessPacket(client_address, connection_id, true,
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
-                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
-                PACKET_4BYTE_PACKET_NUMBER, 1);
-
-  // Turn off version 37.
-  SetQuicReloadableFlag(quic_disable_version_37, true);
-  ++connection_id;
-  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
-                                              QuicStringPiece("hq")))
-      .Times(0);
-  ProcessPacket(client_address, connection_id, true,
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
-                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
-                PACKET_4BYTE_PACKET_NUMBER, 1);
-
-  // Turn on version 37.
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  ++connection_id;
-  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
-                                              QuicStringPiece("hq")))
-      .WillOnce(testing::Return(CreateSession(
-          dispatcher_.get(), config_, connection_id, client_address,
-          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
-          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
-  EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
-              ProcessUdpPacket(_, _, _))
-      .WillOnce(WithArg<2>(
-          Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
-            ValidatePacket(connection_id, packet);
-          })));
-  EXPECT_CALL(*dispatcher_,
-              ShouldCreateOrBufferPacketForConnection(connection_id));
-  ProcessPacket(client_address, connection_id, true,
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
-                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
-                PACKET_4BYTE_PACKET_NUMBER, 1);
 }
 
 // Enables mocking of the handshake-confirmation for stateless rejects.
diff --git a/net/third_party/quic/core/quic_flags_list.h b/net/third_party/quic/core/quic_flags_list.h
index 7ecf0792..3940e15 100644
--- a/net/third_party/quic/core/quic_flags_list.h
+++ b/net/third_party/quic/core/quic_flags_list.h
@@ -49,10 +49,6 @@
 // allow CHLO packets to be buffered until next iteration of the event loop.
 QUIC_FLAG(bool, FLAGS_quic_allow_chlo_buffering, true)
 
-// If true, GFE sends spdy::SETTINGS_MAX_HEADER_LIST_SIZE to the client at the
-// beginning of a connection.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_max_header_list_size, true)
-
 // If greater than zero, mean RTT variation is multiplied by the specified
 // factor and added to the congestion window limit.
 QUIC_FLAG(double, FLAGS_quic_bbr_rtt_variation_weight, 0.0f)
@@ -68,9 +64,6 @@
 // 3RTOs if there are no open streams.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_3rtos, false)
 
-// If true, enable experiment for testing PCC congestion-control.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc2, false)
-
 // When true, defaults to BBR congestion control instead of Cubic.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
 
@@ -100,14 +93,7 @@
 // If true, enable QUIC v99.
 QUIC_FLAG(bool, FLAGS_quic_enable_version_99, false)
 
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_37, true)
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_38, true)
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_41, false)
-
-// If true, framer will process and report ack frame incrementally.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_use_incremental_ack_processing4,
-          true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_41_2, false)
 
 // If this flag and
 // FLAGS_quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash
@@ -141,17 +127,6 @@
 // incoming initial RTT values.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_irtt, false)
 
-// Fixed QUIC's PROBE_BW logic to exit low gain mode based on bytes_in_flight,
-// not prior_in_flight.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_fix_probe_bw, true)
-
-// If true, changes when the dispatcher changes internal state.
-QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_l1_munge, true)
-
-// Don't slow down the pacing rate in STARTUP upon loss if there hasn't been
-// at least one non app-limited sample.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slower_startup2, true)
-
 // If true, put ScopedRetransmissionScheduler's functionality to
 // ScopedPacketFlusher.
 QUIC_FLAG(bool,
@@ -196,3 +171,40 @@
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_add_to_blocked_list_if_writer_blocked,
           false)
+
+// Only send an ack immediately when a previously missing packet is received if
+// an ack with a larger largest acked has already been sent.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_ack_reordered_packets, false)
+
+// If true, QuicWriteBlockedList will use StaticStreamCollection to speed up
+// operations on static streams.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_use_static_stream_collection_in_write_blocked_list,
+    false)
+
+// If true, disables QUIC v42.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_42, false)
+
+// Stop checking QuicUnackedPacketMap::HasUnackedRetransmittableFrames and
+// instead rely on the existing check that bytes_in_flight > 0
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_optimize_inflight_check, false)
+
+// When you\'re app-limited entering recovery, stay app-limited until you exit
+// recovery in QUIC BBR.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_app_limited_recovery, false)
+
+// If true, mark QUIC as app-limited after sending queued packets or
+// retransmisssions and we then become congestion control blocked.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_retransmissions_app_limited,
+          false)
+
+// If true, stop resetting ideal_next_packet_send_time_ in pacing sender.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time,
+    false)
+
+// If true, enable experiment for testing PCC congestion-control.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc3, false)
diff --git a/net/third_party/quic/core/quic_framer.cc b/net/third_party/quic/core/quic_framer.cc
index 60e6f1d8..2e103059 100644
--- a/net/third_party/quic/core/quic_framer.cc
+++ b/net/third_party/quic/core/quic_framer.cc
@@ -272,15 +272,8 @@
       alternative_decrypter_latch_(false),
       perspective_(perspective),
       validate_flags_(true),
-      creation_time_(creation_time),
-      last_timestamp_(QuicTime::Delta::Zero()),
       data_producer_(nullptr),
-      use_incremental_ack_processing_(
-          GetQuicReloadableFlag(quic_use_incremental_ack_processing4)),
       decrypted_payload_reader_(nullptr) {
-  if (use_incremental_ack_processing_) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_incremental_ack_processing4);
-  }
   DCHECK(!supported_versions.empty());
   version_ = supported_versions_[0];
   decrypter_ = QuicMakeUnique<NullDecrypter>(perspective);
@@ -998,8 +991,7 @@
   }
 
   for (const ParsedQuicVersion& version : versions) {
-    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_35 is removed.
     if (!writer.WriteTag(
             QuicEndian::HostToNet32(CreateQuicVersionLabel(version)))) {
       return nullptr;
@@ -1039,8 +1031,7 @@
   }
 
   for (const ParsedQuicVersion& version : versions) {
-    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_35 is removed.
     if (!writer.WriteTag(
             QuicEndian::HostToNet32(CreateQuicVersionLabel(version)))) {
       return nullptr;
@@ -1135,8 +1126,7 @@
       set_detailed_error("Unable to read supported version in negotiation.");
       return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
     }
-    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
     version_label = QuicEndian::NetToHost32(version_label);
     packet.versions.push_back(ParseQuicVersionLabel(version_label));
   } while (!reader->IsDoneReading());
@@ -1405,8 +1395,7 @@
   if (header.version_flag) {
     DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
     QuicVersionLabel version_label = CreateQuicVersionLabel(version_);
-    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_35 is removed.
     if (!writer->WriteTag(QuicEndian::NetToHost32(version_label))) {
       return false;
     }
@@ -1450,8 +1439,7 @@
   if (header.version_flag) {
     // Append version for long header.
     QuicVersionLabel version_label = CreateQuicVersionLabel(version_);
-    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use WriteUInt32() once QUIC_VERSION_35 is removed.
     if (!writer->WriteTag(QuicEndian::NetToHost32(version_label))) {
       return false;
     }
@@ -1488,29 +1476,6 @@
   return true;
 }
 
-const QuicTime::Delta QuicFramer::CalculateTimestampFromWire(
-    uint32_t time_delta_us) {
-  // The new time_delta might have wrapped to the next epoch, or it
-  // might have reverse wrapped to the previous epoch, or it might
-  // remain in the same epoch. Select the time closest to the previous
-  // time.
-  //
-  // epoch_delta is the delta between epochs. A delta is 4 bytes of
-  // microseconds.
-  const uint64_t epoch_delta = UINT64_C(1) << 32;
-  uint64_t epoch = last_timestamp_.ToMicroseconds() & ~(epoch_delta - 1);
-  // Wrapping is safe here because a wrapped value will not be ClosestTo below.
-  uint64_t prev_epoch = epoch - epoch_delta;
-  uint64_t next_epoch = epoch + epoch_delta;
-
-  uint64_t time = ClosestTo(
-      last_timestamp_.ToMicroseconds(), epoch + time_delta_us,
-      ClosestTo(last_timestamp_.ToMicroseconds(), prev_epoch + time_delta_us,
-                next_epoch + time_delta_us));
-
-  return QuicTime::Delta::FromMicroseconds(time);
-}
-
 QuicPacketNumber QuicFramer::CalculatePacketNumberFromWire(
     QuicPacketNumberLength packet_number_length,
     QuicPacketNumber base_packet_number,
@@ -1585,8 +1550,7 @@
       set_detailed_error("Unable to read protocol version.");
       return false;
     }
-    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
     version_label = QuicEndian::NetToHost32(version_label);
 
     // If the version from the new packet is the same as the version of this
@@ -1780,8 +1744,7 @@
       set_detailed_error("Unable to read protocol version.");
       return false;
     }
-    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_38 and earlier
-    // are removed.
+    // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
     version_label = QuicEndian::NetToHost32(version_label);
     if (header->long_packet_type == VERSION_NEGOTIATION && version_label) {
       // Version negotiation is identified by the version field.
@@ -1899,18 +1862,9 @@
           (version_.transport_version >= QUIC_VERSION_41 &&
            ((frame_type & kQuicFrameTypeSpecialMask) ==
             kQuicFrameTypeAckMask_v41))) {
-        // TODO(fayang): Remove frame when deprecating
-        // quic_reloadable_flag_quic_use_incremental_ack_processing4.
-        QuicAckFrame frame;
-        if (!ProcessAckFrame(reader, frame_type, &frame)) {
+        if (!ProcessAckFrame(reader, frame_type)) {
           return RaiseError(QUIC_INVALID_ACK_DATA);
         }
-        if (!use_incremental_ack_processing_ && !visitor_->OnAckFrame(frame)) {
-          QUIC_DVLOG(1) << ENDPOINT
-                        << "Visitor asked to stop further processing.";
-          // Returning true since there was no parsing error.
-          return true;
-        }
         continue;
       }
 
@@ -2231,12 +2185,6 @@
           if (!ProcessIetfAckFrame(reader, &frame)) {
             return RaiseError(QUIC_INVALID_ACK_DATA);
           }
-          if (!use_incremental_ack_processing_ &&
-              !visitor_->OnAckFrame(frame)) {
-            QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
-            // Returning true since there was no parsing error.
-            return true;
-          }
           break;
         }
         case IETF_PATH_CHALLENGE: {
@@ -2437,9 +2385,7 @@
   return true;
 }
 
-bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
-                                 uint8_t frame_type,
-                                 QuicAckFrame* ack_frame) {
+bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) {
   bool has_ack_blocks =
       ExtractBit(frame_type, version_.transport_version != QUIC_VERSION_41
                                  ? kQuicHasMultipleAckBlocksOffset
@@ -2481,17 +2427,7 @@
     return false;
   }
 
-  if (!use_incremental_ack_processing_) {
-    if (ack_delay_time_us == kUFloat16MaxValue) {
-      ack_frame->ack_delay_time = QuicTime::Delta::Infinite();
-    } else {
-      ack_frame->ack_delay_time =
-          QuicTime::Delta::FromMicroseconds(ack_delay_time_us);
-    }
-  }
-
-  if (use_incremental_ack_processing_ &&
-      !visitor_->OnAckFrameStart(
+  if (!visitor_->OnAckFrameStart(
           largest_acked,
           ack_delay_time_us == kUFloat16MaxValue
               ? QuicTime::Delta::Infinite()
@@ -2539,18 +2475,13 @@
   }
 
   QuicPacketNumber first_received = largest_acked + 1 - first_block_length;
-  if (use_incremental_ack_processing_) {
-    if (!visitor_->OnAckRange(first_received, largest_acked + 1,
-                              /*last_range=*/!has_ack_blocks)) {
-      // The visitor suppresses further processing of the packet. Although
-      // this is not a parsing error, returns false as this is in middle
-      // of processing an ack frame,
-      set_detailed_error("Visitor suppresses further processing of ack frame.");
-      return false;
-    }
-  } else {
-    ack_frame->largest_acked = largest_acked;
-    ack_frame->packets.AddRange(first_received, largest_acked + 1);
+  if (!visitor_->OnAckRange(first_received, largest_acked + 1,
+                            /*last_range=*/!has_ack_blocks)) {
+    // The visitor suppresses further processing of the packet. Although
+    // this is not a parsing error, returns false as this is in middle
+    // of processing an ack frame,
+    set_detailed_error("Visitor suppresses further processing of ack frame.");
+    return false;
   }
 
   if (num_ack_blocks > 0) {
@@ -2575,8 +2506,7 @@
 
       first_received -= (gap + current_block_length);
       const bool last_range = i + 1 == num_ack_blocks;
-      if (use_incremental_ack_processing_ &&
-          (current_block_length > 0 || last_range)) {
+      if (current_block_length > 0 || last_range) {
         if (!visitor_->OnAckRange(first_received,
                                   first_received + current_block_length,
                                   last_range)) {
@@ -2588,10 +2518,6 @@
           return false;
         }
       }
-      if (!use_incremental_ack_processing_ && current_block_length > 0) {
-        ack_frame->packets.AddRange(first_received,
-                                    first_received + current_block_length);
-      }
     }
   }
 
@@ -2601,7 +2527,7 @@
     return false;
   }
 
-  if (!ProcessTimestampsInAckFrame(num_received_packets, reader, ack_frame)) {
+  if (!ProcessTimestampsInAckFrame(num_received_packets, reader)) {
     return false;
   }
 
@@ -2609,16 +2535,13 @@
 }
 
 bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
-                                             QuicDataReader* reader,
-                                             QuicAckFrame* ack_frame) {
+                                             QuicDataReader* reader) {
   if (num_received_packets > 0) {
     uint8_t delta_from_largest_observed;
     if (!reader->ReadUInt8(&delta_from_largest_observed)) {
       set_detailed_error("Unable to read sequence delta in received packets.");
       return false;
     }
-    QuicPacketNumber seq_num =
-        LargestAcked(*ack_frame) - delta_from_largest_observed;
 
     // Time delta from the framer creation.
     uint32_t time_delta_us;
@@ -2627,19 +2550,12 @@
       return false;
     }
 
-    last_timestamp_ = CalculateTimestampFromWire(time_delta_us);
-
-    ack_frame->received_packet_times.reserve(num_received_packets);
-    ack_frame->received_packet_times.emplace_back(
-        seq_num, creation_time_ + last_timestamp_);
-
     for (uint8_t i = 1; i < num_received_packets; ++i) {
       if (!reader->ReadUInt8(&delta_from_largest_observed)) {
         set_detailed_error(
             "Unable to read sequence delta in received packets.");
         return false;
       }
-      seq_num = LargestAcked(*ack_frame) - delta_from_largest_observed;
 
       // Time delta from the previous timestamp.
       uint64_t incremental_time_delta_us;
@@ -2648,11 +2564,6 @@
             "Unable to read incremental time delta in received packets.");
         return false;
       }
-
-      last_timestamp_ = last_timestamp_ + QuicTime::Delta::FromMicroseconds(
-                                              incremental_time_delta_us);
-      ack_frame->received_packet_times.emplace_back(
-          seq_num, creation_time_ + last_timestamp_);
     }
   }
   return true;
@@ -2682,8 +2593,7 @@
         QuicTime::Delta::FromMicroseconds(ack_delay_time_in_us);
   }
 
-  if (use_incremental_ack_processing_ &&
-      !visitor_->OnAckFrameStart(largest_acked, ack_frame->ack_delay_time)) {
+  if (!visitor_->OnAckFrameStart(largest_acked, ack_frame->ack_delay_time)) {
     // The visitor suppresses further processing of the packet. Although this is
     // not a parsing error, returns false as this is in middle of processing an
     // ACK frame.
@@ -2723,17 +2633,13 @@
     return false;
   }
 
-  if (use_incremental_ack_processing_) {
-    if (!visitor_->OnAckRange(block_low, block_high,
-                              /* last_range= */ (ack_block_count == 0))) {
-      // The visitor suppresses further processing of the packet. Although
-      // this is not a parsing error, returns false as this is in middle
-      // of processing an ACK frame.
-      set_detailed_error("Visitor suppresses further processing of ACK frame.");
-      return false;
-    }
-  } else {
-    ack_frame->packets.AddRange(block_low, block_high);
+  if (!visitor_->OnAckRange(block_low, block_high,
+                            /* last_range= */ (ack_block_count == 0))) {
+    // The visitor suppresses further processing of the packet. Although
+    // this is not a parsing error, returns false as this is in middle
+    // of processing an ACK frame.
+    set_detailed_error("Visitor suppresses further processing of ACK frame.");
+    return false;
   }
 
   while (ack_block_count != 0) {
@@ -2781,18 +2687,13 @@
     // Calculate the low end of the new nth ack block. The +1 is
     // because the encoded value is the blocksize-1.
     block_low = block_high - 1 - ack_block_value;
-    if (use_incremental_ack_processing_) {
-      if (!visitor_->OnAckRange(block_low, block_high,
-                                /*last_range=*/(ack_block_count == 1))) {
-        // The visitor suppresses further processing of the packet. Although
-        // this is not a parsing error, returns false as this is in middle
-        // of processing an ACK frame.
-        set_detailed_error(
-            "Visitor suppresses further processing of ACK frame.");
-        return false;
-      }
-    } else {
-      ack_frame->packets.AddRange(block_low, block_high);
+    if (!visitor_->OnAckRange(block_low, block_high,
+                              /*last_range=*/(ack_block_count == 1))) {
+      // The visitor suppresses further processing of the packet. Although
+      // this is not a parsing error, returns false as this is in middle
+      // of processing an ACK frame.
+      set_detailed_error("Visitor suppresses further processing of ACK frame.");
+      return false;
     }
 
     // Another one done.
@@ -2942,7 +2843,7 @@
 
 void QuicFramer::ProcessPaddingFrame(QuicDataReader* reader,
                                      QuicPaddingFrame* frame) {
-  if (version_.transport_version <= QUIC_VERSION_37) {
+  if (version_.transport_version == QUIC_VERSION_35) {
     frame->num_padding_bytes = reader->BytesRemaining() + 1;
     reader->ReadRemainingPayload();
     return;
@@ -3138,15 +3039,6 @@
   return true;
 }
 
-size_t QuicFramer::GetAckFrameTimeStampSize(const QuicAckFrame& ack) {
-  DCHECK(!use_incremental_ack_processing_);
-  if (ack.received_packet_times.empty()) {
-    return 0;
-  }
-
-  return 5 + 3 * (ack.received_packet_times.size() - 1);
-}
-
 size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) {
   // Type byte, largest_acked, and delay_time are straight-forward.
   size_t ack_frame_size = kQuicFrameTypeSize;
@@ -3248,11 +3140,6 @@
                 (ack_block_length + PACKET_1BYTE_PACKET_NUMBER);
   }
 
-  // Include timestamps.
-  if (!use_incremental_ack_processing_) {
-    ack_size += GetAckFrameTimeStampSize(ack);
-  }
-
   return ack_size;
 }
 
@@ -3857,93 +3744,13 @@
   // Timestamps.
   // If we don't have enough available space to append all the timestamps, don't
   // append any of them.
-  if (!use_incremental_ack_processing_ &&
-      writer->capacity() - writer->length() >=
-          GetAckFrameTimeStampSize(frame)) {
-    if (!AppendTimestampsToAckFrame(frame, num_timestamps_offset, writer)) {
-      return false;
-    }
-  } else {
-    if (transport_version() != QUIC_VERSION_41) {
-      uint8_t num_received_packets = 0;
-      if (!writer->WriteBytes(&num_received_packets, 1)) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-bool QuicFramer::AppendTimestampsToAckFrame(const QuicAckFrame& frame,
-                                            size_t num_timestamps_offset,
-                                            QuicDataWriter* writer) {
-  DCHECK_GE(std::numeric_limits<uint8_t>::max(),
-            frame.received_packet_times.size());
-  // num_received_packets is only 1 byte.
-  if (frame.received_packet_times.size() >
-      std::numeric_limits<uint8_t>::max()) {
-    return false;
-  }
-
-  uint8_t num_received_packets = frame.received_packet_times.size();
-  if (version_.transport_version != QUIC_VERSION_41) {
+  if (transport_version() != QUIC_VERSION_41) {
+    uint8_t num_received_packets = 0;
     if (!writer->WriteBytes(&num_received_packets, 1)) {
       return false;
     }
-  } else {
-    if (!writer->WriteUInt8AtOffset(num_received_packets,
-                                    num_timestamps_offset)) {
-      return false;
-    }
-  }
-  if (num_received_packets == 0) {
-    return true;
   }
 
-  PacketTimeVector::const_iterator it = frame.received_packet_times.begin();
-  QuicPacketNumber packet_number = it->first;
-  QuicPacketNumber delta_from_largest_observed =
-      LargestAcked(frame) - packet_number;
-
-  DCHECK_GE(std::numeric_limits<uint8_t>::max(), delta_from_largest_observed);
-  if (delta_from_largest_observed > std::numeric_limits<uint8_t>::max()) {
-    return false;
-  }
-
-  if (!writer->WriteUInt8(delta_from_largest_observed)) {
-    return false;
-  }
-
-  // Use the lowest 4 bytes of the time delta from the creation_time_.
-  const uint64_t time_epoch_delta_us = UINT64_C(1) << 32;
-  uint32_t time_delta_us =
-      static_cast<uint32_t>((it->second - creation_time_).ToMicroseconds() &
-                            (time_epoch_delta_us - 1));
-  if (!writer->WriteUInt32(time_delta_us)) {
-    return false;
-  }
-
-  QuicTime prev_time = it->second;
-
-  for (++it; it != frame.received_packet_times.end(); ++it) {
-    packet_number = it->first;
-    delta_from_largest_observed = LargestAcked(frame) - packet_number;
-
-    if (delta_from_largest_observed > std::numeric_limits<uint8_t>::max()) {
-      return false;
-    }
-
-    if (!writer->WriteUInt8(delta_from_largest_observed)) {
-      return false;
-    }
-
-    uint64_t frame_time_delta_us = (it->second - prev_time).ToMicroseconds();
-    prev_time = it->second;
-    if (!writer->WriteUFloat16(frame_time_delta_us)) {
-      return false;
-    }
-  }
   return true;
 }
 
@@ -4217,7 +4024,7 @@
 
 bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
                                     QuicDataWriter* writer) {
-  if (version_.transport_version <= QUIC_VERSION_37) {
+  if (version_.transport_version == QUIC_VERSION_35) {
     writer->WritePadding();
     return true;
   }
@@ -4256,8 +4063,8 @@
 }
 
 Endianness QuicFramer::endianness() const {
-  return version_.transport_version > QUIC_VERSION_38 ? NETWORK_BYTE_ORDER
-                                                      : HOST_BYTE_ORDER;
+  return version_.transport_version != QUIC_VERSION_35 ? NETWORK_BYTE_ORDER
+                                                       : HOST_BYTE_ORDER;
 }
 
 bool QuicFramer::StartsWithChlo(QuicStreamId id,
diff --git a/net/third_party/quic/core/quic_framer.h b/net/third_party/quic/core/quic_framer.h
index ebe80535..e3ac38f 100644
--- a/net/third_party/quic/core/quic_framer.h
+++ b/net/third_party/quic/core/quic_framer.h
@@ -114,10 +114,6 @@
   // Called when a StreamFrame has been parsed.
   virtual bool OnStreamFrame(const QuicStreamFrame& frame) = 0;
 
-  // Called when a AckFrame has been parsed.  If OnAckFrame returns false,
-  // the framer will stop parsing the current packet.
-  virtual bool OnAckFrame(const QuicAckFrame& frame) = 0;
-
   // Called when largest acked of an AckFrame has been parsed.
   virtual bool OnAckFrameStart(QuicPacketNumber largest_acked,
                                QuicTime::Delta ack_delay_time) = 0;
@@ -234,10 +230,6 @@
 
   QuicErrorCode error() const { return error_; }
 
-  bool use_incremental_ack_processing() const {
-    return use_incremental_ack_processing_;
-  }
-
   // Pass a UDP packet into the framer for parsing.
   // Return true if the packet was processed succesfully. |packet| must be a
   // single, complete UDP packet (not a frame of a packet).  This packet
@@ -538,12 +530,9 @@
   bool ProcessStreamFrame(QuicDataReader* reader,
                           uint8_t frame_type,
                           QuicStreamFrame* frame);
-  bool ProcessAckFrame(QuicDataReader* reader,
-                       uint8_t frame_type,
-                       QuicAckFrame* frame);
+  bool ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type);
   bool ProcessTimestampsInAckFrame(uint8_t num_received_packets,
-                                   QuicDataReader* reader,
-                                   QuicAckFrame* ack_frame);
+                                   QuicDataReader* reader);
   bool ProcessIetfAckFrame(QuicDataReader* reader, QuicAckFrame* ack_frame);
   bool ProcessStopWaitingFrame(QuicDataReader* reader,
                                const QuicPacketHeader& header,
@@ -571,13 +560,6 @@
       QuicPacketNumber base_packet_number,
       QuicPacketNumber packet_number) const;
 
-  // Returns the QuicTime::Delta corresponding to the time from when the framer
-  // was created.
-  const QuicTime::Delta CalculateTimestampFromWire(uint32_t time_delta_us);
-
-  // Computes the wire size in bytes of time stamps in |ack|.
-  size_t GetAckFrameTimeStampSize(const QuicAckFrame& ack);
-
   // Computes the wire size in bytes of the |ack| frame.
   size_t GetAckFrameSize(const QuicAckFrame& ack,
                          QuicPacketNumberLength packet_number_length);
@@ -627,9 +609,6 @@
 
   bool AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
                                  QuicDataWriter* builder);
-  bool AppendTimestampsToAckFrame(const QuicAckFrame& frame,
-                                  size_t num_timestamps_offset,
-                                  QuicDataWriter* writer);
 
   // Append IETF format ACK frame.
   //
@@ -780,12 +759,6 @@
   Perspective perspective_;
   // If false, skip validation that the public flags are set to legal values.
   bool validate_flags_;
-  // The time this framer was created.  Time written to the wire will be
-  // written as a delta from this value.
-  QuicTime creation_time_;
-  // The time delta computed for the last timestamp frame. This is relative to
-  // the creation_time.
-  QuicTime::Delta last_timestamp_;
   // The diversification nonce from the last received packet.
   DiversificationNonce last_nonce_;
 
@@ -793,9 +766,6 @@
   // owned. TODO(fayang): Consider add data producer to framer's constructor.
   QuicStreamFrameDataProducer* data_producer_;
 
-  // Latched value of quic_reloadable_flag_quic_use_incremental_ack_processing4.
-  const bool use_incremental_ack_processing_;
-
   // If the framer is processing a decrypted payload of a data packet,
   // |decrypted_payload_reader_| will be set to the reader of that payload,
   // otherwise nullptr.
diff --git a/net/third_party/quic/core/quic_framer_test.cc b/net/third_party/quic/core/quic_framer_test.cc
index afa7955..b0e4a6d 100644
--- a/net/third_party/quic/core/quic_framer_test.cc
+++ b/net/third_party/quic/core/quic_framer_test.cc
@@ -212,12 +212,6 @@
     return true;
   }
 
-  bool OnAckFrame(const QuicAckFrame& frame) override {
-    ++frame_count_;
-    ack_frames_.push_back(QuicMakeUnique<QuicAckFrame>(frame));
-    return true;
-  }
-
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override {
     ++frame_count_;
@@ -770,7 +764,7 @@
   }
 
   PacketFragments& fragments =
-      framer_.transport_version() <= QUIC_VERSION_38 ? packet38 : packet39;
+      framer_.transport_version() == QUIC_VERSION_35 ? packet38 : packet39;
 
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -864,7 +858,7 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() <= QUIC_VERSION_38 ? packet
+          : (framer_.transport_version() == QUIC_VERSION_35 ? packet
                                                             : packet39);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -933,7 +927,7 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() <= QUIC_VERSION_38 ? packet
+          : (framer_.transport_version() == QUIC_VERSION_35 ? packet
                                                             : packet39);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -993,7 +987,7 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() <= QUIC_VERSION_38 ? packet
+          : (framer_.transport_version() == QUIC_VERSION_35 ? packet
                                                             : packet39);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -1052,7 +1046,7 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() <= QUIC_VERSION_38 ? packet
+          : (framer_.transport_version() == QUIC_VERSION_35 ? packet
                                                             : packet39);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -1242,7 +1236,7 @@
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -1310,7 +1304,7 @@
   QuicEncryptedPacket encrypted(
       AsChars(framer_.transport_version() > QUIC_VERSION_43
                   ? packet44
-                  : (framer_.transport_version() <= QUIC_VERSION_38
+                  : (framer_.transport_version() == QUIC_VERSION_35
                          ? packet
                          : packet39)),
       framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
@@ -1354,7 +1348,7 @@
   };
   // clang-format on
 
-  if (framer_.transport_version() > QUIC_VERSION_37) {
+  if (framer_.transport_version() != QUIC_VERSION_35) {
     return;
   }
 
@@ -1519,7 +1513,7 @@
   };
   // clang-format on
 
-  if (framer_.transport_version() <= QUIC_VERSION_37) {
+  if (framer_.transport_version() == QUIC_VERSION_35) {
     return;
   }
   unsigned char* p = packet;
@@ -1532,7 +1526,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -1715,7 +1709,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -1849,7 +1843,7 @@
     p = packet44;
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p),
@@ -1966,7 +1960,8 @@
   PacketFragments& fragments =
       framer_.transport_version() == QUIC_VERSION_41
           ? packet41
-          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                            : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2148,7 +2143,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -2332,7 +2327,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -2537,7 +2532,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -2663,7 +2658,7 @@
     p = packet44;
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p),
@@ -2874,7 +2869,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -3048,7 +3043,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -3503,8 +3498,8 @@
           ? packet44
           : (framer_.transport_version() == QUIC_VERSION_41
                  ? packet41
-                 : (framer_.transport_version() > QUIC_VERSION_38 ? packet39
-                                                                  : packet));
+                 : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                                   : packet));
 
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
@@ -3518,11 +3513,7 @@
       PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
 
   EXPECT_EQ(0u, visitor_.stream_frames_.size());
-  if (framer_.use_incremental_ack_processing()) {
-    ASSERT_EQ(1u, visitor_.ack_frames_.size());
-  } else {
-    ASSERT_EQ(0u, visitor_.ack_frames_.size());
-  }
+  ASSERT_EQ(1u, visitor_.ack_frames_.size());
 
   CheckFramingBoundaries(fragments, QUIC_INVALID_ACK_DATA);
 }
@@ -3676,7 +3667,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -4038,7 +4029,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
 
@@ -4125,7 +4116,8 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                            : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4194,7 +4186,7 @@
   QuicEncryptedPacket encrypted(
       AsChars(framer_.transport_version() > QUIC_VERSION_43
                   ? packet44
-                  : (framer_.transport_version() <= QUIC_VERSION_38
+                  : (framer_.transport_version() == QUIC_VERSION_35
                          ? packet
                          : packet39)),
       framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
@@ -4339,7 +4331,7 @@
                  ? packet44
                  : (framer_.transport_version() == QUIC_VERSION_41
                         ? packet41
-                        : (framer_.transport_version() > QUIC_VERSION_38
+                        : (framer_.transport_version() != QUIC_VERSION_35
                                ? packet39
                                : packet)));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -4478,8 +4470,8 @@
           ? packet99
           : (framer_.transport_version() > QUIC_VERSION_43
                  ? packet44
-                 : (framer_.transport_version() > QUIC_VERSION_38 ? packet39
-                                                                  : packet));
+                 : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                                   : packet));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4661,7 +4653,8 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                            : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4757,7 +4750,8 @@
   PacketFragments& fragments =
       framer_.transport_version() > QUIC_VERSION_43
           ? packet44
-          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
+          : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                            : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4944,8 +4938,8 @@
           ? packet99
           : (framer_.transport_version() > QUIC_VERSION_43
                  ? packet44
-                 : (framer_.transport_version() > QUIC_VERSION_38 ? packet39
-                                                                  : packet));
+                 : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+                                                                   : packet));
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -5012,7 +5006,7 @@
   QuicEncryptedPacket encrypted(
       AsChars(framer_.transport_version() > QUIC_VERSION_43
                   ? packet44
-                  : (framer_.transport_version() <= QUIC_VERSION_38
+                  : (framer_.transport_version() == QUIC_VERSION_35
                          ? packet
                          : packet39)),
       framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
@@ -5444,7 +5438,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -5464,7 +5458,7 @@
 }
 
 TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
-  if (framer_.transport_version() <= QUIC_VERSION_37) {
+  if (framer_.transport_version() == QUIC_VERSION_35) {
     return;
   }
   QuicPacketHeader header;
@@ -5628,7 +5622,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -5691,7 +5685,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -5764,7 +5758,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -5973,7 +5967,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -6115,7 +6109,7 @@
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
     p_size = QUIC_ARRAYSIZE(packet41);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -6289,7 +6283,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -6427,7 +6421,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -6656,7 +6650,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -7154,7 +7148,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -7212,7 +7206,7 @@
   // clang-format on
 
   unsigned char* p = packet;
-  if (framer_.transport_version() > QUIC_VERSION_38) {
+  if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -7221,8 +7215,8 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(), AsChars(p),
-      framer_.transport_version() > QUIC_VERSION_38 ? QUIC_ARRAYSIZE(packet39)
-                                                    : QUIC_ARRAYSIZE(packet));
+      framer_.transport_version() != QUIC_VERSION_35 ? QUIC_ARRAYSIZE(packet39)
+                                                     : QUIC_ARRAYSIZE(packet));
 }
 
 TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
@@ -7352,7 +7346,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -7473,7 +7467,7 @@
   } else if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -7707,7 +7701,7 @@
   } else if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -7938,7 +7932,7 @@
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8127,7 +8121,7 @@
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8232,7 +8226,7 @@
   } else if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8410,7 +8404,7 @@
   } else if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8468,7 +8462,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8542,7 +8536,7 @@
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     packet_size = QUIC_ARRAYSIZE(packet44);
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
     packet_size = QUIC_ARRAYSIZE(packet39);
   }
@@ -8617,7 +8611,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8789,7 +8783,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -8865,7 +8859,7 @@
   unsigned char* p = packet;
   if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
 
@@ -9202,7 +9196,6 @@
   EXPECT_CALL(visitor, OnPacket());
   EXPECT_CALL(visitor, OnPacketHeader(_));
   EXPECT_CALL(visitor, OnStreamFrame(_)).WillOnce(Return(false));
-  EXPECT_CALL(visitor, OnAckFrame(_)).Times(0);
   EXPECT_CALL(visitor, OnPacketComplete());
   EXPECT_CALL(visitor, OnUnauthenticatedPublicHeader(_)).WillOnce(Return(true));
   EXPECT_CALL(visitor, OnUnauthenticatedHeader(_)).WillOnce(Return(true));
@@ -9218,7 +9211,7 @@
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -9266,7 +9259,6 @@
   EXPECT_CALL(visitor, OnError(_)).Times(0);
   EXPECT_CALL(visitor, OnStreamFrame(_)).Times(0);
   EXPECT_CALL(visitor, OnStreamFrame(Truly(ExpectedStreamFrame))).Times(1);
-  EXPECT_CALL(visitor, OnAckFrame(_)).Times(0);
   EXPECT_CALL(visitor, OnPacketComplete()).Times(1);
 
   EXPECT_TRUE(framer_.ProcessPacket(*packet));
@@ -9302,7 +9294,6 @@
   EXPECT_CALL(visitor, OnDecryptedPacket(_)).Times(1);
   EXPECT_CALL(visitor, OnError(_)).Times(1);
   EXPECT_CALL(visitor, OnStreamFrame(_)).Times(0);
-  EXPECT_CALL(visitor, OnAckFrame(_)).Times(0);
   EXPECT_CALL(visitor, OnPacketComplete()).Times(0);
 
   EXPECT_FALSE(framer_.ProcessPacket(*packet));
@@ -9445,7 +9436,7 @@
     p = packet44;
   } else if (framer_.transport_version() == QUIC_VERSION_41) {
     p = packet41;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  } else if (framer_.transport_version() != QUIC_VERSION_35) {
     p = packet39;
   }
   QuicFramerFuzzFunc(p,
diff --git a/net/third_party/quic/core/quic_headers_stream_test.cc b/net/third_party/quic/core/quic_headers_stream_test.cc
index a2ea32b..86744f0 100644
--- a/net/third_party/quic/core/quic_headers_stream_test.cc
+++ b/net/third_party/quic/core/quic_headers_stream_test.cc
@@ -600,7 +600,6 @@
 }
 
 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
-  SetQuicReloadableFlag(quic_send_max_header_list_size, true);
   const uint32_t kTestHeaderTableSize = 1000;
   SpdySettingsIR data;
   // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE,
@@ -616,7 +615,6 @@
 }
 
 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
-  SetQuicReloadableFlag(quic_send_max_header_list_size, true);
   SpdySettingsIR data;
   // Does not support SETTINGS_MAX_CONCURRENT_STREAMS,
   // SETTINGS_INITIAL_WINDOW_SIZE, SETTINGS_ENABLE_PUSH and
diff --git a/net/third_party/quic/core/quic_ietf_framer_test.cc b/net/third_party/quic/core/quic_ietf_framer_test.cc
index 329a754..5a15137 100644
--- a/net/third_party/quic/core/quic_ietf_framer_test.cc
+++ b/net/third_party/quic/core/quic_ietf_framer_test.cc
@@ -106,8 +106,6 @@
 
   bool OnStreamFrame(const QuicStreamFrame& frame) override { return true; }
 
-  bool OnAckFrame(const QuicAckFrame& frame) override { return true; }
-
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override {
     return true;
@@ -297,24 +295,6 @@
     // framing and upshift on deframing results in clearing the 3
     // low-order bits ... The masking basically does the same thing,
     // so the compare works properly.
-    if (!framer_.use_incremental_ack_processing()) {
-      // incremental ack processing does not set these in the
-      // QuicAckFrame so test them only if we are not doing
-      // incremental ack.
-      EXPECT_EQ(transmit_frame.ack_delay_time.ToMicroseconds() & ~0x7,
-                receive_frame.ack_delay_time.ToMicroseconds() & ~0x7);
-      EXPECT_EQ(transmit_frame.packets.NumIntervals(),
-                receive_frame.packets.NumIntervals());
-      // now go through the two sets of intervals....
-      auto xmit_itr = transmit_frame.packets.begin();  // first range
-      auto recv_itr = receive_frame.packets.begin();   // first range
-      while (xmit_itr != transmit_frame.packets.end()) {
-        EXPECT_EQ(xmit_itr->max(), recv_itr->max());
-        EXPECT_EQ(xmit_itr->min(), recv_itr->min());
-        xmit_itr++;
-        recv_itr++;
-      }
-    }
     return true;
   }
 
@@ -727,16 +707,6 @@
 
   // Now check that the received frame matches the sent frame.
   EXPECT_EQ(transmit_frame.largest_acked, receive_frame.largest_acked);
-
-  if (!framer_.use_incremental_ack_processing()) {
-    // Transmit QuicAckFrame had no explicit ranges -- which means no
-    // intervals are in the frame.
-    EXPECT_EQ(0u, transmit_frame.packets.NumIntervals());
-    // However, the actual serialization generates a FirstAckBlock and,
-    // therefore, when we deserialize, we should get a single interval
-    // in the Receive QuicAckFrame.
-    EXPECT_EQ(1u, receive_frame.packets.NumIntervals());
-  }
 }
 
 TEST_F(QuicIetfFramerTest, PathChallengeFrame) {
diff --git a/net/third_party/quic/core/quic_packet_creator_test.cc b/net/third_party/quic/core/quic_packet_creator_test.cc
index 9f0b91e..dc9959d 100644
--- a/net/third_party/quic/core/quic_packet_creator_test.cc
+++ b/net/third_party/quic/core/quic_packet_creator_test.cc
@@ -281,26 +281,22 @@
       EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
       EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
       EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
-      if (client_framer_.use_incremental_ack_processing()) {
-        EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
+      EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
+          .WillOnce(Return(true));
+      // This test includes an ack frame with largest_acked == 0 and
+      // the size of the first ack-block == 1 (serialized as
+      // 0). This is an invalid format for pre-version99, valid
+      // for version 99.
+      if (client_framer_.transport_version() != QUIC_VERSION_99) {
+        // pre-version 99; ensure that the error is gracefully
+        // handled.
+        EXPECT_CALL(framer_visitor_, OnAckRange(1, 1, true))
             .WillOnce(Return(true));
-        // This test includes an ack frame with largest_acked == 0 and
-        // the size of the first ack-block == 1 (serialized as
-        // 0). This is an invalid format for pre-version99, valid
-        // for version 99.
-        if (client_framer_.transport_version() != QUIC_VERSION_99) {
-          // pre-version 99; ensure that the error is gracefully
-          // handled.
-          EXPECT_CALL(framer_visitor_, OnAckRange(1, 1, true))
-              .WillOnce(Return(true));
-        } else {
-          // version 99; ensure that the correct packet is signalled
-          // properly.
-          EXPECT_CALL(framer_visitor_, OnAckRange(0, 1, true))
-              .WillOnce(Return(true));
-        }
       } else {
-        EXPECT_CALL(framer_visitor_, OnAckFrame(_));
+        // version 99; ensure that the correct packet is signalled
+        // properly.
+        EXPECT_CALL(framer_visitor_, OnAckRange(0, 1, true))
+            .WillOnce(Return(true));
       }
       EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
       EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.cc b/net/third_party/quic/core/quic_sent_packet_manager.cc
index f1f2fc5..8bc4104 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager.cc
+++ b/net/third_party/quic/core/quic_sent_packet_manager.cc
@@ -170,7 +170,7 @@
               config.HasClientRequestedIndependentOption(kQBIC,
                                                          perspective_))) {
     SetSendAlgorithm(kCubicBytes);
-  } else if (GetQuicReloadableFlag(quic_enable_pcc2) &&
+  } else if (GetQuicReloadableFlag(quic_enable_pcc3) &&
              config.HasClientRequestedIndependentOption(kTPCC, perspective_)) {
     SetSendAlgorithm(kPCC);
   }
@@ -267,22 +267,6 @@
   }
 }
 
-bool QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
-                                          QuicTime ack_receive_time) {
-  DCHECK_LE(LargestAcked(ack_frame), unacked_packets_.largest_sent_packet());
-  QuicByteCount prior_in_flight = unacked_packets_.bytes_in_flight();
-  bool rtt_updated = MaybeUpdateRTT(LargestAcked(ack_frame),
-                                    ack_frame.ack_delay_time, ack_receive_time);
-  DCHECK_GE(LargestAcked(ack_frame), unacked_packets_.largest_observed());
-  unacked_packets_.IncreaseLargestObserved(LargestAcked(ack_frame));
-
-  HandleAckForSentPackets(ack_frame);
-  const bool acked_new_packet = !packets_acked_.empty();
-  PostProcessAfterMarkingPacketHandled(ack_frame, ack_receive_time, rtt_updated,
-                                       prior_in_flight);
-  return acked_new_packet;
-}
-
 void QuicSentPacketManager::PostProcessAfterMarkingPacketHandled(
     const QuicAckFrame& ack_frame,
     QuicTime ack_receive_time,
@@ -326,9 +310,12 @@
 
   if (debug_delegate_ != nullptr) {
     debug_delegate_->OnIncomingAck(ack_frame, ack_receive_time,
-                                   unacked_packets_.largest_observed(),
+                                   unacked_packets_.largest_acked(),
                                    rtt_updated, GetLeastUnacked());
   }
+  // Remove packets below least unacked from all_packets_acked_ and
+  // last_ack_frame_.
+  last_ack_frame_.packets.RemoveUpTo(unacked_packets_.GetLeastUnacked());
 }
 
 void QuicSentPacketManager::MaybeInvokeCongestionEvent(
@@ -352,44 +339,6 @@
   }
 }
 
-void QuicSentPacketManager::HandleAckForSentPackets(
-    const QuicAckFrame& ack_frame) {
-  // Go through the packets we have not received an ack for and see if this
-  // incoming_ack shows they've been seen by the peer.
-  QuicTime::Delta ack_delay_time = ack_frame.ack_delay_time;
-  QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
-  for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
-       it != unacked_packets_.end(); ++it, ++packet_number) {
-    if (packet_number > LargestAcked(ack_frame)) {
-      // These packets are still in flight.
-      break;
-    }
-    if (!QuicUtils::IsAckable(it->state)) {
-      continue;
-    }
-    if (!ack_frame.packets.Contains(packet_number)) {
-      // Packet is still missing.
-      continue;
-    }
-    // Packet was acked, so remove it from our unacked packet list.
-    QUIC_DVLOG(1) << ENDPOINT << "Got an ack for packet " << packet_number;
-    if (it->largest_acked > 0) {
-      largest_packet_peer_knows_is_acked_ =
-          std::max(largest_packet_peer_knows_is_acked_, it->largest_acked);
-    }
-    // If data is associated with the most recent transmission of this
-    // packet, then inform the caller.
-    if (it->in_flight) {
-      packets_acked_.emplace_back(packet_number, it->bytes_sent,
-                                  QuicTime::Zero());
-    } else {
-      // Unackable packets are skipped earlier.
-      largest_newly_acked_ = packet_number;
-    }
-    MarkPacketHandled(packet_number, &(*it), ack_delay_time);
-  }
-}
-
 void QuicSentPacketManager::RetransmitUnackedPackets(
     TransmissionType retransmission_type) {
   DCHECK(retransmission_type == ALL_UNACKED_RETRANSMISSION ||
@@ -683,8 +632,6 @@
       return;
     }
     case TLP_MODE:
-      // If no tail loss probe can be sent, because there are no retransmittable
-      // packets, execute a conventional RTO to abandon old packets.
       ++stats_->tlp_count;
       ++consecutive_tlp_count_;
       pending_timer_transmission_count_ = 1;
@@ -729,6 +676,23 @@
   }
 }
 
+bool QuicSentPacketManager::MaybeRetransmitTailLossProbe() {
+  if (pending_timer_transmission_count_ == 0) {
+    return false;
+  }
+  if (!MaybeRetransmitOldestPacket(TLP_RETRANSMISSION)) {
+    // If no tail loss probe can be sent, because there are no retransmittable
+    // packets, execute a conventional RTO to abandon old packets.
+    if (GetQuicReloadableFlag(quic_optimize_inflight_check)) {
+      QUIC_FLAG_COUNT(quic_reloadable_flag_quic_optimize_inflight_check);
+      pending_timer_transmission_count_ = 0;
+      RetransmitRtoPackets();
+    }
+    return false;
+  }
+  return true;
+}
+
 bool QuicSentPacketManager::MaybeRetransmitOldestPacket(TransmissionType type) {
   QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
   for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
@@ -806,7 +770,8 @@
     return LOSS_MODE;
   }
   if (consecutive_tlp_count_ < max_tail_loss_probes_) {
-    if (unacked_packets_.HasUnackedRetransmittableFrames()) {
+    if (GetQuicReloadableFlag(quic_optimize_inflight_check) ||
+        unacked_packets_.HasUnackedRetransmittableFrames()) {
       return TLP_MODE;
     }
   }
@@ -855,7 +820,7 @@
       unacked_packets_.GetTransmissionInfo(largest_acked);
   // Ensure the packet has a valid sent time.
   if (transmission_info.sent_time == QuicTime::Zero()) {
-    QUIC_BUG << "Acked packet has zero sent time, largest_observed:"
+    QUIC_BUG << "Acked packet has zero sent time, largest_acked:"
              << largest_acked;
     return false;
   }
@@ -890,7 +855,8 @@
       pending_timer_transmission_count_ > 0) {
     return QuicTime::Zero();
   }
-  if (!unacked_packets_.HasUnackedRetransmittableFrames()) {
+  if (!GetQuicReloadableFlag(quic_optimize_inflight_check) &&
+      !unacked_packets_.HasUnackedRetransmittableFrames()) {
     return QuicTime::Zero();
   }
   switch (GetRetransmissionMode()) {
@@ -1051,7 +1017,7 @@
   DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet());
   rtt_updated_ =
       MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time);
-  DCHECK_GE(largest_acked, unacked_packets_.largest_observed());
+  DCHECK_GE(largest_acked, unacked_packets_.largest_acked());
   last_ack_frame_.ack_delay_time = ack_delay_time;
   acked_packets_iter_ = last_ack_frame_.packets.rbegin();
 }
@@ -1060,7 +1026,7 @@
                                        QuicPacketNumber end) {
   if (end > last_ack_frame_.largest_acked + 1) {
     // Largest acked increases.
-    unacked_packets_.IncreaseLargestObserved(end - 1);
+    unacked_packets_.IncreaseLargestAcked(end - 1);
     last_ack_frame_.largest_acked = end - 1;
   }
   // Drop ack ranges which ack packets below least_unacked.
@@ -1137,11 +1103,6 @@
   const bool acked_new_packet = !packets_acked_.empty();
   PostProcessAfterMarkingPacketHandled(last_ack_frame_, ack_receive_time,
                                        rtt_updated_, prior_bytes_in_flight);
-  // TODO(fayang): Move this line to PostProcessAfterMarkingPacketHandled
-  // when deprecating quic_reloadable_flag_quic_use_incremental_ack_processing4.
-  // Remove packets below least unacked from all_packets_acked_ and
-  // last_ack_frame_.
-  last_ack_frame_.packets.RemoveUpTo(unacked_packets_.GetLeastUnacked());
 
   return acked_new_packet;
 }
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.h b/net/third_party/quic/core/quic_sent_packet_manager.h
index 3aafc96..7037836 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager.h
+++ b/net/third_party/quic/core/quic_sent_packet_manager.h
@@ -123,10 +123,6 @@
 
   void SetHandshakeConfirmed() { handshake_confirmed_ = true; }
 
-  // Processes the incoming ack. Returns true if a previously-unacked packet is
-  // acked.
-  bool OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
-
   // Requests retransmission of all unacked packets of |retransmission_type|.
   // The behavior of this method depends on the value of |retransmission_type|:
   // ALL_UNACKED_RETRANSMISSION - All unacked packets will be retransmitted.
@@ -143,12 +139,7 @@
 
   // Retransmits the oldest pending packet there is still a tail loss probe
   // pending.  Invoked after OnRetransmissionTimeout.
-  bool MaybeRetransmitTailLossProbe() {
-    if (pending_timer_transmission_count_ == 0) {
-      return false;
-    }
-    return MaybeRetransmitOldestPacket(TLP_RETRANSMISSION);
-  }
+  bool MaybeRetransmitTailLossProbe();
 
   // Retransmits the oldest pending packet.
   bool MaybeRetransmitOldestPacket(TransmissionType type);
@@ -289,7 +280,7 @@
   }
 
   QuicPacketNumber GetLargestObserved() const {
-    return unacked_packets_.largest_observed();
+    return unacked_packets_.largest_acked();
   }
 
   QuicPacketNumber GetLargestSentPacket() const {
@@ -341,6 +332,8 @@
   QuicTime::Delta delayed_ack_time() const { return delayed_ack_time_; }
 
   void set_delayed_ack_time(QuicTime::Delta delayed_ack_time) {
+    // The delayed ack time should never be more than one half the min RTO time.
+    DCHECK_LE(delayed_ack_time, (min_rto_timeout_ * 0.5));
     delayed_ack_time_ = delayed_ack_time;
   }
 
@@ -369,9 +362,6 @@
   typedef QuicLinkedHashMap<QuicPacketNumber, TransmissionType>
       PendingRetransmissionMap;
 
-  // Process the incoming ack looking for newly ack'd data packets.
-  void HandleAckForSentPackets(const QuicAckFrame& ack_frame);
-
   // Returns the current retransmission mode.
   RetransmissionTimeoutMode GetRetransmissionMode() const;
 
@@ -568,8 +558,7 @@
   // Latest received ack frame.
   QuicAckFrame last_ack_frame_;
 
-  // Record whether RTT gets updated by last largest acked. This is only used
-  // when quic_reloadable_flag_quic_use_incremental_ack_processing4 is true.
+  // Record whether RTT gets updated by last largest acked..
   bool rtt_updated_;
 
   // Latched value of quic_reloadable_flag_quic_extra_checks_in_ack_processing.
@@ -577,8 +566,7 @@
   QuicDebugInfoProviderInterface* debug_info_provider_;
 
   // A reverse iterator of last_ack_frame_.packets. This is reset in
-  // OnAckRangeStart, and gradually moves in OnAckRange. This is only used
-  // when quic_reloadable_flag_quic_use_incremental_ack_processing4 is true.
+  // OnAckRangeStart, and gradually moves in OnAckRange..
   PacketNumberQueue::const_reverse_iterator acked_packets_iter_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManager);
diff --git a/net/third_party/quic/core/quic_sent_packet_manager_test.cc b/net/third_party/quic/core/quic_sent_packet_manager_test.cc
index 0214e9a..e4c7af3 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager_test.cc
+++ b/net/third_party/quic/core/quic_sent_packet_manager_test.cc
@@ -348,16 +348,10 @@
   RetransmitAndSendPacket(1, 2);
 
   // Ack 2 but not 1.
-  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
-
   ExpectAck(2);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(2, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(2, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   if (manager_.session_decides_what_to_write()) {
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
@@ -384,15 +378,10 @@
     EXPECT_TRUE(manager_.HasPendingRetransmissions());
   }
   // Ack 1.
-  QuicAckFrame ack_frame = InitAckFrame(1);
   ExpectAck(1);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   // There should no longer be a pending retransmission.
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -443,14 +432,9 @@
 
   // Ack 1 but not 2.
   ExpectAck(1);
-  QuicAckFrame ack_frame = InitAckFrame(1);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   if (manager_.session_decides_what_to_write()) {
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
@@ -463,14 +447,9 @@
     // Ack 2 causes 2 be considered as spurious retransmission.
     EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
     ExpectAck(2);
-    QuicAckFrame ack_frame2 = InitAckFrame(2);
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-      manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
-      manager_.OnAckRange(1, 3);
-      EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-    } else {
-      manager_.OnIncomingAck(ack_frame2, clock_.ApproximateNow());
-    }
+    manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+    manager_.OnAckRange(1, 3);
+    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   }
 
   EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
@@ -484,14 +463,9 @@
 
   // First, ACK packet 1 which makes packet 2 non-retransmittable.
   ExpectAck(1);
-  QuicAckFrame ack_frame = InitAckFrame(1);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   SendDataPacket(3);
   SendDataPacket(4);
@@ -499,43 +473,27 @@
   clock_.AdvanceTime(rtt);
 
   // Next, NACK packet 2 three times.
-  ack_frame = InitAckFrame({{1, 2}, {3, 4}});
-
   ExpectAck(3);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 4);
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 4);
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
-  ack_frame = InitAckFrame({{1, 2}, {3, 5}});
   ExpectAck(4);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 5);
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 5);
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
-  ack_frame = InitAckFrame({{1, 2}, {3, 6}});
   ExpectAckAndLoss(true, 5, 2);
   if (manager_.session_decides_what_to_write()) {
     // Frames in all packets are acked.
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 6);
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 6);
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   // No packets remain unacked.
   VerifyUnackedPackets(nullptr, 0);
@@ -561,16 +519,11 @@
   // Ack 1 but not 2, before 2 is able to be sent.
   // Since 1 has been retransmitted, it has already been lost, and so the
   // send algorithm is not informed that it has been ACK'd.
-  QuicAckFrame ack_frame = InitAckFrame(1);
   ExpectUpdatedRtt(1);
   EXPECT_CALL(*send_algorithm_, RevertRetransmissionTimeout());
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   // Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT.
   QuicPacketNumber unacked[] = {2};
@@ -604,14 +557,9 @@
 
   // Ack 1 but not 2 or 3.
   ExpectAck(1);
-  QuicAckFrame ack_frame = InitAckFrame(1);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   if (manager_.session_decides_what_to_write()) {
     // Frames in packets 2 and 3 are acked.
     EXPECT_CALL(notifier_, IsFrameOutstanding(_))
@@ -633,38 +581,28 @@
         .WillOnce(Return(false))
         .WillRepeatedly(Return(true));
   }
-  ack_frame = InitAckFrame({{1, 2}, {3, 5}});
   QuicPacketNumber acked[] = {3, 4};
   ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 5);
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 5);
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   QuicPacketNumber unacked2[] = {2};
   VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
   EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
 
   SendDataPacket(5);
-  ack_frame = InitAckFrame({{1, 2}, {3, 6}});
   ExpectAckAndLoss(true, 5, 2);
   EXPECT_CALL(debug_delegate, OnPacketLoss(2, LOSS_RETRANSMISSION, _));
   if (manager_.session_decides_what_to_write()) {
     // Frames in all packetss are acked.
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 6);
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 6);
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   VerifyUnackedPackets(nullptr, 0);
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
@@ -687,53 +625,36 @@
   // Ack original transmission, but that wasn't lost via fast retransmit,
   // so no call on OnSpuriousRetransmission is expected.
   {
-    QuicAckFrame ack_frame = InitAckFrame(1);
     ExpectAck(1);
     EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-      manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-      manager_.OnAckRange(1, 2);
-      EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-    } else {
-      EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-    }
+    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+    manager_.OnAckRange(1, 2);
+    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   }
 
   SendDataPacket(3);
   SendDataPacket(4);
   // Ack 4, which causes 3 to be retransmitted.
   {
-    QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {4, 5}});
     ExpectAck(4);
     EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-      manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
-      manager_.OnAckRange(4, 5);
-      manager_.OnAckRange(1, 2);
-      EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-    } else {
-      EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-    }
+    manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+    manager_.OnAckRange(4, 5);
+    manager_.OnAckRange(1, 2);
+    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
     RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
   }
 
   // Ack 3, which causes SpuriousRetransmitDetected to be called.
   {
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-      QuicPacketNumber acked[] = {3};
-      ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-    }
-    QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {3, 5}});
+    QuicPacketNumber acked[] = {3};
+    ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
     EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
     EXPECT_CALL(*loss_algorithm, SpuriousRetransmitDetected(_, _, _, 5));
-    if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-      manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
-      manager_.OnAckRange(3, 5);
-      manager_.OnAckRange(1, 2);
-      EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-    } else {
-      EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-    }
+    manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+    manager_.OnAckRange(3, 5);
+    manager_.OnAckRange(1, 2);
+    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
     if (manager_.session_decides_what_to_write()) {
       // Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
       // 5 will cause 5 be considered as a spurious retransmission as no new
@@ -741,15 +662,10 @@
       ExpectAck(5);
       EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
       EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
-      QuicAckFrame ack_frame2 = InitAckFrame({{1, 2}, {3, 6}});
-      if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-        manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
-        manager_.OnAckRange(3, 6);
-        manager_.OnAckRange(1, 2);
-        EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-      } else {
-        manager_.OnIncomingAck(ack_frame2, clock_.Now());
-      }
+      manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+      manager_.OnAckRange(3, 6);
+      manager_.OnAckRange(1, 2);
+      EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
     }
   }
 }
@@ -769,42 +685,22 @@
   SendAckPacket(2, 1);
 
   // Now ack the ack and expect an RTT update.
-  QuicAckFrame ack_frame = InitAckFrame(2);
-  ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(5);
-
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    QuicPacketNumber acked[] = {1, 2};
-    ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  } else {
-    ExpectAck(1);
-  }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5),
-                             clock_.Now());
-    manager_.OnAckRange(1, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  QuicPacketNumber acked[] = {1, 2};
+  ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+  manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5),
+                           clock_.Now());
+  manager_.OnAckRange(1, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(1u, manager_.largest_packet_peer_knows_is_acked());
 
   SendAckPacket(3, 3);
 
   // Now ack the ack and expect only an RTT update.
-  ack_frame = InitAckFrame(3);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    QuicPacketNumber acked[] = {3};
-    ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  } else {
-    ExpectUpdatedRtt(3);
-  }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 4);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  QuicPacketNumber acked2[] = {3};
+  ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
+  manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 4);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(3u, manager_.largest_packet_peer_knows_is_acked());
 }
 
@@ -815,14 +711,9 @@
   clock_.AdvanceTime(expected_rtt);
 
   ExpectAck(packet_number);
-  QuicAckFrame ack_frame = InitAckFrame(packet_number);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
 }
 
@@ -836,16 +727,10 @@
   clock_.AdvanceTime(expected_rtt);
 
   ExpectAck(packet_number);
-  QuicAckFrame ack_frame = InitAckFrame(packet_number);
-  ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(11);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11),
-                             clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11),
+                           clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
 }
 
@@ -858,15 +743,9 @@
   clock_.AdvanceTime(expected_rtt);
 
   ExpectAck(packet_number);
-  QuicAckFrame ack_frame = InitAckFrame(packet_number);
-  ack_frame.ack_delay_time = QuicTime::Delta::Infinite();
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
 }
 
@@ -879,15 +758,9 @@
   clock_.AdvanceTime(expected_rtt);
 
   ExpectAck(packet_number);
-  QuicAckFrame ack_frame = InitAckFrame(packet_number);
-  ack_frame.ack_delay_time = QuicTime::Delta::Zero();
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Zero(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Zero(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
 }
 
@@ -935,21 +808,15 @@
   // Ack the third and ensure the first two are still pending.
   ExpectAck(3);
 
-  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 4);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 4);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
 
   // Acking two more packets will lose both of them due to nacks.
   SendDataPacket(4);
   SendDataPacket(5);
-  ack_frame = InitAckFrame({{3, 6}});
   QuicPacketNumber acked[] = {4, 5};
   QuicPacketNumber lost[] = {1, 2};
   ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
@@ -958,13 +825,9 @@
     // Frames in all packets are acked.
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 6);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 6);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
@@ -1055,7 +918,6 @@
     EXPECT_TRUE(manager_.HasPendingRetransmissions());
     RetransmitNextPacket(103);
   }
-  QuicAckFrame ack_frame = InitAckFrame({{103, 104}});
   QuicPacketNumber largest_acked = 103;
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
   EXPECT_CALL(*send_algorithm_,
@@ -1072,13 +934,9 @@
     // Packets 1, 2 and [4, 102] are lost.
     EXPECT_CALL(notifier_, OnFrameLost(_)).Times(101);
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(103, 104);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(103, 104);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   // All packets before 103 should be lost.
   if (manager_.session_decides_what_to_write()) {
     // Packet 104 is still in flight.
@@ -1136,19 +994,14 @@
   // and ensure the first four crypto packets get abandoned, but not lost.
   QuicPacketNumber acked[] = {3, 4, 5, 8, 9};
   ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  QuicAckFrame ack_frame = InitAckFrame({{3, 6}, {8, 10}});
   if (manager_.session_decides_what_to_write()) {
     EXPECT_CALL(notifier_, HasPendingCryptoData())
         .WillRepeatedly(Return(false));
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(8, 10);
-    manager_.OnAckRange(3, 6);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(8, 10);
+  manager_.OnAckRange(3, 6);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
 }
@@ -1214,14 +1067,9 @@
   // crypto packets.
   QuicPacketNumber acked[] = {8, 9};
   ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  QuicAckFrame ack_frame = InitAckFrame({{8, 10}});
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(8, 10);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(8, 10);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   if (manager_.session_decides_what_to_write()) {
     EXPECT_CALL(notifier_, HasPendingCryptoData())
         .WillRepeatedly(Return(false));
@@ -1256,25 +1104,16 @@
 
   // Now ack the second crypto packet, and ensure the first gets removed, but
   // the third does not.
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    QuicPacketNumber acked[] = {2};
-    ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  } else {
-    ExpectUpdatedRtt(2);
-  }
-  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
+  QuicPacketNumber acked[] = {2};
+  ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
   if (manager_.session_decides_what_to_write()) {
     EXPECT_CALL(notifier_, HasPendingCryptoData())
         .WillRepeatedly(Return(false));
     EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(2, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(2, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
   QuicPacketNumber unacked[] = {3};
@@ -1389,20 +1228,11 @@
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
 
   // Ensure both packets get discarded when packet 2 is acked.
-  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    QuicPacketNumber acked[] = {3};
-    ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
-  } else {
-    ExpectUpdatedRtt(3);
-  }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(3, 4);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  QuicPacketNumber acked[] = {3};
+  ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+  manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(3, 4);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   VerifyUnackedPackets(nullptr, 0);
   VerifyRetransmittablePackets(nullptr, 0);
 }
@@ -1443,8 +1273,6 @@
   }
 
   // Ack a retransmission.
-  QuicAckFrame ack_frame = InitAckFrame({{102, 103}});
-  ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   // Ensure no packets are lost.
   QuicPacketNumber largest_acked = 102;
   EXPECT_CALL(*send_algorithm_,
@@ -1470,13 +1298,9 @@
     // retransmittable frames as packet 102 is acked.
     EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
-    manager_.OnAckRange(102, 103);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
+  manager_.OnAckRange(102, 103);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 }
 
 TEST_P(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) {
@@ -1573,8 +1397,6 @@
   }
 
   // Ack a retransmission and expect no call to OnRetransmissionTimeout.
-  QuicAckFrame ack_frame = InitAckFrame({{102, 103}});
-  ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   // This will include packets in the lost packet map.
   QuicPacketNumber largest_acked = 102;
   EXPECT_CALL(*send_algorithm_,
@@ -1594,13 +1416,9 @@
     // retransmittable frames as packet 102 is acked.
     EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
   }
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
-    manager_.OnAckRange(102, 103);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
+  manager_.OnAckRange(102, 103);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 }
 
 TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
@@ -1644,16 +1462,10 @@
 
   // Ack a retransmission and ensure OnRetransmissionTimeout is called.
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
-  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
-  ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   ExpectAck(2);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::Zero(), clock_.Now());
-    manager_.OnAckRange(2, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(2, QuicTime::Delta::Zero(), clock_.Now());
+  manager_.OnAckRange(2, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   // The original packet and newest should be outstanding.
   EXPECT_EQ(2 * kDefaultLength,
@@ -1701,16 +1513,10 @@
 
   // Ack a retransmission and ensure OnRetransmissionTimeout is called.
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
-  QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
-  ack_frame.ack_delay_time = QuicTime::Delta::Zero();
   ExpectAck(3);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(3, QuicTime::Delta::Zero(), clock_.Now());
-    manager_.OnAckRange(3, 4);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(3, QuicTime::Delta::Zero(), clock_.Now());
+  manager_.OnAckRange(3, 4);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   // The first two packets should still be outstanding.
   EXPECT_EQ(2 * kDefaultLength,
@@ -1890,15 +1696,10 @@
 
   // Ack a packet before the first RTO and ensure the RTO timeout returns to the
   // original value and OnRetransmissionTimeout is not called or reverted.
-  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
   ExpectAck(2);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(2, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
-  }
+  manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(2, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
   EXPECT_FALSE(manager_.HasPendingRetransmissions());
   EXPECT_EQ(5 * kDefaultLength,
             QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
@@ -2030,14 +1831,9 @@
   // set the loss timeout.
   ExpectAck(2);
   EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
-  QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(2, 3);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(2, 3);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 
   QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10));
   EXPECT_CALL(*loss_algorithm, GetLossTimeout())
@@ -2558,17 +2354,12 @@
   EXPECT_CALL(*network_change_visitor_,
               OnPathMtuIncreased(kDefaultLength + 100));
   QuicAckFrame ack_frame = InitAckFrame(1);
-  if (GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
-    manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
-    manager_.OnAckRange(1, 2);
-    EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
-  } else {
-    EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
-  }
+  manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+  manager_.OnAckRange(1, 2);
+  EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
 }
 
 TEST_P(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
-  SetQuicReloadableFlag(quic_use_incremental_ack_processing4, true);
   // Send packets 1 - 20.
   for (size_t i = 1; i <= 20; ++i) {
     SendDataPacket(i);
diff --git a/net/third_party/quic/core/quic_spdy_client_session.cc b/net/third_party/quic/core/quic_spdy_client_session.cc
index fae3e83..e06c9c8 100644
--- a/net/third_party/quic/core/quic_spdy_client_session.cc
+++ b/net/third_party/quic/core/quic_spdy_client_session.cc
@@ -8,6 +8,7 @@
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/quic_server_id.h"
+#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
diff --git a/net/third_party/quic/core/quic_spdy_client_session_base.cc b/net/third_party/quic/core/quic_spdy_client_session_base.cc
index 3145fc0..c1d959f 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_base.cc
+++ b/net/third_party/quic/core/quic_spdy_client_session_base.cc
@@ -10,6 +10,8 @@
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 
+using spdy::SpdyHeaderBlock;
+
 namespace quic {
 
 QuicSpdyClientSessionBase::QuicSpdyClientSessionBase(
@@ -40,7 +42,7 @@
 
 void QuicSpdyClientSessionBase::OnInitialHeadersComplete(
     QuicStreamId stream_id,
-    const spdy::SpdyHeaderBlock& response_headers) {
+    const SpdyHeaderBlock& response_headers) {
   // Note that the strong ordering of the headers stream means that
   // QuicSpdyClientStream::OnPromiseHeadersComplete must have already
   // been called (on the associated stream) if this is a promised
@@ -77,10 +79,9 @@
   stream->OnPromiseHeaderList(promised_stream_id, frame_len, header_list);
 }
 
-bool QuicSpdyClientSessionBase::HandlePromised(
-    QuicStreamId /* associated_id */,
-    QuicStreamId promised_id,
-    const spdy::SpdyHeaderBlock& headers) {
+bool QuicSpdyClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
+                                               QuicStreamId promised_id,
+                                               const SpdyHeaderBlock& headers) {
   // Due to pathalogical packet re-ordering, it is possible that
   // frames for the promised stream have already arrived, and the
   // promised stream could be active or closed.
diff --git a/net/third_party/quic/core/quic_spdy_client_session_test.cc b/net/third_party/quic/core/quic_spdy_client_session_test.cc
index 5b00f180..142fe2af 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_test.cc
+++ b/net/third_party/quic/core/quic_spdy_client_session_test.cc
@@ -4,13 +4,14 @@
 
 #include "net/third_party/quic/core/quic_spdy_client_session.h"
 
+#include <memory>
 #include <vector>
 
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
-#include "net/third_party/quic/platform/api/quic_flags.h"
+#include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_socket_address.h"
 #include "net/third_party/quic/platform/api/quic_str_cat.h"
@@ -25,7 +26,7 @@
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
 
-using google::protobuf::implicit_cast;
+using spdy::SpdyHeaderBlock;
 using testing::_;
 using testing::AnyNumber;
 using testing::Invoke;
@@ -125,7 +126,7 @@
   PacketSavingConnection* connection_;
   std::unique_ptr<TestQuicSpdyClientSession> session_;
   QuicClientPushPromiseIndex push_promise_index_;
-  spdy::SpdyHeaderBlock push_promise_;
+  SpdyHeaderBlock push_promise_;
   QuicString promise_url_;
   QuicStreamId promised_stream_id_;
   QuicStreamId associated_stream_id_;
@@ -178,8 +179,8 @@
   EXPECT_TRUE(session_->CreateOutgoingDynamicStream() == nullptr);
   // Verify that no data may be send on existing streams.
   char data[] = "hello world";
-  QuicConsumedData consumed =
-      session_->WritevData(stream, stream->id(), arraysize(data), 0, NO_FIN);
+  QuicConsumedData consumed = session_->WritevData(
+      stream, stream->id(), QUIC_ARRAYSIZE(data), 0, NO_FIN);
   EXPECT_FALSE(consumed.fin_consumed);
   EXPECT_EQ(0u, consumed.bytes_consumed);
 }
@@ -462,7 +463,7 @@
               OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM));
 
   session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM);
-  spdy::SpdyHeaderBlock promise_headers;
+  SpdyHeaderBlock promise_headers;
   EXPECT_FALSE(session_->HandlePromised(associated_stream_id_,
                                         promised_stream_id_, promise_headers));
 
@@ -559,16 +560,14 @@
   EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr);
   EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
 
-  session_->OnInitialHeadersComplete(promised_stream_id_,
-                                     spdy::SpdyHeaderBlock());
+  session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
 }
 
 TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsNotPush) {
   // Initialize crypto before the client session will create a stream.
   CompleteCryptoHandshake();
   session_->CreateOutgoingDynamicStream();
-  session_->OnInitialHeadersComplete(promised_stream_id_,
-                                     spdy::SpdyHeaderBlock());
+  session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock());
 }
 
 TEST_P(QuicSpdyClientSessionTest, DeletePromised) {
diff --git a/net/third_party/quic/core/quic_spdy_client_stream.cc b/net/third_party/quic/core/quic_spdy_client_stream.cc
index 88517ba2..c03f47d 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream.cc
+++ b/net/third_party/quic/core/quic_spdy_client_stream.cc
@@ -13,7 +13,7 @@
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/spdy/core/spdy_protocol.h"
 
-using std::string;
+using spdy::SpdyHeaderBlock;
 
 namespace quic {
 
@@ -80,7 +80,7 @@
     const QuicHeaderList& header_list) {
   header_bytes_read_ += frame_len;
   int64_t content_length = -1;
-  spdy::SpdyHeaderBlock promise_headers;
+  SpdyHeaderBlock promise_headers;
   if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length,
                                          &promise_headers)) {
     QUIC_DLOG(ERROR) << "Failed to parse promise headers: "
@@ -127,7 +127,7 @@
   }
 }
 
-size_t QuicSpdyClientStream::SendRequest(spdy::SpdyHeaderBlock headers,
+size_t QuicSpdyClientStream::SendRequest(SpdyHeaderBlock headers,
                                          QuicStringPiece body,
                                          bool fin) {
   QuicConnection::ScopedPacketFlusher flusher(
diff --git a/net/third_party/quic/core/quic_spdy_client_stream.h b/net/third_party/quic/core/quic_spdy_client_stream.h
index 9710404..5fe0e36 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream.h
+++ b/net/third_party/quic/core/quic_spdy_client_stream.h
@@ -5,8 +5,7 @@
 #ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_STREAM_H_
 #define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_STREAM_H_
 
-#include <stddef.h>
-#include <sys/types.h>
+#include <cstddef>
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/quic_packets.h"
diff --git a/net/third_party/quic/core/quic_spdy_client_stream_test.cc b/net/third_party/quic/core/quic_spdy_client_stream_test.cc
index 391efe64..33c713b 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream_test.cc
+++ b/net/third_party/quic/core/quic_spdy_client_stream_test.cc
@@ -21,7 +21,7 @@
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
 
-using base::IntToString;
+using spdy::SpdyHeaderBlock;
 using testing::_;
 using testing::StrictMock;
 
@@ -88,7 +88,7 @@
   MockQuicSpdyClientSession session_;
   std::unique_ptr<QuicSpdyClientStream> stream_;
   std::unique_ptr<StreamVisitor> stream_visitor_;
-  spdy::SpdyHeaderBlock headers_;
+  SpdyHeaderBlock headers_;
   QuicString body_;
 };
 
@@ -162,6 +162,7 @@
 TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) {
   // Test that receiving trailing headers, containing a final offset, results in
   // the stream being closed at that byte offset.
+
   // Send headers as usual.
   auto headers = AsHeaderList(headers_);
   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
@@ -170,7 +171,7 @@
   // Send trailers before sending the body. Even though a FIN has been received
   // the stream should not be closed, as it does not yet have all the data bytes
   // promised by the final offset field.
-  spdy::SpdyHeaderBlock trailer_block;
+  SpdyHeaderBlock trailer_block;
   trailer_block["trailer key"] = "trailer value";
   trailer_block[kFinalOffsetHeaderKey] =
       QuicTextUtils::Uint64ToString(body_.size());
diff --git a/net/third_party/quic/core/quic_spdy_session.cc b/net/third_party/quic/core/quic_spdy_session.cc
index 87f6ff5..9127014 100644
--- a/net/third_party/quic/core/quic_spdy_session.cc
+++ b/net/third_party/quic/core/quic_spdy_session.cc
@@ -20,23 +20,48 @@
 #include "net/third_party/quic/platform/api/quic_text_utils.h"
 #include "net/third_party/spdy/core/http2_frame_decoder_adapter.h"
 
+using http2::Http2DecoderAdapter;
+using spdy::HpackEntry;
+using spdy::HpackHeaderTable;
+using spdy::Http2WeightToSpdy3Priority;
+using spdy::SETTINGS_ENABLE_PUSH;
+using spdy::SETTINGS_HEADER_TABLE_SIZE;
+using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
+using spdy::Spdy3PriorityToHttp2Weight;
+using spdy::SpdyErrorCode;
+using spdy::SpdyFramer;
+using spdy::SpdyFramerDebugVisitorInterface;
+using spdy::SpdyFramerVisitorInterface;
+using spdy::SpdyFrameType;
+using spdy::SpdyHeaderBlock;
+using spdy::SpdyHeadersHandlerInterface;
+using spdy::SpdyHeadersIR;
+using spdy::SpdyKnownSettingsId;
+using spdy::SpdyPingId;
+using spdy::SpdyPriority;
+using spdy::SpdyPriorityIR;
+using spdy::SpdyPushPromiseIR;
+using spdy::SpdySerializedFrame;
+using spdy::SpdySettingsId;
+using spdy::SpdySettingsIR;
+using spdy::SpdyStreamId;
+
 namespace quic {
 
 namespace {
 
-class HeaderTableDebugVisitor
-    : public spdy::HpackHeaderTable::DebugVisitorInterface {
+class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
  public:
   HeaderTableDebugVisitor(const QuicClock* clock,
                           std::unique_ptr<QuicHpackDebugVisitor> visitor)
       : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
 
-  int64_t OnNewEntry(const spdy::HpackEntry& entry) override {
+  int64_t OnNewEntry(const HpackEntry& entry) override {
     QUIC_DVLOG(1) << entry.GetDebugString();
     return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
   }
 
-  void OnUseEntry(const spdy::HpackEntry& entry) override {
+  void OnUseEntry(const HpackEntry& entry) override {
     const QuicTime::Delta elapsed(
         clock_->ApproximateNow() -
         QuicTime::Delta::FromMicroseconds(entry.time_added()) -
@@ -58,44 +83,44 @@
 // A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
 // closes the connection if any unexpected frames are received.
 class QuicSpdySession::SpdyFramerVisitor
-    : public spdy::SpdyFramerVisitorInterface,
-      public spdy::SpdyFramerDebugVisitorInterface {
+    : public SpdyFramerVisitorInterface,
+      public SpdyFramerDebugVisitorInterface {
  public:
   explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
 
-  spdy::SpdyHeadersHandlerInterface* OnHeaderFrameStart(
-      spdy::SpdyStreamId /* stream_id */) override {
+  SpdyHeadersHandlerInterface* OnHeaderFrameStart(
+      SpdyStreamId /* stream_id */) override {
     return &header_list_;
   }
 
-  void OnHeaderFrameEnd(spdy::SpdyStreamId /* stream_id */) override {
+  void OnHeaderFrameEnd(SpdyStreamId /* stream_id */) override {
     if (session_->IsConnected()) {
       session_->OnHeaderList(header_list_);
     }
     header_list_.Clear();
   }
 
-  void OnStreamFrameData(spdy::SpdyStreamId stream_id,
+  void OnStreamFrameData(SpdyStreamId stream_id,
                          const char* data,
                          size_t len) override {
     CloseConnection("SPDY DATA frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnStreamEnd(spdy::SpdyStreamId stream_id) override {
+  void OnStreamEnd(SpdyStreamId stream_id) override {
     // The framer invokes OnStreamEnd after processing a frame that had the fin
     // bit set.
   }
 
-  void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override {
+  void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
     CloseConnection("SPDY frame padding received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnError(http2::Http2DecoderAdapter::SpdyFramerError error) override {
+  void OnError(Http2DecoderAdapter::SpdyFramerError error) override {
     QuicErrorCode code = QUIC_INVALID_HEADERS_STREAM_DATA;
     switch (error) {
-      case http2::Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE:
+      case Http2DecoderAdapter::SpdyFramerError::SPDY_DECOMPRESS_FAILURE:
         code = QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE;
         break;
       default:
@@ -103,35 +128,33 @@
     }
     CloseConnection(
         QuicStrCat("SPDY framing error: ",
-                   http2::Http2DecoderAdapter::SpdyFramerErrorToString(error)),
+                   Http2DecoderAdapter::SpdyFramerErrorToString(error)),
         code);
   }
 
-  void OnDataFrameHeader(spdy::SpdyStreamId stream_id,
+  void OnDataFrameHeader(SpdyStreamId stream_id,
                          size_t length,
                          bool fin) override {
     CloseConnection("SPDY DATA frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnRstStream(spdy::SpdyStreamId stream_id,
-                   spdy::SpdyErrorCode error_code) override {
+  void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override {
     CloseConnection("SPDY RST_STREAM frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnSetting(spdy::SpdySettingsId id, uint32_t value) override {
+  void OnSetting(SpdySettingsId id, uint32_t value) override {
     switch (id) {
-      case spdy::SETTINGS_HEADER_TABLE_SIZE:
+      case SETTINGS_HEADER_TABLE_SIZE:
         session_->UpdateHeaderEncoderTableSize(value);
         break;
-      case spdy::SETTINGS_ENABLE_PUSH:
+      case SETTINGS_ENABLE_PUSH:
         if (session_->perspective() == Perspective::IS_SERVER) {
           // See rfc7540, Section 6.5.2.
           if (value > 1) {
             CloseConnection(
-                QuicStrCat("Invalid value for spdy::SETTINGS_ENABLE_PUSH: ",
-                           value),
+                QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value),
                 QUIC_INVALID_HEADERS_STREAM_DATA);
             return;
           }
@@ -143,13 +166,10 @@
               QUIC_INVALID_HEADERS_STREAM_DATA);
         }
         break;
-      // TODO(fayang): Need to support spdy::SETTINGS_MAX_HEADER_LIST_SIZE when
+      // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
       // clients are actually sending it.
-      case spdy::SETTINGS_MAX_HEADER_LIST_SIZE:
-        if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
-          break;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
+      case SETTINGS_MAX_HEADER_LIST_SIZE:
+        break;
       default:
         CloseConnection(
             QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id),
@@ -159,21 +179,21 @@
 
   void OnSettingsEnd() override {}
 
-  void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override {
+  void OnPing(SpdyPingId unique_id, bool is_ack) override {
     CloseConnection("SPDY PING frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
-                spdy::SpdyErrorCode error_code) override {
+  void OnGoAway(SpdyStreamId last_accepted_stream_id,
+                SpdyErrorCode error_code) override {
     CloseConnection("SPDY GOAWAY frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnHeaders(spdy::SpdyStreamId stream_id,
+  void OnHeaders(SpdyStreamId stream_id,
                  bool has_priority,
                  int weight,
-                 spdy::SpdyStreamId /*parent_stream_id*/,
+                 SpdyStreamId /*parent_stream_id*/,
                  bool /*exclusive*/,
                  bool fin,
                  bool end) override {
@@ -181,21 +201,20 @@
       return;
     }
 
-    // TODO(mpw): avoid down-conversion and plumb spdy::SpdyStreamPrecedence
-    // through QuicHeadersStream.
-    spdy::SpdyPriority priority =
-        has_priority ? spdy::Http2WeightToSpdy3Priority(weight) : 0;
+    // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
+    // QuicHeadersStream.
+    SpdyPriority priority =
+        has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
     session_->OnHeaders(stream_id, has_priority, priority, fin);
   }
 
-  void OnWindowUpdate(spdy::SpdyStreamId stream_id,
-                      int delta_window_size) override {
+  void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
     CloseConnection("SPDY WINDOW_UPDATE frame received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
   }
 
-  void OnPushPromise(spdy::SpdyStreamId stream_id,
-                     spdy::SpdyStreamId promised_stream_id,
+  void OnPushPromise(SpdyStreamId stream_id,
+                     SpdyStreamId promised_stream_id,
                      bool end) override {
     if (!session_->supports_push_promise()) {
       CloseConnection("PUSH_PROMISE not supported.",
@@ -208,10 +227,10 @@
     session_->OnPushPromise(stream_id, promised_stream_id, end);
   }
 
-  void OnContinuation(spdy::SpdyStreamId stream_id, bool end) override {}
+  void OnContinuation(SpdyStreamId stream_id, bool end) override {}
 
-  void OnPriority(spdy::SpdyStreamId stream_id,
-                  spdy::SpdyStreamId parent_id,
+  void OnPriority(SpdyStreamId stream_id,
+                  SpdyStreamId parent_id,
                   int weight,
                   bool exclusive) override {
     if (session_->connection()->transport_version() <= QUIC_VERSION_42) {
@@ -223,21 +242,20 @@
       return;
     }
     // TODO (wangyix): implement real HTTP/2 weights and dependencies instead of
-    // converting to spdy::SpdyPriority.
-    spdy::SpdyPriority priority = spdy::Http2WeightToSpdy3Priority(weight);
+    // converting to SpdyPriority.
+    SpdyPriority priority = Http2WeightToSpdy3Priority(weight);
     session_->OnPriority(stream_id, priority);
   }
 
-  bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
-                      uint8_t frame_type) override {
+  bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
     CloseConnection("Unknown frame type received.",
                     QUIC_INVALID_HEADERS_STREAM_DATA);
     return false;
   }
 
-  // spdy::SpdyFramerDebugVisitorInterface implementation
-  void OnSendCompressedFrame(spdy::SpdyStreamId stream_id,
-                             spdy::SpdyFrameType type,
+  // SpdyFramerDebugVisitorInterface implementation
+  void OnSendCompressedFrame(SpdyStreamId stream_id,
+                             SpdyFrameType type,
                              size_t payload_len,
                              size_t frame_len) override {
     if (payload_len == 0) {
@@ -248,8 +266,8 @@
     QUIC_DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
   }
 
-  void OnReceiveCompressedFrame(spdy::SpdyStreamId stream_id,
-                                spdy::SpdyFrameType type,
+  void OnReceiveCompressedFrame(SpdyStreamId stream_id,
+                                SpdyFrameType type,
                                 size_t frame_len) override {
     if (session_->IsConnected()) {
       session_->OnCompressedFrameSize(frame_len);
@@ -291,7 +309,7 @@
       frame_len_(0),
       uncompressed_frame_len_(0),
       supports_push_promise_(perspective() == Perspective::IS_CLIENT),
-      spdy_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
+      spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
   h2_deframer_.set_visitor(spdy_framer_visitor_.get());
   h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
@@ -333,7 +351,7 @@
 }
 
 void QuicSpdySession::OnStreamHeadersPriority(QuicStreamId stream_id,
-                                              spdy::SpdyPriority priority) {
+                                              SpdyPriority priority) {
   QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
   if (!stream) {
     // It's quite possible to receive headers after a stream has been reset.
@@ -375,7 +393,7 @@
 }
 
 void QuicSpdySession::OnPriorityFrame(QuicStreamId stream_id,
-                                      spdy::SpdyPriority priority) {
+                                      SpdyPriority priority) {
   QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
   if (!stream) {
     // It's quite possible to receive a PRIORITY frame after a stream has been
@@ -392,24 +410,24 @@
 
 size_t QuicSpdySession::WriteHeaders(
     QuicStreamId id,
-    spdy::SpdyHeaderBlock headers,
+    SpdyHeaderBlock headers,
     bool fin,
-    spdy::SpdyPriority priority,
+    SpdyPriority priority,
     QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
   return WriteHeadersImpl(
-      id, std::move(headers), fin, spdy::Spdy3PriorityToHttp2Weight(priority),
+      id, std::move(headers), fin, Spdy3PriorityToHttp2Weight(priority),
       /*parent_stream_id=*/0, /*exclusive=*/false, std::move(ack_listener));
 }
 
 size_t QuicSpdySession::WriteHeadersImpl(
     QuicStreamId id,
-    spdy::SpdyHeaderBlock headers,
+    SpdyHeaderBlock headers,
     bool fin,
     int weight,
     QuicStreamId parent_stream_id,
     bool exclusive,
     QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
-  spdy::SpdyHeadersIR headers_frame(id, std::move(headers));
+  SpdyHeadersIR headers_frame(id, std::move(headers));
   headers_frame.set_fin(fin);
   if (perspective() == Perspective::IS_CLIENT) {
     headers_frame.set_has_priority(true);
@@ -417,7 +435,7 @@
     headers_frame.set_parent_stream_id(parent_stream_id);
     headers_frame.set_exclusive(exclusive);
   }
-  spdy::SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
+  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
   headers_stream_->WriteOrBufferData(
       QuicStringPiece(frame.data(), frame.size()), false,
       std::move(ack_listener));
@@ -431,9 +449,8 @@
   if (connection()->transport_version() <= QUIC_VERSION_42) {
     return 0;
   }
-  spdy::SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
-
-  spdy::SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
+  SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
+  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
   headers_stream_->WriteOrBufferData(
       QuicStringPiece(frame.data(), frame.size()), false, nullptr);
   return frame.size();
@@ -441,29 +458,29 @@
 
 size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
                                          QuicStreamId promised_stream_id,
-                                         spdy::SpdyHeaderBlock headers) {
+                                         SpdyHeaderBlock headers) {
   if (perspective() == Perspective::IS_CLIENT) {
     QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
     return 0;
   }
 
-  spdy::SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
-                                       std::move(headers));
+  SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
+                                 std::move(headers));
   // PUSH_PROMISE must not be the last frame sent out, at least followed by
   // response headers.
   push_promise.set_fin(false);
 
-  spdy::SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
   headers_stream_->WriteOrBufferData(
       QuicStringPiece(frame.data(), frame.size()), false, nullptr);
   return frame.size();
 }
 
 size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) {
-  spdy::SpdySettingsIR settings_frame;
-  settings_frame.AddSetting(spdy::SETTINGS_MAX_HEADER_LIST_SIZE, value);
+  SpdySettingsIR settings_frame;
+  settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
 
-  spdy::SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
+  SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
   headers_stream_->WriteOrBufferData(
       QuicStringPiece(frame.data(), frame.size()), false, nullptr);
   return frame.size();
@@ -476,8 +493,7 @@
 
 void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
   QuicSession::OnCryptoHandshakeEvent(event);
-  if (GetQuicReloadableFlag(quic_send_max_header_list_size) &&
-      event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
+  if (event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
     SendMaxHeaderListSize(max_inbound_header_list_size_);
   }
 }
@@ -497,9 +513,9 @@
   return false;
 }
 
-void QuicSpdySession::OnHeaders(spdy::SpdyStreamId stream_id,
+void QuicSpdySession::OnHeaders(SpdyStreamId stream_id,
                                 bool has_priority,
-                                spdy::SpdyPriority priority,
+                                SpdyPriority priority,
                                 bool fin) {
   if (has_priority) {
     if (perspective() == Perspective::IS_CLIENT) {
@@ -521,8 +537,8 @@
   fin_ = fin;
 }
 
-void QuicSpdySession::OnPushPromise(spdy::SpdyStreamId stream_id,
-                                    spdy::SpdyStreamId promised_stream_id,
+void QuicSpdySession::OnPushPromise(SpdyStreamId stream_id,
+                                    SpdyStreamId promised_stream_id,
                                     bool end) {
   DCHECK_EQ(kInvalidStreamId, stream_id_);
   DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
@@ -530,10 +546,10 @@
   promised_stream_id_ = promised_stream_id;
 }
 
-// TODO (wangyix): Why is spdy::SpdyStreamId used instead of QuicStreamId?
+// TODO (wangyix): Why is SpdyStreamId used instead of QuicStreamId?
 // This occurs in many places in this file.
-void QuicSpdySession::OnPriority(spdy::SpdyStreamId stream_id,
-                                 spdy::SpdyPriority priority) {
+void QuicSpdySession::OnPriority(SpdyStreamId stream_id,
+                                 SpdyPriority priority) {
   if (perspective() == Perspective::IS_CLIENT) {
     CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
                                "Server must not send PRIORITY frames.");
@@ -563,7 +579,6 @@
   frame_len_ += frame_len;
 }
 
-
 void QuicSpdySession::SetHpackEncoderDebugVisitor(
     std::unique_ptr<QuicHpackDebugVisitor> visitor) {
   spdy_framer_.SetEncoderHeaderTableDebugVisitor(
diff --git a/net/third_party/quic/core/quic_spdy_session.h b/net/third_party/quic/core/quic_spdy_session.h
index ec29258..74ed443 100644
--- a/net/third_party/quic/core/quic_spdy_session.h
+++ b/net/third_party/quic/core/quic_spdy_session.h
@@ -111,7 +111,7 @@
                                   QuicStreamId promised_stream_id,
                                   spdy::SpdyHeaderBlock headers);
 
-  // Sends spdy::SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
+  // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
   size_t SendMaxHeaderListSize(size_t value);
 
   QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
@@ -119,7 +119,7 @@
   bool server_push_enabled() const { return server_push_enabled_; }
 
   // Called by |QuicHeadersStream::UpdateEnableServerPush()| with
-  // value from spdy::SETTINGS_ENABLE_PUSH.
+  // value from SETTINGS_ENABLE_PUSH.
   void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; }
 
   // Return true if this session wants to release headers stream's buffer
@@ -139,6 +139,7 @@
   // QuicSpdyStreams.
   QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override = 0;
   QuicSpdyStream* CreateOutgoingDynamicStream() override = 0;
+
   QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
 
   // If an incoming stream can be created, return true.
@@ -173,7 +174,7 @@
   // willing to use to encode header blocks.
   void UpdateHeaderEncoderTableSize(uint32_t value);
 
-  // Called when spdy::SETTINGS_ENABLE_PUSH is received, only supported on
+  // Called when SETTINGS_ENABLE_PUSH is received, only supported on
   // server side.
   void UpdateEnableServerPush(bool value);
 
diff --git a/net/third_party/quic/core/quic_spdy_session_test.cc b/net/third_party/quic/core/quic_spdy_session_test.cc
index 6396669c3..8696d8f 100644
--- a/net/third_party/quic/core/quic_spdy_session_test.cc
+++ b/net/third_party/quic/core/quic_spdy_session_test.cc
@@ -8,10 +8,6 @@
 #include <set>
 #include <utility>
 
-#include "base/callback.h"
-#include "base/rand_util.h"
-#include "build/build_config.h"
-#include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/crypto/null_encrypter.h"
 #include "net/third_party/quic/core/quic_crypto_stream.h"
@@ -36,8 +32,14 @@
 #include "net/third_party/quic/test_tools/quic_stream_send_buffer_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
 #include "net/third_party/spdy/core/spdy_framer.h"
-#include "testing/gmock_mutant.h"
 
+using spdy::kV3HighestPriority;
+using spdy::Spdy3PriorityToHttp2Weight;
+using spdy::SpdyFramer;
+using spdy::SpdyHeaderBlock;
+using spdy::SpdyPriority;
+using spdy::SpdyPriorityIR;
+using spdy::SpdySerializedFrame;
 using testing::_;
 using testing::AtLeast;
 using testing::InSequence;
@@ -327,7 +329,7 @@
   StrictMock<MockQuicConnection>* connection_;
   TestSession session_;
   std::set<QuicStreamId> closed_streams_;
-  spdy::SpdyHeaderBlock headers_;
+  SpdyHeaderBlock headers_;
 };
 
 class QuicSpdySessionTestServer : public QuicSpdySessionTestBase {
@@ -522,7 +524,7 @@
   // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
   // priority stream 6.  4 should be preempted.  6 will write but *not* block so
   // will cede back to 4.
-  stream6->SetPriority(spdy::kV3HighestPriority);
+  stream6->SetPriority(kV3HighestPriority);
   EXPECT_CALL(*stream4, OnCanWrite())
       .WillOnce(Invoke([this, stream4, stream6]() {
         session_.SendLargeFakeData(stream4, 6000);
@@ -554,10 +556,8 @@
   CryptoHandshakeMessage msg;
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
       QuicConnectionPeer::GetWriter(session_.connection()));
-  if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
-    EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
-        .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
-  }
+  EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+      .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
   session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
 
   // Drive congestion control manually.
@@ -1014,12 +1014,13 @@
   // Write until the header stream is flow control blocked.
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
-  spdy::SpdyHeaderBlock headers;
+  SpdyHeaderBlock headers;
+  SimpleRandom random;
   while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
     EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
     EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
-    headers["header"] = QuicStrCat("", base::RandUint64(), base::RandUint64(),
-                                   base::RandUint64());
+    headers["header"] = QuicStrCat("", random.RandUint64(), random.RandUint64(),
+                                   random.RandUint64());
     session_.WriteHeaders(stream_id, headers.Clone(), true, 0, nullptr);
     stream_id += 2;
   }
@@ -1407,22 +1408,20 @@
 
   const QuicStreamId id = 4;
   const QuicStreamId parent_stream_id = 9;
-  const spdy::SpdyPriority priority = spdy::kV3HighestPriority;
+  const SpdyPriority priority = kV3HighestPriority;
   const bool exclusive = true;
   session_.WritePriority(id, parent_stream_id,
-                         spdy::Spdy3PriorityToHttp2Weight(priority), exclusive);
+                         Spdy3PriorityToHttp2Weight(priority), exclusive);
 
   QuicStreamSendBuffer& send_buffer =
       QuicStreamPeer::SendBuffer(headers_stream);
   if (transport_version() > QUIC_VERSION_42) {
     ASSERT_EQ(1u, send_buffer.size());
 
-    spdy::SpdyPriorityIR priority_frame(
-        id, parent_stream_id, spdy::Spdy3PriorityToHttp2Weight(priority),
-        exclusive);
-    spdy::SpdyFramer spdy_framer(spdy::SpdyFramer::ENABLE_COMPRESSION);
-    spdy::SpdySerializedFrame frame =
-        spdy_framer.SerializeFrame(priority_frame);
+    SpdyPriorityIR priority_frame(
+        id, parent_stream_id, Spdy3PriorityToHttp2Weight(priority), exclusive);
+    SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
+    SpdySerializedFrame frame = spdy_framer.SerializeFrame(priority_frame);
 
     const QuicMemSlice& slice =
         QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
@@ -1589,8 +1588,8 @@
 TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
   QuicStreamId stream_id = GetNthClientInitiatedId(0);
   TestStream* stream = session_.CreateIncomingDynamicStream(stream_id);
-  session_.OnPriorityFrame(stream_id, spdy::kV3HighestPriority);
-  EXPECT_EQ(spdy::kV3HighestPriority, stream->priority());
+  session_.OnPriorityFrame(stream_id, kV3HighestPriority);
+  EXPECT_EQ(kV3HighestPriority, stream->priority());
 }
 
 }  // namespace
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.cc b/net/third_party/quic/core/quic_time_wait_list_manager.cc
index 2963f9e7..c751a2e 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.cc
@@ -75,13 +75,13 @@
 QuicTimeWaitListManager::QuicTimeWaitListManager(
     QuicPacketWriter* writer,
     Visitor* visitor,
-    QuicConnectionHelperInterface* helper,
+    const QuicClock* clock,
     QuicAlarmFactory* alarm_factory)
     : time_wait_period_(
           QuicTime::Delta::FromSeconds(FLAGS_quic_time_wait_list_seconds)),
       connection_id_clean_up_alarm_(
           alarm_factory->CreateAlarm(new ConnectionIdCleanUpAlarm(this))),
-      clock_(helper->GetClock()),
+      clock_(clock),
       writer_(writer),
       visitor_(visitor) {
   SetConnectionIdCleanUpAlarm();
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.h b/net/third_party/quic/core/quic_time_wait_list_manager.h
index 0d84c82..bae6a2c 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.h
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.h
@@ -14,7 +14,6 @@
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/quic_blocked_writer_interface.h"
-#include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_framer.h"
 #include "net/third_party/quic/core/quic_packet_writer.h"
 #include "net/third_party/quic/core/quic_packets.h"
@@ -59,13 +58,13 @@
         QuicConnectionId connection_id) = 0;
   };
 
-  // writer - the entity that writes to the socket. (Owned by the dispatcher)
-  // visitor - the entity that manages blocked writers. (The dispatcher)
-  // helper - provides a clock (Owned by the dispatcher)
-  // alarm_factory - used to run clean up alarms. (Owned by the dispatcher)
+  // writer - the entity that writes to the socket. (Owned by the caller)
+  // visitor - the entity that manages blocked writers. (Owned by the caller)
+  // clock - provide a clock (Owned by the caller)
+  // alarm_factory - used to run clean up alarms. (Owned by the caller)
   QuicTimeWaitListManager(QuicPacketWriter* writer,
                           Visitor* visitor,
-                          QuicConnectionHelperInterface* helper,
+                          const QuicClock* clock,
                           QuicAlarmFactory* alarm_factory);
   ~QuicTimeWaitListManager() override;
 
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
index fe4314d3..4901405 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
@@ -13,15 +13,12 @@
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
 #include "net/third_party/quic/core/quic_data_reader.h"
-#include "net/third_party/quic/core/quic_epoll_alarm_factory.h"
-#include "net/third_party/quic/core/quic_epoll_connection_helper.h"
 #include "net/third_party/quic/core/quic_framer.h"
 #include "net/third_party/quic/core/quic_packet_writer.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
-#include "net/third_party/quic/test_tools/mock_epoll_server.h"
 #include "net/third_party/quic/test_tools/mock_quic_session_visitor.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
 #include "net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.h"
@@ -74,19 +71,65 @@
   QuicConnectionId connection_id_;
 };
 
-class MockFakeTimeEpollServer : public FakeTimeEpollServer {
+class MockAlarmFactory;
+class MockAlarm : public QuicAlarm {
  public:
-  MOCK_METHOD2(RegisterAlarm,
-               void(int64_t timeout_in_us,
-                    net::EpollAlarmCallbackInterface* alarm));
+  explicit MockAlarm(QuicArenaScopedPtr<Delegate> delegate,
+                     int alarm_index,
+                     MockAlarmFactory* factory)
+      : QuicAlarm(std::move(delegate)),
+        alarm_index_(alarm_index),
+        factory_(factory) {}
+  virtual ~MockAlarm() {}
+
+  void SetImpl() override;
+  void CancelImpl() override;
+
+ private:
+  int alarm_index_;
+  MockAlarmFactory* factory_;
 };
 
+class MockAlarmFactory : public QuicAlarmFactory {
+ public:
+  ~MockAlarmFactory() override {}
+
+  // Creates a new platform-specific alarm which will be configured to notify
+  // |delegate| when the alarm fires. Returns an alarm allocated on the heap.
+  // Caller takes ownership of the new alarm, which will not yet be "set" to
+  // fire.
+  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
+    return new MockAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate),
+                         alarm_index_++, this);
+  }
+  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
+      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
+      QuicConnectionArena* arena) override {
+    if (arena != nullptr) {
+      return arena->New<MockAlarm>(std::move(delegate), alarm_index_++, this);
+    }
+    return QuicArenaScopedPtr<MockAlarm>(
+        new MockAlarm(std::move(delegate), alarm_index_++, this));
+  }
+  MOCK_METHOD2(OnAlarmSet, void(int, QuicTime));
+  MOCK_METHOD1(OnAlarmCancelled, void(int));
+
+ private:
+  int alarm_index_ = 0;
+};
+
+void MockAlarm::SetImpl() {
+  factory_->OnAlarmSet(alarm_index_, deadline());
+}
+
+void MockAlarm::CancelImpl() {
+  factory_->OnAlarmCancelled(alarm_index_);
+}
+
 class QuicTimeWaitListManagerTest : public QuicTest {
  protected:
   QuicTimeWaitListManagerTest()
-      : helper_(&epoll_server_, QuicAllocator::BUFFER_POOL),
-        alarm_factory_(&epoll_server_),
-        time_wait_list_manager_(&writer_, &visitor_, &helper_, &alarm_factory_),
+      : time_wait_list_manager_(&writer_, &visitor_, &clock_, &alarm_factory_),
         connection_id_(45),
         client_address_(TestPeerIPAddress(), kTestPort),
         writer_is_blocked_(false) {}
@@ -142,9 +185,8 @@
                                                 false, packet_number, "data");
   }
 
-  NiceMock<MockFakeTimeEpollServer> epoll_server_;
-  QuicEpollConnectionHelper helper_;
-  QuicEpollAlarmFactory alarm_factory_;
+  MockClock clock_;
+  MockAlarmFactory alarm_factory_;
   StrictMock<MockPacketWriter> writer_;
   StrictMock<MockQuicSessionVisitor> visitor_;
   QuicTimeWaitListManager time_wait_list_manager_;
@@ -304,7 +346,6 @@
   const size_t kOldConnectionIdCount = 31;
 
   // Add connection_ids such that their expiry time is time_wait_period_.
-  epoll_server_.set_now_in_usec(0);
   for (size_t connection_id = 1; connection_id <= kOldConnectionIdCount;
        ++connection_id) {
     EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
@@ -316,7 +357,7 @@
   // 2 * time_wait_period_.
   const QuicTime::Delta time_wait_period =
       QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
-  epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds());
+  clock_.AdvanceTime(time_wait_period);
   for (size_t connection_id = kOldConnectionIdCount + 1;
        connection_id <= kConnectionIdCount; ++connection_id) {
     EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
@@ -326,12 +367,11 @@
 
   QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
   // Now set the current time as time_wait_period + offset usecs.
-  epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds());
+  clock_.AdvanceTime(offset);
   // After all the old connection_ids are cleaned up, check the next alarm
   // interval.
-  int64_t next_alarm_time = epoll_server_.ApproximateNowInUsec() +
-                            (time_wait_period - offset).ToMicroseconds();
-  EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _));
+  QuicTime next_alarm_time = clock_.Now() + time_wait_period - offset;
+  EXPECT_CALL(alarm_factory_, OnAlarmSet(_, next_alarm_time));
 
   time_wait_list_manager_.CleanUpOldConnectionIds();
   for (size_t connection_id = 1; connection_id <= kConnectionIdCount;
@@ -399,7 +439,6 @@
 
 TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) {
   // Add connection_ids such that their expiry time is time_wait_period_.
-  epoll_server_.set_now_in_usec(0);
   EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_));
   AddConnectionId(connection_id_, QuicTimeWaitListManager::DO_NOTHING);
   EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_));
@@ -424,13 +463,11 @@
       QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
 
   QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39);
+  clock_.AdvanceTime(offset + time_wait_period);
   // Now set the current time as time_wait_period + offset usecs.
-  epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds());
-  // After the connection_ids are cleaned up, check the next alarm interval.
-  int64_t next_alarm_time =
-      epoll_server_.ApproximateNowInUsec() + time_wait_period.ToMicroseconds();
+  QuicTime next_alarm_time = clock_.Now() + time_wait_period;
+  EXPECT_CALL(alarm_factory_, OnAlarmSet(_, next_alarm_time));
 
-  EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _));
   time_wait_list_manager_.CleanUpOldConnectionIds();
   EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_));
   EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
@@ -445,19 +482,18 @@
 
   // 1 will hash lower than 2, but we add it later. They should come out in the
   // add order, not hash order.
-  epoll_server_.set_now_in_usec(0);
   EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id1));
   AddConnectionId(connection_id1, QuicTimeWaitListManager::DO_NOTHING);
-  epoll_server_.set_now_in_usec(10);
+  clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(10));
   EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id2));
   AddConnectionId(connection_id2, QuicTimeWaitListManager::DO_NOTHING);
   EXPECT_EQ(2u, time_wait_list_manager_.num_connections());
 
   const QuicTime::Delta time_wait_period =
       QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
-  epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds() + 1);
+  clock_.AdvanceTime(time_wait_period - QuicTime::Delta::FromMicroseconds(9));
 
-  EXPECT_CALL(epoll_server_, RegisterAlarm(_, _));
+  EXPECT_CALL(alarm_factory_, OnAlarmSet(_, _));
 
   time_wait_list_manager_.CleanUpOldConnectionIds();
   EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id1));
diff --git a/net/third_party/quic/core/quic_trace_visitor.h b/net/third_party/quic/core/quic_trace_visitor.h
index 876776d9..279c8d9f 100644
--- a/net/third_party/quic/core/quic_trace_visitor.h
+++ b/net/third_party/quic/core/quic_trace_visitor.h
@@ -5,9 +5,9 @@
 #ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_TRACE_VISITOR_H_
 #define NET_THIRD_PARTY_QUIC_CORE_QUIC_TRACE_VISITOR_H_
 
-#include "net/third_party/quic/core/proto/quic_trace.pb.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_types.h"
+#include "third_party/quic_trace/lib/quic_trace.pb.h"
 
 namespace quic {
 
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.cc b/net/third_party/quic/core/quic_unacked_packet_map.cc
index 4e034c90..a707bcf7 100644
--- a/net/third_party/quic/core/quic_unacked_packet_map.cc
+++ b/net/third_party/quic/core/quic_unacked_packet_map.cc
@@ -13,7 +13,8 @@
 QuicUnackedPacketMap::QuicUnackedPacketMap()
     : largest_sent_packet_(0),
       largest_sent_retransmittable_packet_(0),
-      largest_observed_(0),
+      largest_sent_largest_acked_(0),
+      largest_acked_(0),
       least_unacked_(1),
       bytes_in_flight_(0),
       pending_crypto_packet_count_(0),
@@ -47,6 +48,8 @@
       packet->encryption_level, packet->packet_number_length, transmission_type,
       sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
   info.largest_acked = packet->largest_acked;
+  largest_sent_largest_acked_ =
+      std::max(largest_sent_largest_acked_, packet->largest_acked);
   if (old_packet_number > 0) {
     TransferRetransmissionInfo(old_packet_number, packet_number,
                                transmission_type, &info);
@@ -193,10 +196,10 @@
   RemoveRetransmittability(info);
 }
 
-void QuicUnackedPacketMap::IncreaseLargestObserved(
-    QuicPacketNumber largest_observed) {
-  DCHECK_LE(largest_observed_, largest_observed);
-  largest_observed_ = largest_observed;
+void QuicUnackedPacketMap::IncreaseLargestAcked(
+    QuicPacketNumber largest_acked) {
+  DCHECK_LE(largest_acked_, largest_acked);
+  largest_acked_ = largest_acked;
 }
 
 bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
@@ -204,7 +207,7 @@
     const QuicTransmissionInfo& info) const {
   // Packet can be used for RTT measurement if it may yet be acked as the
   // largest observed packet by the receiver.
-  return QuicUtils::IsAckable(info.state) && packet_number > largest_observed_;
+  return QuicUtils::IsAckable(info.state) && packet_number > largest_acked_;
 }
 
 bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
@@ -219,7 +222,7 @@
   // retransmitted with a new packet number.
   return HasRetransmittableFrames(info) ||
          // Allow for an extra 1 RTT before stopping to track old packets.
-         info.retransmission > largest_observed_;
+         info.retransmission > largest_acked_;
 }
 
 bool QuicUnackedPacketMap::IsPacketUseless(
@@ -345,6 +348,7 @@
 }
 
 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
+  DCHECK(!GetQuicReloadableFlag(quic_optimize_inflight_check));
   for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
        it != unacked_packets_.rend(); ++it) {
     if (it->in_flight && HasRetransmittableFrames(*it)) {
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.h b/net/third_party/quic/core/quic_unacked_packet_map.h
index ce8bec5..4587ccc 100644
--- a/net/third_party/quic/core/quic_unacked_packet_map.h
+++ b/net/third_party/quic/core/quic_unacked_packet_map.h
@@ -99,8 +99,12 @@
     return largest_sent_retransmittable_packet_;
   }
 
+  QuicPacketNumber largest_sent_largest_acked() const {
+    return largest_sent_largest_acked_;
+  }
+
   // Returns the largest packet number that has been acked.
-  QuicPacketNumber largest_observed() const { return largest_observed_; }
+  QuicPacketNumber largest_acked() const { return largest_acked_; }
 
   // Returns the sum of bytes from all packets in flight.
   QuicByteCount bytes_in_flight() const { return bytes_in_flight_; }
@@ -160,9 +164,9 @@
   // RemoveRetransmittability.
   void RemoveRetransmittability(QuicPacketNumber packet_number);
 
-  // Increases the largest observed.  Any packets less or equal to
-  // |largest_acked_packet| are discarded if they are only for the RTT purposes.
-  void IncreaseLargestObserved(QuicPacketNumber largest_observed);
+  // Increases the largest acked.  Any packets less or equal to
+  // |largest_acked| are discarded if they are only for the RTT purposes.
+  void IncreaseLargestAcked(QuicPacketNumber largest_acked);
 
   // Remove any packets no longer needed for retransmission, congestion, or
   // RTT measurement purposes.
@@ -207,7 +211,10 @@
   QuicPacketNumber largest_sent_packet_;
   // The largest sent packet we expect to receive an ack for.
   QuicPacketNumber largest_sent_retransmittable_packet_;
-  QuicPacketNumber largest_observed_;
+  // The largest sent largest_acked in an ACK frame.
+  QuicPacketNumber largest_sent_largest_acked_;
+  // The largest received largest_acked from an ACK frame.
+  QuicPacketNumber largest_acked_;
 
   // Newly serialized retransmittable packets are added to this map, which
   // contains owning pointers to any contained frames.  If a packet is
diff --git a/net/third_party/quic/core/quic_unacked_packet_map_test.cc b/net/third_party/quic/core/quic_unacked_packet_map_test.cc
index 76961a0..296d313 100644
--- a/net/third_party/quic/core/quic_unacked_packet_map_test.cc
+++ b/net/third_party/quic/core/quic_unacked_packet_map_test.cc
@@ -87,7 +87,9 @@
     unacked_packets_.RemoveObsoletePackets();
     if (num_packets == 0) {
       EXPECT_FALSE(unacked_packets_.HasUnackedPackets());
-      EXPECT_FALSE(unacked_packets_.HasUnackedRetransmittableFrames());
+      if (!GetQuicReloadableFlag(quic_optimize_inflight_check)) {
+        EXPECT_FALSE(unacked_packets_.HasUnackedRetransmittableFrames());
+      }
       return;
     }
     EXPECT_TRUE(unacked_packets_.HasUnackedPackets());
@@ -163,7 +165,7 @@
   VerifyInFlightPackets(nullptr, 0);
   VerifyRetransmittablePackets(nullptr, 0);
 
-  unacked_packets_.IncreaseLargestObserved(1);
+  unacked_packets_.IncreaseLargestAcked(1);
   VerifyUnackedPackets(nullptr, 0);
   VerifyInFlightPackets(nullptr, 0);
   VerifyRetransmittablePackets(nullptr, 0);
@@ -184,7 +186,7 @@
   VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyRetransmittablePackets(nullptr, 0);
 
-  unacked_packets_.IncreaseLargestObserved(1);
+  unacked_packets_.IncreaseLargestAcked(1);
   VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyRetransmittablePackets(nullptr, 0);
@@ -290,7 +292,7 @@
   VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyRetransmittablePackets(nullptr, 0);
 
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
   VerifyRetransmittablePackets(nullptr, 0);
@@ -322,7 +324,7 @@
                                QUIC_ARRAYSIZE(retransmittable));
 
   // Early retransmit 1 as 3 and send new data as 4.
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   unacked_packets_.RemoveFromInFlight(2);
   unacked_packets_.RemoveRetransmittability(2);
   unacked_packets_.RemoveFromInFlight(1);
@@ -343,7 +345,7 @@
   VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
 
   // Early retransmit 3 (formerly 1) as 5, and remove 1 from unacked.
-  unacked_packets_.IncreaseLargestObserved(4);
+  unacked_packets_.IncreaseLargestAcked(4);
   unacked_packets_.RemoveFromInFlight(4);
   unacked_packets_.RemoveRetransmittability(4);
   RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
@@ -365,7 +367,7 @@
   VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
 
   // Early retransmit 5 as 7 and ensure in flight packet 3 is not removed.
-  unacked_packets_.IncreaseLargestObserved(6);
+  unacked_packets_.IncreaseLargestAcked(6);
   unacked_packets_.RemoveFromInFlight(6);
   unacked_packets_.RemoveRetransmittability(6);
   RetransmitAndSendPacket(5, 7, LOSS_RETRANSMISSION);
@@ -406,7 +408,7 @@
                                QUIC_ARRAYSIZE(retransmittable));
 
   // Early retransmit 1 as 3.
-  unacked_packets_.IncreaseLargestObserved(2);
+  unacked_packets_.IncreaseLargestAcked(2);
   unacked_packets_.RemoveFromInFlight(2);
   unacked_packets_.RemoveRetransmittability(2);
   unacked_packets_.RemoveFromInFlight(1);
@@ -442,7 +444,7 @@
   VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
 
   // Early retransmit 4 as 6 and ensure in flight packet 3 is removed.
-  unacked_packets_.IncreaseLargestObserved(5);
+  unacked_packets_.IncreaseLargestAcked(5);
   unacked_packets_.RemoveFromInFlight(5);
   unacked_packets_.RemoveRetransmittability(5);
   unacked_packets_.RemoveFromInFlight(3);
diff --git a/net/third_party/quic/core/quic_version_manager.cc b/net/third_party/quic/core/quic_version_manager.cc
index 0a71f0e..07ab540 100644
--- a/net/third_party/quic/core/quic_version_manager.cc
+++ b/net/third_party/quic/core/quic_version_manager.cc
@@ -17,9 +17,8 @@
     : enable_version_99_(GetQuicFlag(FLAGS_quic_enable_version_99)),
       enable_version_44_(GetQuicReloadableFlag(quic_enable_version_44)),
       enable_version_43_(GetQuicReloadableFlag(quic_enable_version_43)),
-      disable_version_41_(GetQuicReloadableFlag(quic_disable_version_41)),
-      disable_version_38_(GetQuicReloadableFlag(quic_disable_version_38)),
-      disable_version_37_(GetQuicReloadableFlag(quic_disable_version_37)),
+      disable_version_42_(GetQuicReloadableFlag(quic_disable_version_42)),
+      disable_version_41_(GetQuicReloadableFlag(quic_disable_version_41_2)),
       allowed_supported_versions_(std::move(supported_versions)) {
   RefilterSupportedVersions();
 }
@@ -41,15 +40,13 @@
   if (enable_version_99_ != GetQuicFlag(FLAGS_quic_enable_version_99) ||
       enable_version_44_ != GetQuicReloadableFlag(quic_enable_version_44) ||
       enable_version_43_ != GetQuicReloadableFlag(quic_enable_version_43) ||
-      disable_version_41_ != GetQuicReloadableFlag(quic_disable_version_41) ||
-      disable_version_38_ != GetQuicReloadableFlag(quic_disable_version_38) ||
-      disable_version_37_ != GetQuicReloadableFlag(quic_disable_version_37)) {
+      disable_version_42_ != GetQuicReloadableFlag(quic_disable_version_42) ||
+      disable_version_41_ != GetQuicReloadableFlag(quic_disable_version_41_2)) {
     enable_version_99_ = GetQuicFlag(FLAGS_quic_enable_version_99);
     enable_version_44_ = GetQuicReloadableFlag(quic_enable_version_44);
     enable_version_43_ = GetQuicReloadableFlag(quic_enable_version_43);
-    disable_version_37_ = GetQuicReloadableFlag(quic_disable_version_37);
-    disable_version_38_ = GetQuicReloadableFlag(quic_disable_version_38);
-    disable_version_41_ = GetQuicReloadableFlag(quic_disable_version_41);
+    disable_version_42_ = GetQuicReloadableFlag(quic_disable_version_42);
+    disable_version_41_ = GetQuicReloadableFlag(quic_disable_version_41_2);
     RefilterSupportedVersions();
   }
 }
diff --git a/net/third_party/quic/core/quic_version_manager.h b/net/third_party/quic/core/quic_version_manager.h
index cbf6bf6..839e813 100644
--- a/net/third_party/quic/core/quic_version_manager.h
+++ b/net/third_party/quic/core/quic_version_manager.h
@@ -41,12 +41,10 @@
   bool enable_version_44_;
   // FLAGS_quic_reloadable_flag_quic_disable_version_43
   bool enable_version_43_;
+  // FLAGS_quic_reloadable_flag_quic_disable_version_42
+  bool disable_version_42_;
   // FLAGS_quic_reloadable_flag_quic_disable_version_41
   bool disable_version_41_;
-  // FLAGS_quic_reloadable_flag_quic_disable_version_38
-  bool disable_version_38_;
-  // FLAGS_quic_reloadable_flag_quic_disable_version_37
-  bool disable_version_37_;
   // The list of versions that may be supported.
   ParsedQuicVersionVector allowed_supported_versions_;
   // This vector contains QUIC versions which are currently supported based on
diff --git a/net/third_party/quic/core/quic_version_manager_test.cc b/net/third_party/quic/core/quic_version_manager_test.cc
index ea9261b..beb6fcc6 100644
--- a/net/third_party/quic/core/quic_version_manager_test.cc
+++ b/net/third_party/quic/core/quic_version_manager_test.cc
@@ -16,60 +16,49 @@
 class QuicVersionManagerTest : public QuicTest {};
 
 TEST_F(QuicVersionManagerTest, QuicVersionManager) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 9u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   SetQuicFlag(&FLAGS_quic_enable_version_99, false);
   SetQuicReloadableFlag(quic_enable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_43, false);
-  SetQuicReloadableFlag(quic_disable_version_41, true);
-  SetQuicReloadableFlag(quic_disable_version_38, true);
-  SetQuicReloadableFlag(quic_disable_version_37, true);
+  SetQuicReloadableFlag(quic_disable_version_42, true);
+  SetQuicReloadableFlag(quic_disable_version_41_2, true);
   QuicVersionManager manager(AllSupportedVersions());
 
   EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
             manager.GetSupportedTransportVersions());
 
+  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_39, QUIC_VERSION_35}),
+            manager.GetSupportedTransportVersions());
+
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
   EXPECT_EQ(QuicTransportVersionVector(
-                {QUIC_VERSION_42, QUIC_VERSION_39, QUIC_VERSION_35}),
+                {QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35}),
             manager.GetSupportedTransportVersions());
 
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_42, QUIC_VERSION_39,
-                                        QUIC_VERSION_37, QUIC_VERSION_35}),
-            manager.GetSupportedTransportVersions());
-
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_42, QUIC_VERSION_39,
-                                        QUIC_VERSION_38, QUIC_VERSION_37,
-                                        QUIC_VERSION_35}),
-            manager.GetSupportedTransportVersions());
-
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_42, false);
   EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_42, QUIC_VERSION_41,
-                                        QUIC_VERSION_39, QUIC_VERSION_38,
-                                        QUIC_VERSION_37, QUIC_VERSION_35}),
+                                        QUIC_VERSION_39, QUIC_VERSION_35}),
             manager.GetSupportedTransportVersions());
 
   SetQuicReloadableFlag(quic_enable_version_43, true);
-  EXPECT_EQ(
-      QuicTransportVersionVector(
-          {QUIC_VERSION_43, QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-           QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35}),
-      manager.GetSupportedTransportVersions());
+  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_43, QUIC_VERSION_42,
+                                        QUIC_VERSION_41, QUIC_VERSION_39,
+                                        QUIC_VERSION_35}),
+            manager.GetSupportedTransportVersions());
 
   SetQuicReloadableFlag(quic_enable_version_44, true);
-  EXPECT_EQ(
-      QuicTransportVersionVector(
-          {QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42, QUIC_VERSION_41,
-           QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35}),
-      manager.GetSupportedTransportVersions());
+  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_44, QUIC_VERSION_43,
+                                        QUIC_VERSION_42, QUIC_VERSION_41,
+                                        QUIC_VERSION_39, QUIC_VERSION_35}),
+            manager.GetSupportedTransportVersions());
 
   SetQuicFlag(&FLAGS_quic_enable_version_99, true);
-  EXPECT_EQ(QuicTransportVersionVector(
-                {QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43,
-                 QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-                 QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35}),
-            manager.GetSupportedTransportVersions());
+  EXPECT_EQ(
+      QuicTransportVersionVector(
+          {QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42,
+           QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35}),
+      manager.GetSupportedTransportVersions());
 
   // Ensure that all versions are now supported.
   EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
diff --git a/net/third_party/quic/core/quic_versions.cc b/net/third_party/quic/core/quic_versions.cc
index e6540f4..60bb2ed 100644
--- a/net/third_party/quic/core/quic_versions.cc
+++ b/net/third_party/quic/core/quic_versions.cc
@@ -56,10 +56,6 @@
   switch (parsed_version.transport_version) {
     case QUIC_VERSION_35:
       return MakeVersionLabel(proto, '0', '3', '5');
-    case QUIC_VERSION_37:
-      return MakeVersionLabel(proto, '0', '3', '7');
-    case QUIC_VERSION_38:
-      return MakeVersionLabel(proto, '0', '3', '8');
     case QUIC_VERSION_39:
       return MakeVersionLabel(proto, '0', '3', '9');
     case QUIC_VERSION_41:
@@ -176,16 +172,12 @@
       if (GetQuicReloadableFlag(quic_enable_version_43)) {
         filtered_versions.push_back(version);
       }
+    } else if (version.transport_version == QUIC_VERSION_42) {
+      if (!GetQuicReloadableFlag(quic_disable_version_42)) {
+        filtered_versions.push_back(version);
+      }
     } else if (version.transport_version == QUIC_VERSION_41) {
-      if (!GetQuicReloadableFlag(quic_disable_version_41)) {
-        filtered_versions.push_back(version);
-      }
-    } else if (version.transport_version == QUIC_VERSION_38) {
-      if (!GetQuicReloadableFlag(quic_disable_version_38)) {
-        filtered_versions.push_back(version);
-      }
-    } else if (version.transport_version == QUIC_VERSION_37) {
-      if (!GetQuicReloadableFlag(quic_disable_version_37)) {
+      if (!GetQuicReloadableFlag(quic_disable_version_41_2)) {
         filtered_versions.push_back(version);
       }
     } else {
@@ -278,8 +270,6 @@
 QuicString QuicVersionToString(QuicTransportVersion transport_version) {
   switch (transport_version) {
     RETURN_STRING_LITERAL(QUIC_VERSION_35);
-    RETURN_STRING_LITERAL(QUIC_VERSION_37);
-    RETURN_STRING_LITERAL(QUIC_VERSION_38);
     RETURN_STRING_LITERAL(QUIC_VERSION_39);
     RETURN_STRING_LITERAL(QUIC_VERSION_41);
     RETURN_STRING_LITERAL(QUIC_VERSION_42);
diff --git a/net/third_party/quic/core/quic_versions.h b/net/third_party/quic/core/quic_versions.h
index 0da58b4b..dc3ff33 100644
--- a/net/third_party/quic/core/quic_versions.h
+++ b/net/third_party/quic/core/quic_versions.h
@@ -25,9 +25,6 @@
   QUIC_VERSION_UNSUPPORTED = 0,
 
   QUIC_VERSION_35 = 35,  // Allows endpoints to independently set stream limit.
-  QUIC_VERSION_37 = 37,  // Add perspective into null encryption.
-  QUIC_VERSION_38 = 38,  // PADDING frame is a 1-byte frame with type 0x00.
-                         // Respect NSTP connection option.
   QUIC_VERSION_39 = 39,  // Integers and floating numbers are written in big
                          // endian. Dot not ack acks. Send a connection level
                          // WINDOW_UPDATE every 20 sent packets which do not
@@ -101,9 +98,8 @@
 // IMPORTANT: if you are adding to this list, follow the instructions at
 // http://sites/quic/adding-and-removing-versions
 static const QuicTransportVersion kSupportedTransportVersions[] = {
-    QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43,
-    QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-    QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
+    QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42,
+    QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35};
 
 // This vector contains all crypto handshake protocols that are supported.
 static const HandshakeProtocol kSupportedHandshakeProtocols[] = {
diff --git a/net/third_party/quic/core/quic_versions_test.cc b/net/third_party/quic/core/quic_versions_test.cc
index 8e40ead..0f68492 100644
--- a/net/third_party/quic/core/quic_versions_test.cc
+++ b/net/third_party/quic/core/quic_versions_test.cc
@@ -132,10 +132,6 @@
 TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35),
             ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '5')));
-  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37),
-            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '7')));
-  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38),
-            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '8')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
             ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '9')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41),
@@ -151,10 +147,6 @@
   FLAGS_quic_supports_tls_handshake = true;
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_35),
             ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
-  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_37),
-            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '7')));
-  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_38),
-            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '8')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
             ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_41),
@@ -189,12 +181,6 @@
   EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '5'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35)));
-  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '7'),
-            CreateQuicVersionLabel(
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37)));
-  EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '8'),
-            CreateQuicVersionLabel(
-                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38)));
   EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '9'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39)));
@@ -216,12 +202,6 @@
   EXPECT_EQ(MakeVersionLabel('T', '0', '3', '5'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_35)));
-  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '7'),
-            CreateQuicVersionLabel(
-                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_37)));
-  EXPECT_EQ(MakeVersionLabel('T', '0', '3', '8'),
-            CreateQuicVersionLabel(
-                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_38)));
   EXPECT_EQ(MakeVersionLabel('T', '0', '3', '9'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39)));
@@ -338,9 +318,8 @@
 
 TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
   QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
+  SetQuicReloadableFlag(quic_disable_version_42, false);
   SetQuicReloadableFlag(quic_enable_version_43, true);
   SetQuicReloadableFlag(quic_enable_version_44, true);
   SetQuicFlag(&FLAGS_quic_enable_version_99, true);
@@ -349,9 +328,8 @@
     parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
   }
   QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43,
-      QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-      QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
+      QUIC_VERSION_99, QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42,
+      QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
     expected_parsed_versions.push_back(
@@ -364,9 +342,7 @@
 
 TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
   QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
   SetQuicReloadableFlag(quic_enable_version_43, true);
   SetQuicReloadableFlag(quic_enable_version_44, true);
   SetQuicFlag(&FLAGS_quic_enable_version_99, false);
@@ -375,8 +351,8 @@
     parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
   }
   QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42, QUIC_VERSION_41,
-      QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
+      QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_42,
+      QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
     expected_parsed_versions.push_back(
@@ -389,9 +365,7 @@
 
 TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo44) {
   QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
   SetQuicReloadableFlag(quic_enable_version_43, true);
   SetQuicReloadableFlag(quic_enable_version_44, false);
   SetQuicFlag(&FLAGS_quic_enable_version_99, false);
@@ -401,7 +375,7 @@
   }
   QuicTransportVersionVector expected_versions = {
       QUIC_VERSION_43, QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-      QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
+      QUIC_VERSION_35};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
     expected_parsed_versions.push_back(
@@ -412,11 +386,10 @@
   ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
 }
 
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo43) {
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo42) {
   QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
+  SetQuicReloadableFlag(quic_disable_version_41_2, false);
+  SetQuicReloadableFlag(quic_disable_version_42, true);
   SetQuicReloadableFlag(quic_enable_version_43, false);
   SetQuicReloadableFlag(quic_enable_version_44, false);
   SetQuicFlag(&FLAGS_quic_enable_version_99, false);
@@ -425,8 +398,7 @@
     parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
   }
   QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39,
-      QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_35};
+      QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_35};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
     expected_parsed_versions.push_back(
@@ -439,9 +411,8 @@
 
 TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo41) {
   QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, true);
-  SetQuicReloadableFlag(quic_disable_version_41, true);
+  SetQuicReloadableFlag(quic_disable_version_41_2, true);
+  SetQuicReloadableFlag(quic_disable_version_42, true);
   SetQuicReloadableFlag(quic_enable_version_43, false);
   SetQuicReloadableFlag(quic_enable_version_44, false);
   SetQuicFlag(&FLAGS_quic_enable_version_99, false);
@@ -449,58 +420,8 @@
   for (QuicTransportVersion version : all_versions) {
     parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
   }
-  QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_42, QUIC_VERSION_39, QUIC_VERSION_37, QUIC_VERSION_35};
-  ParsedQuicVersionVector expected_parsed_versions;
-  for (QuicTransportVersion version : expected_versions) {
-    expected_parsed_versions.push_back(
-        ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
-  }
-
-  ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
-  ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
-
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo38) {
-  QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, false);
-  SetQuicReloadableFlag(quic_disable_version_38, true);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
-  SetQuicReloadableFlag(quic_enable_version_43, false);
-  SetQuicReloadableFlag(quic_enable_version_44, false);
-  SetQuicFlag(&FLAGS_quic_enable_version_99, false);
-  ParsedQuicVersionVector parsed_versions;
-  for (QuicTransportVersion version : all_versions) {
-    parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
-  }
-  QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_37,
-      QUIC_VERSION_35};
-  ParsedQuicVersionVector expected_parsed_versions;
-  for (QuicTransportVersion version : expected_versions) {
-    expected_parsed_versions.push_back(
-        ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
-  }
-
-  ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
-  ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
-
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo37) {
-  QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
-  SetQuicReloadableFlag(quic_disable_version_37, true);
-  SetQuicReloadableFlag(quic_disable_version_38, false);
-  SetQuicReloadableFlag(quic_disable_version_41, false);
-  SetQuicReloadableFlag(quic_enable_version_43, false);
-  SetQuicReloadableFlag(quic_enable_version_44, false);
-  SetQuicFlag(&FLAGS_quic_enable_version_99, false);
-  ParsedQuicVersionVector parsed_versions;
-  for (QuicTransportVersion version : all_versions) {
-    parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
-  }
-  QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_42, QUIC_VERSION_41, QUIC_VERSION_39, QUIC_VERSION_38,
-      QUIC_VERSION_35};
+  QuicTransportVersionVector expected_versions = {QUIC_VERSION_39,
+                                                  QUIC_VERSION_35};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
     expected_parsed_versions.push_back(
@@ -512,8 +433,7 @@
 }
 
 TEST_F(QuicVersionsTest, LookUpVersionByIndex) {
-  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_37,
-                                             QUIC_VERSION_38, QUIC_VERSION_39};
+  QuicTransportVersionVector all_versions = {QUIC_VERSION_35, QUIC_VERSION_39};
   int version_count = all_versions.size();
   for (int i = -5; i <= version_count + 1; ++i) {
     if (i >= 0 && i < version_count) {
@@ -552,11 +472,9 @@
 // yet a typo was made in doing the #defines and it was caught
 // only in some test far removed from here... Better safe than sorry.
 TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 9u,
+  static_assert(QUIC_ARRAYSIZE(quic::kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   EXPECT_EQ(QUIC_VERSION_35, 35);
-  EXPECT_EQ(QUIC_VERSION_37, 37);
-  EXPECT_EQ(QUIC_VERSION_38, 38);
   EXPECT_EQ(QUIC_VERSION_39, 39);
   EXPECT_EQ(QUIC_VERSION_41, 41);
   EXPECT_EQ(QUIC_VERSION_42, 42);
diff --git a/net/third_party/quic/core/quic_write_blocked_list.cc b/net/third_party/quic/core/quic_write_blocked_list.cc
index f6b2e18..80a8512 100644
--- a/net/third_party/quic/core/quic_write_blocked_list.cc
+++ b/net/third_party/quic/core/quic_write_blocked_list.cc
@@ -9,7 +9,10 @@
 
 namespace quic {
 
-QuicWriteBlockedList::QuicWriteBlockedList() : last_priority_popped_(0) {
+QuicWriteBlockedList::QuicWriteBlockedList()
+    : last_priority_popped_(0),
+      use_static_stream_collection_(GetQuicReloadableFlag(
+          quic_use_static_stream_collection_in_write_blocked_list)) {
   memset(batch_write_stream_id_, 0, sizeof(batch_write_stream_id_));
   memset(bytes_left_for_batch_write_, 0, sizeof(bytes_left_for_batch_write_));
 }
diff --git a/net/third_party/quic/core/quic_write_blocked_list.h b/net/third_party/quic/core/quic_write_blocked_list.h
index 03262ad..793f8a1 100644
--- a/net/third_party/quic/core/quic_write_blocked_list.h
+++ b/net/third_party/quic/core/quic_write_blocked_list.h
@@ -32,6 +32,10 @@
   }
 
   bool HasWriteBlockedSpecialStream() const {
+    if (use_static_stream_collection_) {
+      return static_stream_collection_.num_blocked() > 0;
+    }
+
     for (const auto& stream : static_streams_) {
       if (stream.second) {
         return true;
@@ -41,6 +45,10 @@
   }
 
   size_t NumBlockedSpecialStreams() const {
+    if (use_static_stream_collection_) {
+      return static_stream_collection_.num_blocked();
+    }
+
     size_t num_blocked = 0;
     for (const auto& stream : static_streams_) {
       if (stream.second) {
@@ -56,14 +64,27 @@
   }
 
   bool ShouldYield(QuicStreamId id) const {
-    for (const auto& stream : static_streams_) {
-      if (stream.first == id) {
-        // Static streams should never yield to data streams, or to lower
-        // priority static stream.
-        return false;
+    if (use_static_stream_collection_) {
+      for (const auto& stream : static_stream_collection_) {
+        if (stream.id == id) {
+          // Static streams should never yield to data streams, or to lower
+          // priority static stream.
+          return false;
+        }
+        if (stream.is_blocked) {
+          return true;  // All data streams yield to static streams.
+        }
       }
-      if (stream.second) {
-        return true;  // All data streams yield to static streams.
+    } else {
+      for (const auto& stream : static_streams_) {
+        if (stream.first == id) {
+          // Static streams should never yield to data streams, or to lower
+          // priority static stream.
+          return false;
+        }
+        if (stream.second) {
+          return true;  // All data streams yield to static streams.
+        }
       }
     }
     return priority_write_scheduler_.ShouldYield(id);
@@ -72,10 +93,17 @@
   // Pops the highest priorty stream, special casing crypto and headers streams.
   // Latches the most recently popped data stream for batch writing purposes.
   QuicStreamId PopFront() {
-    for (auto& stream : static_streams_) {
-      if (stream.second) {
-        stream.second = false;
-        return stream.first;
+    if (use_static_stream_collection_) {
+      QuicStreamId static_stream_id;
+      if (static_stream_collection_.UnblockFirstBlocked(&static_stream_id)) {
+        return static_stream_id;
+      }
+    } else {
+      for (auto& stream : static_streams_) {
+        if (stream.second) {
+          stream.second = false;
+          return stream.first;
+        }
       }
     }
 
@@ -103,24 +131,39 @@
   void RegisterStream(QuicStreamId stream_id,
                       bool is_static_stream,
                       spdy::SpdyPriority priority) {
-    if (is_static_stream) {
+    if (use_static_stream_collection_) {
       DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
-      DCHECK(!QuicContainsKey(static_streams_, stream_id));
-      DCHECK(static_streams_.empty() ||
-             stream_id > static_streams_.back().first)
-          << "stream_id: " << stream_id
-          << " last static stream: " << static_streams_.back().first;
-      static_streams_[stream_id] = false;
-      return;
+      if (is_static_stream) {
+        static_stream_collection_.Register(stream_id);
+        return;
+      }
+
+      priority_write_scheduler_.RegisterStream(
+          stream_id, spdy::SpdyStreamPrecedence(priority));
+    } else {
+      if (is_static_stream) {
+        DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
+        DCHECK(!QuicContainsKey(static_streams_, stream_id));
+        DCHECK(static_streams_.empty() ||
+               stream_id > static_streams_.back().first)
+            << "stream_id: " << stream_id
+            << " last static stream: " << static_streams_.back().first;
+        static_streams_[stream_id] = false;
+        return;
+      }
+      DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
+      priority_write_scheduler_.RegisterStream(
+          stream_id, spdy::SpdyStreamPrecedence(priority));
     }
-    DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
-    priority_write_scheduler_.RegisterStream(
-        stream_id, spdy::SpdyStreamPrecedence(priority));
   }
 
   void UnregisterStream(QuicStreamId stream_id, bool is_static) {
     if (is_static) {
-      static_streams_.erase(stream_id);
+      if (use_static_stream_collection_) {
+        static_stream_collection_.Unregister(stream_id);
+      } else {
+        static_streams_.erase(stream_id);
+      }
       return;
     }
     priority_write_scheduler_.UnregisterStream(stream_id);
@@ -128,7 +171,10 @@
 
   void UpdateStreamPriority(QuicStreamId stream_id,
                             spdy::SpdyPriority new_priority) {
-    DCHECK(!QuicContainsKey(static_streams_, stream_id));
+    DCHECK(use_static_stream_collection_ ||
+           !QuicContainsKey(static_streams_, stream_id));
+    DCHECK(!use_static_stream_collection_ ||
+           !static_stream_collection_.IsRegistered(stream_id));
     priority_write_scheduler_.UpdateStreamPrecedence(
         stream_id, spdy::SpdyStreamPrecedence(new_priority));
   }
@@ -147,10 +193,16 @@
   // the list for its priority level.
   // Headers and crypto streams are special cased to always resume first.
   void AddStream(QuicStreamId stream_id) {
-    auto it = static_streams_.find(stream_id);
-    if (it != static_streams_.end()) {
-      it->second = true;
-      return;
+    if (use_static_stream_collection_) {
+      if (static_stream_collection_.SetBlocked(stream_id)) {
+        return;
+      }
+    } else {
+      auto it = static_streams_.find(stream_id);
+      if (it != static_streams_.end()) {
+        it->second = true;
+        return;
+      }
     }
     bool push_front =
         stream_id == batch_write_stream_id_[last_priority_popped_] &&
@@ -158,12 +210,19 @@
     priority_write_scheduler_.MarkStreamReady(stream_id, push_front);
   }
 
-  // This function is used for debugging and test only. Returns true if stream
-  // with |stream_id| is write blocked.
+  // Returns true if stream with |stream_id| is write blocked.
   bool IsStreamBlocked(QuicStreamId stream_id) const {
-    auto it = static_streams_.find(stream_id);
-    if (it != static_streams_.end()) {
-      return it->second;
+    if (use_static_stream_collection_) {
+      for (const auto& stream : static_stream_collection_) {
+        if (stream.id == stream_id) {
+          return stream.is_blocked;
+        }
+      }
+    } else {
+      auto it = static_streams_.find(stream_id);
+      if (it != static_streams_.end()) {
+        return it->second;
+      }
     }
 
     return priority_write_scheduler_.IsStreamReady(stream_id);
@@ -184,8 +243,104 @@
   // Tracks the last priority popped for UpdateBytesForStream.
   spdy::SpdyPriority last_priority_popped_;
 
+  // A StaticStreamCollection is a vector of <QuicStreamId, bool> pairs plus a
+  // eagerly-computed number of blocked static streams.
+  class StaticStreamCollection {
+   public:
+    struct StreamIdBlockedPair {
+      QuicStreamId id;
+      bool is_blocked;
+    };
+
+    std::vector<StreamIdBlockedPair>::const_iterator begin() const {
+      return streams_.cbegin();
+    }
+
+    std::vector<StreamIdBlockedPair>::const_iterator end() const {
+      return streams_.cend();
+    }
+
+    size_t num_blocked() const { return num_blocked_; }
+
+    // Add |id| to the collection in unblocked state.
+    void Register(QuicStreamId id) {
+      DCHECK(!IsRegistered(id));
+      DCHECK(streams_.empty() || id > streams_.back().id)
+          << "stream_id: " << id
+          << " last static stream: " << streams_.back().id;
+      streams_.push_back({id, false});
+    }
+
+    // True if |id| is in the collection, regardless of its state.
+    bool IsRegistered(QuicStreamId id) const {
+      for (const auto& stream : streams_) {
+        if (stream.id == id) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Remove |id| from the collection, if it is in the blocked state, reduce
+    // |num_blocked_| by 1.
+    void Unregister(QuicStreamId id) {
+      for (auto it = streams_.begin(); it != streams_.end(); ++it) {
+        if (it->id == id) {
+          if (it->is_blocked) {
+            --num_blocked_;
+          }
+          streams_.erase(it);
+          return;
+        }
+      }
+      DCHECK(false) << "Erasing a non-exist stream with id " << id;
+    }
+
+    // Set |id| to be blocked. If |id| is not already blocked, increase
+    // |num_blocked_| by 1.
+    // Return true if |id| is in the collection.
+    bool SetBlocked(QuicStreamId id) {
+      for (auto& stream : streams_) {
+        if (stream.id == id) {
+          if (!stream.is_blocked) {
+            stream.is_blocked = true;
+            ++num_blocked_;
+          }
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Unblock the first blocked stream in the collection.
+    // If no stream is blocked, return false. Otherwise return true, set *id to
+    // the unblocked stream id and reduce |num_blocked_| by 1.
+    bool UnblockFirstBlocked(QuicStreamId* id) {
+      for (auto& stream : streams_) {
+        if (stream.is_blocked) {
+          --num_blocked_;
+          stream.is_blocked = false;
+          *id = stream.id;
+          return true;
+        }
+      }
+      return false;
+    }
+
+   private:
+    size_t num_blocked_ = 0;
+    std::vector<StreamIdBlockedPair> streams_;
+  };
+
+  // Used iff use_static_stream_collection_ is true.
+  StaticStreamCollection static_stream_collection_;
+
+  // Used iff use_static_stream_collection_ is false.
   QuicLinkedHashMapImpl<QuicStreamId, bool> static_streams_;
 
+  // Latched value of quic_use_static_stream_collection_in_write_blocked_list.
+  const bool use_static_stream_collection_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicWriteBlockedList);
 };
 
diff --git a/net/third_party/quic/core/spdy_utils_test.cc b/net/third_party/quic/core/spdy_utils_test.cc
index 93640eb..4910e72 100644
--- a/net/third_party/quic/core/spdy_utils_test.cc
+++ b/net/third_party/quic/core/spdy_utils_test.cc
@@ -11,13 +11,13 @@
 #include "net/third_party/quic/platform/api/quic_test.h"
 #include "net/third_party/quic/platform/api/quic_text_utils.h"
 
-namespace quic {
-namespace test {
-
 using spdy::SpdyHeaderBlock;
 using testing::Pair;
 using testing::UnorderedElementsAre;
 
+namespace quic {
+namespace test {
+
 static std::unique_ptr<QuicHeaderList> FromList(
     const QuicHeaderList::ListType& src) {
   std::unique_ptr<QuicHeaderList> headers(new QuicHeaderList);
diff --git a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
index 22157e2..56eafde 100644
--- a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
+++ b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
@@ -13,9 +13,9 @@
 MockTimeWaitListManager::MockTimeWaitListManager(
     QuicPacketWriter* writer,
     Visitor* visitor,
-    QuicConnectionHelperInterface* helper,
+    const QuicClock* clock,
     QuicAlarmFactory* alarm_factory)
-    : QuicTimeWaitListManager(writer, visitor, helper, alarm_factory) {
+    : QuicTimeWaitListManager(writer, visitor, clock, alarm_factory) {
   // Though AddConnectionIdToTimeWait is mocked, we want to retain its
   // functionality.
   EXPECT_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _))
diff --git a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
index 13600e0..6dfe8d3 100644
--- a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -15,7 +15,7 @@
  public:
   MockTimeWaitListManager(QuicPacketWriter* writer,
                           Visitor* visitor,
-                          QuicConnectionHelperInterface* helper,
+                          const QuicClock* clock,
                           QuicAlarmFactory* alarm_factory);
   ~MockTimeWaitListManager() override;
 
diff --git a/net/third_party/quic/test_tools/mock_random.cc b/net/third_party/quic/test_tools/mock_random.cc
index baf29ee..3809dd8 100644
--- a/net/third_party/quic/test_tools/mock_random.cc
+++ b/net/third_party/quic/test_tools/mock_random.cc
@@ -21,8 +21,6 @@
   return base_ + increment_;
 }
 
-void MockRandom::Reseed(const void* additional_entropy, size_t entropy_len) {}
-
 void MockRandom::ChangeValue() {
   increment_++;
 }
diff --git a/net/third_party/quic/test_tools/mock_random.h b/net/third_party/quic/test_tools/mock_random.h
index 728249e6..090bab6 100644
--- a/net/third_party/quic/test_tools/mock_random.h
+++ b/net/third_party/quic/test_tools/mock_random.h
@@ -23,8 +23,6 @@
   void RandBytes(void* data, size_t len) override;
   // Returns base + the current increment.
   uint64_t RandUint64() override;
-  // Does nothing.
-  void Reseed(const void* additional_entropy, size_t entropy_len) override;
 
   // ChangeValue increments |increment_|. This causes the value returned by
   // |RandUint64| and the byte that |RandBytes| fills with, to change.
diff --git a/net/third_party/quic/test_tools/quic_test_utils.cc b/net/third_party/quic/test_tools/quic_test_utils.cc
index 407621b6..8608302 100644
--- a/net/third_party/quic/test_tools/quic_test_utils.cc
+++ b/net/third_party/quic/test_tools/quic_test_utils.cc
@@ -124,15 +124,6 @@
   }
 }
 
-void SimpleRandom::Reseed(const void* additional_entropy, size_t len) {
-  const uint8_t* real_entropy = static_cast<const uint8_t*>(additional_entropy);
-  for (size_t offset = 0; offset < len; offset++) {
-    // Note: this is not actually a well-established way to incorporate new
-    // entropy, but good enough for tests.
-    seed_ *= real_entropy[len];
-  }
-}
-
 MockFramerVisitor::MockFramerVisitor() {
   // By default, we want to accept packets.
   ON_CALL(*this, OnProtocolVersionMismatch(_))
@@ -149,8 +140,6 @@
 
   ON_CALL(*this, OnStreamFrame(_)).WillByDefault(testing::Return(true));
 
-  ON_CALL(*this, OnAckFrame(_)).WillByDefault(testing::Return(true));
-
   ON_CALL(*this, OnStopWaitingFrame(_)).WillByDefault(testing::Return(true));
 
   ON_CALL(*this, OnPaddingFrame(_)).WillByDefault(testing::Return(true));
@@ -201,10 +190,6 @@
   return true;
 }
 
-bool NoOpFramerVisitor::OnAckFrame(const QuicAckFrame& frame) {
-  return true;
-}
-
 bool NoOpFramerVisitor::OnAckFrameStart(QuicPacketNumber largest_acked,
                                         QuicTime::Delta ack_delay_time) {
   return true;
@@ -572,6 +557,11 @@
       &helper_);
 }
 
+void TestQuicSpdyServerSession::OnCryptoHandshakeEvent(
+    CryptoHandshakeEvent event) {
+  QuicSession::OnCryptoHandshakeEvent(event);
+}
+
 QuicCryptoServerStream* TestQuicSpdyServerSession::GetMutableCryptoStream() {
   return static_cast<QuicCryptoServerStream*>(
       QuicServerSessionBase::GetMutableCryptoStream());
@@ -601,6 +591,11 @@
   return true;
 }
 
+void TestQuicSpdyClientSession::OnCryptoHandshakeEvent(
+    CryptoHandshakeEvent event) {
+  QuicSession::OnCryptoHandshakeEvent(event);
+}
+
 QuicCryptoClientStream* TestQuicSpdyClientSession::GetMutableCryptoStream() {
   return crypto_stream_.get();
 }
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h
index 5e58ae1..6c14259 100644
--- a/net/third_party/quic/test_tools/quic_test_utils.h
+++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -231,7 +231,6 @@
   uint64_t RandUint64() override;
 
   void RandBytes(void* data, size_t len) override;
-  void Reseed(const void* additional_entropy, size_t len) override;
 
   void set_seed(uint64_t seed) { seed_ = seed; }
 
@@ -261,7 +260,6 @@
   MOCK_METHOD1(OnDecryptedPacket, void(EncryptionLevel level));
   MOCK_METHOD1(OnPacketHeader, bool(const QuicPacketHeader& header));
   MOCK_METHOD1(OnStreamFrame, bool(const QuicStreamFrame& frame));
-  MOCK_METHOD1(OnAckFrame, bool(const QuicAckFrame& frame));
   MOCK_METHOD2(OnAckFrameStart, bool(QuicPacketNumber, QuicTime::Delta));
   MOCK_METHOD3(OnAckRange, bool(QuicPacketNumber, QuicPacketNumber, bool));
   MOCK_METHOD1(OnStopWaitingFrame, bool(const QuicStopWaitingFrame& frame));
@@ -307,7 +305,6 @@
   void OnDecryptedPacket(EncryptionLevel level) override {}
   bool OnPacketHeader(const QuicPacketHeader& header) override;
   bool OnStreamFrame(const QuicStreamFrame& frame) override;
-  bool OnAckFrame(const QuicAckFrame& frame) override;
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override;
   bool OnAckRange(QuicPacketNumber start,
@@ -722,6 +719,9 @@
       const QuicCryptoServerConfig* crypto_config,
       QuicCompressedCertsCache* compressed_certs_cache) override;
 
+  // Override to not send max header list size.
+  void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+
   QuicCryptoServerStream* GetMutableCryptoStream() override;
 
   const QuicCryptoServerStream* GetCryptoStream() const override;
@@ -779,6 +779,8 @@
   MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
   MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
 
+  // Override to not send max header list size.
+  void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
   QuicCryptoClientStream* GetMutableCryptoStream() override;
   const QuicCryptoClientStream* GetCryptoStream() const override;
 
diff --git a/net/third_party/quic/test_tools/simple_quic_framer.cc b/net/third_party/quic/test_tools/simple_quic_framer.cc
index be8c955..06725384 100644
--- a/net/third_party/quic/test_tools/simple_quic_framer.cc
+++ b/net/third_party/quic/test_tools/simple_quic_framer.cc
@@ -63,11 +63,6 @@
     return true;
   }
 
-  bool OnAckFrame(const QuicAckFrame& frame) override {
-    ack_frames_.push_back(frame);
-    return true;
-  }
-
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta ack_delay_time) override {
     QuicAckFrame ack_frame;
diff --git a/net/third_party/quic/test_tools/simulator/quic_endpoint.cc b/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
index 1332c93..0525ffe 100644
--- a/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
+++ b/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
@@ -81,6 +81,7 @@
       bytes_transferred_(0),
       write_blocked_count_(0),
       wrong_data_received_(false),
+      drop_next_packet_(false),
       notifier_(nullptr) {
   nic_tx_queue_.set_listener_interface(this);
 
@@ -170,6 +171,10 @@
   WriteStreamData();
 }
 
+void QuicEndpoint::DropNextIncomingPacket() {
+  drop_next_packet_ = true;
+}
+
 void QuicEndpoint::RecordTrace() {
   trace_visitor_ = QuicMakeUnique<QuicTraceVisitor>(&connection_);
   connection_.set_debug_visitor(trace_visitor_.get());
@@ -179,6 +184,10 @@
   if (packet->destination != name_) {
     return;
   }
+  if (drop_next_packet_) {
+    drop_next_packet_ = false;
+    return;
+  }
 
   QuicReceivedPacket received_packet(packet->contents.data(),
                                      packet->contents.size(), clock_->Now());
diff --git a/net/third_party/quic/test_tools/simulator/quic_endpoint.h b/net/third_party/quic/test_tools/simulator/quic_endpoint.h
index 78a32d77..feb6e68 100644
--- a/net/third_party/quic/test_tools/simulator/quic_endpoint.h
+++ b/net/third_party/quic/test_tools/simulator/quic_endpoint.h
@@ -57,6 +57,9 @@
   // progress.
   void AddBytesToTransfer(QuicByteCount bytes);
 
+  // Drop the next packet upon receipt.
+  void DropNextIncomingPacket();
+
   // UnconstrainedPortInterface method.  Called whenever the endpoint receives a
   // packet.
   void AcceptPacket(std::unique_ptr<Packet> packet) override;
@@ -175,6 +178,9 @@
   // expects.
   bool wrong_data_received_;
 
+  // If true, drop the next packet when receiving it.
+  bool drop_next_packet_;
+
   // Record of received offsets in the data stream.
   QuicIntervalSet<QuicStreamOffset> offsets_received_;
 
diff --git a/net/third_party/quic/tools/quic_client_base.cc b/net/third_party/quic/tools/quic_client_base.cc
index 3f29e8e4..8166c4e 100644
--- a/net/third_party/quic/tools/quic_client_base.cc
+++ b/net/third_party/quic/tools/quic_client_base.cc
@@ -180,6 +180,12 @@
 }
 
 bool QuicClientBase::MigrateSocket(const QuicIpAddress& new_host) {
+  return MigrateSocketWithSpecifiedPort(new_host, local_port_);
+}
+
+bool QuicClientBase::MigrateSocketWithSpecifiedPort(
+    const QuicIpAddress& new_host,
+    int port) {
   if (!connected()) {
     return false;
   }
@@ -188,7 +194,7 @@
 
   set_bind_to_address(new_host);
   if (!network_helper_->CreateUDPSocketAndBind(server_address_,
-                                               bind_to_address_, local_port_)) {
+                                               bind_to_address_, port)) {
     return false;
   }
 
diff --git a/net/third_party/quic/tools/quic_client_base.h b/net/third_party/quic/tools/quic_client_base.h
index d1f2eb12..4503085 100644
--- a/net/third_party/quic/tools/quic_client_base.h
+++ b/net/third_party/quic/tools/quic_client_base.h
@@ -106,9 +106,12 @@
   // Returns true if there are any outstanding requests.
   bool WaitForEvents();
 
-  // Migrate to a new socket during an active connection.
+  // Migrate to a new socket (new_host) during an active connection.
   bool MigrateSocket(const QuicIpAddress& new_host);
 
+  // Migrate to a new socket (new_host, port) during an active connection.
+  bool MigrateSocketWithSpecifiedPort(const QuicIpAddress& new_host, int port);
+
   QuicSession* session();
 
   bool connected() const;
diff --git a/net/third_party/quic/tools/quic_packet_printer_bin.cc b/net/third_party/quic/tools/quic_packet_printer_bin.cc
index 44689525..743d114 100644
--- a/net/third_party/quic/tools/quic_packet_printer_bin.cc
+++ b/net/third_party/quic/tools/quic_packet_printer_bin.cc
@@ -105,10 +105,6 @@
               << " }\n";
     return true;
   }
-  bool OnAckFrame(const QuicAckFrame& frame) override {
-    std::cerr << "OnAckFrame: " << frame;
-    return true;
-  }
   bool OnAckFrameStart(QuicPacketNumber largest_acked,
                        QuicTime::Delta /*ack_delay_time*/) override {
     std::cerr << "OnAckFrameStart, largest_acked: " << largest_acked;
diff --git a/net/third_party/quic/tools/trace/quic_trace_to_time_sequence_gnuplot.cc b/net/third_party/quic/tools/trace/quic_trace_to_time_sequence_gnuplot.cc
deleted file mode 100644
index 0adfeca..0000000
--- a/net/third_party/quic/tools/trace/quic_trace_to_time_sequence_gnuplot.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Helper script to generate time sequence plot using gnuplot.
-// Accepts the trace on stdin, and outputs the gnuplot-consumable time series
-// file into stdout.
-
-#include <iostream>
-#include <streambuf>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "base/command_line.h"
-#include "net/third_party/quic/core/proto/quic_trace.pb.h"
-
-std::string FLAGS_sequence = "";
-bool FLAGS_filter_old_acks = true;
-
-namespace quic_trace {
-namespace {
-
-// Calculates the amount of actual data in the packet.
-size_t FrameDataInSentPacket(const Event& packet) {
-  if (packet.event_type() != PACKET_SENT) {
-    return 0;
-  }
-
-  size_t sent_in_packet = 0;
-  for (const Frame& frame : packet.frames()) {
-    if (frame.frame_type() != STREAM || !frame.has_stream_frame_info()) {
-      continue;
-    }
-    sent_in_packet += frame.stream_frame_info().length();
-  }
-  return sent_in_packet;
-}
-
-struct SentPacket {
-  // Offset of the stream data sent in the frame with respect to the beginning
-  // of the connection.
-  size_t offset;
-  // Size of frame data in the packet.
-  size_t size;
-};
-// Map of the sent packets, keyed by packet number.
-using SentPacketMap = std::unordered_map<uint64_t, SentPacket>;
-
-void PrintSentPacket(const SentPacketMap& packet_map,
-                     uint64_t packet_number,
-                     uint64_t time) {
-  auto original_packet_it = packet_map.find(packet_number);
-  if (original_packet_it == packet_map.end()) {
-    return;
-  }
-
-  const SentPacket& original_packet = original_packet_it->second;
-
-  std::cout << time << " " << original_packet.offset << std::endl;
-  std::cout << time << " " << (original_packet.offset + original_packet.size)
-            << std::endl;
-  std::cout << std::endl;
-}
-
-void PrintTimeSequence(std::istream* trace_source) {
-  Trace trace;
-  std::string trace_raw((std::istreambuf_iterator<char>(std::cin)),
-                        std::istreambuf_iterator<char>());
-  trace.ParseFromString(trace_raw);
-
-  size_t total_sent = 0;
-  SentPacketMap packet_map;
-  std::unordered_set<uint64_t> already_acknowledged;
-  // In a single pass, compute |packet_map| and output the requested sequence.
-  for (const Event& event : trace.events()) {
-    // Track all sent packets and their offsets in the plot.
-    size_t sent_in_packet = FrameDataInSentPacket(event);
-    if (sent_in_packet != 0) {
-      packet_map.emplace(event.packet_number(),
-                         SentPacket{total_sent, sent_in_packet});
-    }
-    total_sent += sent_in_packet;
-
-    // Output sent packets.
-    if (sent_in_packet != 0 && FLAGS_sequence == "send") {
-      std::cout << event.time_us() << " " << (total_sent - sent_in_packet)
-                << std::endl;
-      std::cout << event.time_us() << " " << total_sent << std::endl;
-      std::cout << std::endl;
-    }
-
-    // Output loss events.
-    if (event.event_type() == PACKET_LOST && FLAGS_sequence == "loss") {
-      PrintSentPacket(packet_map, event.packet_number(), event.time_us());
-    }
-
-    // Output acks.
-    if (event.event_type() == PACKET_RECEIVED) {
-      for (const Frame& frame : event.frames()) {
-        if (frame.frame_type() == ACK && FLAGS_sequence == "ack") {
-          for (const AckBlock& block : frame.ack_info().acked_packets()) {
-            for (uint64_t packet = block.first_packet();
-                 packet <= block.last_packet(); packet++) {
-              if (FLAGS_filter_old_acks) {
-                if (already_acknowledged.count(packet) > 0) {
-                  continue;
-                }
-                already_acknowledged.insert(packet);
-              }
-              PrintSentPacket(packet_map, packet, event.time_us());
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-}  // namespace
-}  // namespace quic_trace
-
-int main(int argc, char* argv[]) {
-  base::CommandLine::Init(argc, argv);
-  base::CommandLine* line = base::CommandLine::ForCurrentProcess();
-  if (line->HasSwitch("sequence")) {
-    FLAGS_sequence = line->GetSwitchValueASCII("sequence");
-  }
-  if (line->HasSwitch("nofilter_old_acks")) {
-    FLAGS_filter_old_acks = false;
-  }
-
-  if (FLAGS_sequence != "send" && FLAGS_sequence != "ack" &&
-      FLAGS_sequence != "loss") {
-    std::cerr << "The --type parameter has to be set to either 'send', 'ack' "
-                 "or 'loss'."
-              << std::endl;
-    return 1;
-  }
-
-  quic_trace::PrintTimeSequence(&std::cin);
-  return 0;
-}
diff --git a/net/third_party/quic/tools/trace/time_sequence_gnuplot.sh b/net/third_party/quic/tools/trace/time_sequence_gnuplot.sh
deleted file mode 100755
index 7d9abd20..0000000
--- a/net/third_party/quic/tools/trace/time_sequence_gnuplot.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-#
-# Render a trace using gnuplot into a png file.
-#
-
-if [ -z "$1" ]; then
-  echo "Usage: time_sequence_gnuplot.sh path/to/trace output.png"
-  exit 1
-fi
-
-if [ ! -f "$1" ]; then
-  echo "File $1 does not exist or is not a file"
-  exit 1
-fi
-
-if [ -z "$2" ]; then
-  echo "Output file not specified"
-  exit 1
-fi
-
-if [ ! -x "$QUIC_TRACE_CONV_BIN" ]; then
-  SCRIPT_SOURCE_DIR="$(dirname "${BASH_SOURCE[0]}")"
-  QUIC_TRACE_CONV_BIN="$SCRIPT_SOURCE_DIR/../../../../../out/Default/quic_trace_to_time_sequence_gnuplot"
-fi
-
-if [ ! -x "$QUIC_TRACE_CONV_BIN" ]; then
-  echo "Cannot find conversion tool binary"
-  exit 1
-fi
-
-TMPDIR="$(mktemp -d)"
-for event_type in send ack loss; do
-  "$QUIC_TRACE_CONV_BIN" --sequence=$event_type < "$1" > "$TMPDIR/$event_type.txt"
-done
-
-if [ -z "$GNUPLOT_SIZE" ]; then
-  GNUPLOT_SIZE="7680,4320"
-fi
-if [ -z "$GNUPLOT_TERMINAL" ]; then
-  GNUPLOT_TERMINAL="png size $GNUPLOT_SIZE"
-fi
-
-
-gnuplot <<EOF
-set terminal $GNUPLOT_TERMINAL
-set output "$2"
-plot \
-   "$TMPDIR/send.txt" with lines lt rgb "blue" title "Sent", \
-   "$TMPDIR/ack.txt" with lines lt rgb "green" title "Ack", \
-   "$TMPDIR/loss.txt" with lines lt rgb "red" title "Loss"
-EOF
-
-rm -rf "$TMPDIR"
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.cc b/net/tools/cert_verify_tool/verify_using_path_builder.cc
index 8621c76..8a933a6 100644
--- a/net/tools/cert_verify_tool/verify_using_path_builder.cc
+++ b/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -163,7 +163,8 @@
     return false;
 
   // Verify the chain.
-  net::SimplePathBuilderDelegate delegate(2048);
+  net::SimplePathBuilderDelegate delegate(
+      2048, net::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
   net::CertPathBuilder::Result result;
   net::CertPathBuilder path_builder(
       target_cert, ssl_trust_store->GetTrustStore(), &delegate, time,
@@ -193,11 +194,11 @@
   }
 
   // TODO(mattm): add flag to dump all paths, not just the final one?
-  if (!dump_prefix_path.empty() && result.paths.size()) {
+  if (!dump_prefix_path.empty() && !result.paths.empty()) {
     if (!DumpParsedCertificateChain(
             dump_prefix_path.AddExtension(
                 FILE_PATH_LITERAL(".CertPathBuilder.pem")),
-            *result.paths[result.best_result_index])) {
+            *result.GetBestPathPossiblyInvalid())) {
       return false;
     }
   }
diff --git a/net/tools/huffman_trie/BUILD.gn b/net/tools/huffman_trie/BUILD.gn
index a4d1e3a..c172af0f2 100644
--- a/net/tools/huffman_trie/BUILD.gn
+++ b/net/tools/huffman_trie/BUILD.gn
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-assert(current_toolchain == host_toolchain)
-
 source_set("huffman_trie_generator_sources") {
   sources = [
     "bit_writer.cc",
diff --git a/net/tools/huffman_trie/trie/trie_writer.cc b/net/tools/huffman_trie/trie/trie_writer.cc
index 9f85f132..6dc38eb 100644
--- a/net/tools/huffman_trie/trie/trie_writer.cc
+++ b/net/tools/huffman_trie/trie/trie_writer.cc
@@ -123,7 +123,7 @@
                                      uint32_t* position) {
   DCHECK(start != end) << "No entries passed to WriteDispatchTables";
 
-  huffman_trie::TrieBitBuffer writer;
+  TrieBitBuffer writer;
 
   std::vector<uint8_t> prefix = LongestCommonPrefix(start, end);
   for (size_t i = 0; i < prefix.size(); ++i) {
diff --git a/net/tools/huffman_trie/trie/trie_writer.h b/net/tools/huffman_trie/trie/trie_writer.h
index 6bf3e9bedb..3c824e7 100644
--- a/net/tools/huffman_trie/trie/trie_writer.h
+++ b/net/tools/huffman_trie/trie/trie_writer.h
@@ -20,8 +20,8 @@
 
 class TrieWriter {
  public:
-  TrieWriter(const huffman_trie::HuffmanRepresentationTable& huffman_table,
-             huffman_trie::HuffmanBuilder* huffman_builder);
+  TrieWriter(const HuffmanRepresentationTable& huffman_table,
+             HuffmanBuilder* huffman_builder);
   ~TrieWriter();
 
   // Constructs a trie containing all |entries|. The output is written to
@@ -40,18 +40,25 @@
   // complete.
   const std::vector<uint8_t>& bytes() const { return buffer_.bytes(); }
 
+ protected:
+  const HuffmanRepresentationTable& huffman_table() const {
+    return huffman_table_;
+  }
+
+  HuffmanBuilder* huffman_builder() { return huffman_builder_; }
+
  private:
   bool WriteDispatchTables(ReversedEntries::iterator start,
                            ReversedEntries::iterator end,
                            uint32_t* position);
 
-  huffman_trie::BitWriter buffer_;
-  const huffman_trie::HuffmanRepresentationTable& huffman_table_;
-  huffman_trie::HuffmanBuilder* huffman_builder_;
+  BitWriter buffer_;
+  const HuffmanRepresentationTable& huffman_table_;
+  HuffmanBuilder* huffman_builder_;
 };
 
 }  // namespace huffman_trie
 
 }  // namespace net
 
-#endif  // NET_TOOLS_TRANSPORT_SECURITY_STATE_GENERATOR_TRIE_TRIE_WRITER_H_
+#endif  // NET_TOOLS_HUFFMAN_TRIE_TRIE_TRIE_WRITER_H_
diff --git a/net/tools/huffman_trie/trie_entry.h b/net/tools/huffman_trie/trie_entry.h
index 79273ed..fe70260 100644
--- a/net/tools/huffman_trie/trie_entry.h
+++ b/net/tools/huffman_trie/trie_entry.h
@@ -20,6 +20,8 @@
   TrieEntry();
   virtual ~TrieEntry();
 
+  // The name to be used when inserting the entry to the trie. E.g. for HSTS
+  // preload list, this is the hostname.
   virtual std::string name() const = 0;
   virtual bool WriteEntry(huffman_trie::TrieBitBuffer* writer) const = 0;
 };
@@ -28,6 +30,8 @@
 // of raw pointers instead.
 using TrieEntries = std::vector<TrieEntry*>;
 
+// ReversedEntry points to a TrieEntry and contains the reversed name for
+// that entry. This is used to construct the trie.
 struct ReversedEntry {
   ReversedEntry(std::vector<uint8_t> reversed_name, const TrieEntry* entry);
   ~ReversedEntry();
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index 86ae8fb..5d72a7c 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -14,20 +14,7 @@
     : signin_manager_(signin_manager),
       token_service_(token_service),
       account_tracker_service_(account_tracker_service) {
-  // Initialize the state of the primary account.
   primary_account_info_ = signin_manager_->GetAuthenticatedAccountInfo();
-
-  // Initialize the state of accounts with refresh tokens.
-  // |account_id| is moved into |accounts_with_refresh_tokens_|.
-  // Do not change this to "const std::string&".
-  for (std::string account_id : token_service->GetAccounts()) {
-    AccountInfo account_info =
-        account_tracker_service_->GetAccountInfo(account_id);
-    DCHECK(!account_info.IsEmpty());
-    accounts_with_refresh_tokens_.emplace(std::move(account_id),
-                                          std::move(account_info));
-  }
-
   signin_manager_->AddObserver(this);
 #if !defined(OS_CHROMEOS)
   SigninManager::FromSigninManagerBase(signin_manager_)
@@ -96,29 +83,6 @@
   return !primary_account_info_.account_id.empty();
 }
 
-std::vector<AccountInfo> IdentityManager::GetAccountsWithRefreshTokens() {
-  // TODO(blundell): It seems wasteful to construct this vector every time this
-  // method is called, but it also seems bad to maintain the vector as an ivar
-  // along the map.
-  std::vector<AccountInfo> accounts;
-  accounts.reserve(accounts_with_refresh_tokens_.size());
-
-  for (const auto& pair : accounts_with_refresh_tokens_) {
-    accounts.push_back(pair.second);
-  }
-
-  return accounts;
-}
-
-bool IdentityManager::HasAccountWithRefreshToken(
-    const std::string& account_id) {
-  return base::ContainsKey(accounts_with_refresh_tokens_, account_id);
-}
-
-bool IdentityManager::HasPrimaryAccountWithRefreshToken() {
-  return HasAccountWithRefreshToken(GetPrimaryAccountInfo().account_id);
-}
-
 std::unique_ptr<AccessTokenFetcher>
 IdentityManager::CreateAccessTokenFetcherForAccount(
     const std::string& account_id,
@@ -233,20 +197,6 @@
   AccountInfo account_info =
       account_tracker_service_->GetAccountInfo(account_id);
   DCHECK(!account_info.IsEmpty());
-
-  // Insert the account into |accounts_with_refresh_tokens_|.
-  auto insertion_result = accounts_with_refresh_tokens_.emplace(
-      account_id, std::move(account_info));
-
-  // The account might have already been  present (e.g., this method can fire on
-  // updating an invalid token to a valid one or vice versa); in this case we
-  // sanity-check that the cached account info has the expected values.
-  if (!insertion_result.second) {
-    AccountInfo cached_account_info = insertion_result.first->second;
-    DCHECK_EQ(account_info.gaia, cached_account_info.gaia);
-    DCHECK_EQ(account_info.email, cached_account_info.email);
-  }
-
   for (auto& observer : observer_list_) {
     observer.OnRefreshTokenUpdatedForAccount(account_info, is_valid);
   }
@@ -257,11 +207,6 @@
   AccountInfo account_info =
       account_tracker_service_->GetAccountInfo(account_id);
   DCHECK(!account_info.IsEmpty());
-
-  auto iterator = accounts_with_refresh_tokens_.find(account_id);
-  DCHECK(iterator != accounts_with_refresh_tokens_.end());
-  accounts_with_refresh_tokens_.erase(iterator);
-
   for (auto& observer : observer_list_) {
     observer.OnRefreshTokenRemovedForAccount(account_info);
   }
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index 68aaa157..7597be4 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -120,20 +120,6 @@
   // primary account info has a valid account ID.
   bool HasPrimaryAccount();
 
-  // Provides access to the latest cached information of all accounts that have
-  // refresh tokens.
-  // NOTE: The accounts should not be assumed to be in any particular order; in
-  // particular, they are not guaranteed to be in the order in which the
-  // refresh tokens were added.
-  std::vector<AccountInfo> GetAccountsWithRefreshTokens();
-
-  // Returns true if a refresh token exists for |account_id|.
-  bool HasAccountWithRefreshToken(const std::string& account_id);
-
-  // Returns true if (a) the primary account exists, and (b) a refresh token
-  // exists for the primary account.
-  bool HasPrimaryAccountWithRefreshToken();
-
   // Creates an AccessTokenFetcher given the passed-in information.
   std::unique_ptr<AccessTokenFetcher> CreateAccessTokenFetcherForAccount(
       const std::string& account_id,
@@ -232,10 +218,6 @@
   // The latest (cached) value of the primary account.
   AccountInfo primary_account_info_;
 
-  // The latest (cached) value of the accounts with refresh tokens.
-  using AccountIDToAccountInfoMap = std::map<std::string, AccountInfo>;
-  AccountIDToAccountInfoMap accounts_with_refresh_tokens_;
-
   // Lists of observers.
   // Makes sure lists are empty on destruction.
   base::ObserverList<Observer, true> observer_list_;
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index c2c9f88..c0b490f 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -25,11 +25,8 @@
 #endif  // OS_CHROMEOS
 
 const char kTestGaiaId[] = "dummyId";
-const char kTestGaiaId2[] = "dummyId2";
-const char kTestGaiaId3[] = "dummyId3";
 const char kTestEmail[] = "me@gmail.com";
 const char kTestEmail2[] = "me2@gmail.com";
-const char kTestEmail3[] = "me3@gmail.com";
 
 #if defined(OS_CHROMEOS)
 const char kTestEmailWithPeriod[] = "m.e@gmail.com";
@@ -482,395 +479,6 @@
 #endif
 }
 
-TEST_F(IdentityManagerTest, GetAccountsInteractionWithPrimaryAccount) {
-  // Should not have any refresh tokens at initialization.
-  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
-
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
-  // Add a refresh token for the primary account and check that it shows up in
-  // GetAccountsWithRefreshTokens().
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  std::vector<AccountInfo> accounts_after_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id);
-  EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
-  EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
-
-  // Update the token and check that it doesn't change the state (or blow up).
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  std::vector<AccountInfo> accounts_after_second_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_second_update.size());
-  EXPECT_EQ(accounts_after_second_update[0].account_id, account_id);
-  EXPECT_EQ(accounts_after_second_update[0].gaia, kTestGaiaId);
-  EXPECT_EQ(accounts_after_second_update[0].email, kTestEmail);
-
-  // Remove the token for the primary account and check that this is likewise
-  // reflected.
-  RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
-}
-
-TEST_F(IdentityManagerTest,
-       QueryingOfRefreshTokensInteractionWithPrimaryAccount) {
-  AccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
-  std::string account_id = account_info.account_id;
-
-  // Should not have a refresh token for the primary account at initialization.
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Add a refresh token for the primary account and check that it affects this
-  // state.
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Update the token and check that it doesn't change the state (or blow up).
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Remove the token for the primary account and check that this is likewise
-  // reflected.
-  RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-}
-
-TEST_F(IdentityManagerTest, GetAccountsReflectsNonemptyInitialState) {
-  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
-
-  std::string account_id = signin_manager()->GetAuthenticatedAccountId();
-
-  // Add a refresh token for the primary account and sanity-check that it shows
-  // up in GetAccountsWithRefreshTokens().
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  std::vector<AccountInfo> accounts_after_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id);
-  EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId);
-  EXPECT_EQ(accounts_after_update[0].email, kTestEmail);
-
-  // Recreate the IdentityManager and check that the newly-created instance
-  // reflects the current state.
-  RecreateIdentityManager();
-
-  std::vector<AccountInfo> accounts_after_recreation =
-      identity_manager()->GetAccountsWithRefreshTokens();
-  EXPECT_EQ(1u, accounts_after_recreation.size());
-  EXPECT_EQ(accounts_after_recreation[0].account_id, account_id);
-  EXPECT_EQ(accounts_after_recreation[0].gaia, kTestGaiaId);
-  EXPECT_EQ(accounts_after_recreation[0].email, kTestEmail);
-}
-
-TEST_F(IdentityManagerTest,
-       QueryingOfRefreshTokensReflectsNonemptyInitialState) {
-  AccountInfo account_info = identity_manager()->GetPrimaryAccountInfo();
-  std::string account_id = account_info.account_id;
-
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Recreate the IdentityManager and check that the newly-created instance
-  // reflects the current state.
-  RecreateIdentityManager();
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info.account_id));
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-}
-
-TEST_F(IdentityManagerTest, GetAccountsInteractionWithSecondaryAccounts) {
-  // Should not have any refresh tokens at initialization.
-  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
-
-  // Add a refresh token for a secondary account and check that it shows up in
-  // GetAccountsWithRefreshTokens().
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  std::string account_id2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  std::vector<AccountInfo> accounts_after_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
-  EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
-  EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
-
-  // Add a refresh token for a different secondary account and check that it
-  // also shows up in GetAccountsWithRefreshTokens().
-  account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
-  std::string account_id3 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
-
-  std::vector<AccountInfo> accounts_after_second_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-  EXPECT_EQ(2u, accounts_after_second_update.size());
-
-  for (AccountInfo account_info : accounts_after_second_update) {
-    if (account_info.account_id == account_id2) {
-      EXPECT_EQ(account_info.gaia, kTestGaiaId2);
-      EXPECT_EQ(account_info.email, kTestEmail2);
-    } else {
-      EXPECT_EQ(account_info.gaia, kTestGaiaId3);
-      EXPECT_EQ(account_info.email, kTestEmail3);
-    }
-  }
-
-  // Remove the token for account2 and check that account3 is still present.
-  RemoveRefreshTokenForAccount(token_service(), identity_manager(),
-                               account_id2);
-
-  std::vector<AccountInfo> accounts_after_third_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_third_update.size());
-  EXPECT_EQ(accounts_after_third_update[0].account_id, account_id3);
-  EXPECT_EQ(accounts_after_third_update[0].gaia, kTestGaiaId3);
-  EXPECT_EQ(accounts_after_third_update[0].email, kTestEmail3);
-}
-
-TEST_F(IdentityManagerTest,
-       HasPrimaryAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Adding a refresh token for a secondary account shouldn't change anything
-  // about the primary account
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  std::string account_id2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Adding a refresh token for a different secondary account should not do so
-  // either.
-  account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
-  std::string account_id3 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Removing the token for account2 should have no effect.
-  RemoveRefreshTokenForAccount(token_service(), identity_manager(),
-                               account_id2);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-}
-
-TEST_F(IdentityManagerTest,
-       HasAccountWithRefreshTokenInteractionWithSecondaryAccounts) {
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  AccountInfo account_info2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
-  std::string account_id2 = account_info2.account_id;
-
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-
-  // Add a refresh token for account_info2 and check that this is reflected by
-  // HasAccountWithRefreshToken(.account_id).
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-
-  // Go through the same process for a different secondary account.
-  account_tracker()->SeedAccountInfo(kTestGaiaId3, kTestEmail3);
-  AccountInfo account_info3 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId3);
-  std::string account_id3 = account_info3.account_id;
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
-
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id3);
-
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
-
-  // Remove the token for account2.
-  RemoveRefreshTokenForAccount(token_service(), identity_manager(),
-                               account_id2);
-
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info3.account_id));
-}
-
-TEST_F(IdentityManagerTest,
-       GetAccountsInteractionBetweenPrimaryAndSecondaryAccounts) {
-  // Should not have any refresh tokens at initialization.
-  EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty());
-
-  // Add a refresh token for a secondary account and check that it shows up in
-  // GetAccountsWithRefreshTokens().
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  std::string account_id2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  std::vector<AccountInfo> accounts_after_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
-  EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
-  EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Add a refresh token for the primary account and check that it
-  // also shows up in GetAccountsWithRefreshTokens().
-  std::string primary_account_id =
-      signin_manager()->GetAuthenticatedAccountId();
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  std::vector<AccountInfo> accounts_after_second_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-  EXPECT_EQ(2u, accounts_after_second_update.size());
-
-  for (AccountInfo account_info : accounts_after_second_update) {
-    if (account_info.account_id == account_id2) {
-      EXPECT_EQ(account_info.gaia, kTestGaiaId2);
-      EXPECT_EQ(account_info.email, kTestEmail2);
-    } else {
-      EXPECT_EQ(account_info.gaia, kTestGaiaId);
-      EXPECT_EQ(account_info.email, kTestEmail);
-    }
-  }
-
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Remove the token for the primary account and check that account2 is still
-  // present.
-  RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  std::vector<AccountInfo> accounts_after_third_update =
-      identity_manager()->GetAccountsWithRefreshTokens();
-
-  EXPECT_EQ(1u, accounts_after_third_update.size());
-  EXPECT_EQ(accounts_after_update[0].account_id, account_id2);
-  EXPECT_EQ(accounts_after_update[0].gaia, kTestGaiaId2);
-  EXPECT_EQ(accounts_after_update[0].email, kTestEmail2);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-}
-
-TEST_F(
-    IdentityManagerTest,
-    HasPrimaryAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Add a refresh token for a secondary account and check that it doesn't
-  // impact the above state.
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  std::string account_id2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id;
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Add a refresh token for the primary account and check that it
-  // *does* impact the stsate of HasPrimaryAccountWithRefreshToken().
-  std::string primary_account_id =
-      signin_manager()->GetAuthenticatedAccountId();
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Remove the token for the secondary account and check that this doesn't flip
-  // the state.
-  RemoveRefreshTokenForAccount(token_service(), identity_manager(),
-                               account_id2);
-
-  EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-
-  // Remove the token for the primary account and check that this flips the
-  // state.
-  RemoveRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_FALSE(identity_manager()->HasPrimaryAccountWithRefreshToken());
-}
-
-TEST_F(
-    IdentityManagerTest,
-    HasAccountWithRefreshTokenInteractionBetweenPrimaryAndSecondaryAccounts) {
-  AccountInfo primary_account_info =
-      identity_manager()->GetPrimaryAccountInfo();
-  std::string primary_account_id = primary_account_info.account_id;
-
-  account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2);
-  AccountInfo account_info2 =
-      account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2);
-  std::string account_id2 = account_info2.account_id;
-
-  EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
-      primary_account_info.account_id));
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-
-  // Add a refresh token for account_info2 and check that this is reflected by
-  // HasAccountWithRefreshToken(.account_id).
-  SetRefreshTokenForAccount(token_service(), identity_manager(), account_id2);
-
-  EXPECT_FALSE(identity_manager()->HasAccountWithRefreshToken(
-      primary_account_info.account_id));
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-
-  // Go through the same process for the primary account.
-  SetRefreshTokenForPrimaryAccount(token_service(), identity_manager());
-
-  EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
-      primary_account_info.account_id));
-  EXPECT_TRUE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-
-  // Remove the token for account2.
-  RemoveRefreshTokenForAccount(token_service(), identity_manager(),
-                               account_id2);
-
-  EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken(
-      primary_account_info.account_id));
-  EXPECT_FALSE(
-      identity_manager()->HasAccountWithRefreshToken(account_info2.account_id));
-}
-
 TEST_F(IdentityManagerTest, RemoveAccessTokenFromCache) {
   std::set<std::string> scopes{"scope"};
   std::string access_token = "access_token";
diff --git a/services/viz/public/cpp/compositing/struct_traits_unittest.cc b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
index 51d7ca5..aa8029e0 100644
--- a/services/viz/public/cpp/compositing/struct_traits_unittest.cc
+++ b/services/viz/public/cpp/compositing/struct_traits_unittest.cc
@@ -486,13 +486,11 @@
   // TransferableResource constants.
   const uint32_t tr_id = 1337;
   const ResourceFormat tr_format = ALPHA_8;
-  const gfx::BufferFormat tr_buffer_format = gfx::BufferFormat::R_8;
   const uint32_t tr_filter = 1234;
   const gfx::Size tr_size(1234, 5678);
   TransferableResource resource;
   resource.id = tr_id;
   resource.format = tr_format;
-  resource.buffer_format = tr_buffer_format;
   resource.filter = tr_filter;
   resource.size = tr_size;
 
@@ -528,7 +526,6 @@
   TransferableResource out_resource = output.resource_list[0];
   EXPECT_EQ(tr_id, out_resource.id);
   EXPECT_EQ(tr_format, out_resource.format);
-  EXPECT_EQ(tr_buffer_format, out_resource.buffer_format);
   EXPECT_EQ(tr_filter, out_resource.filter);
   EXPECT_EQ(tr_size, out_resource.size);
 
diff --git a/services/viz/public/cpp/compositing/transferable_resource_struct_traits.cc b/services/viz/public/cpp/compositing/transferable_resource_struct_traits.cc
index df773cf..623889d1 100644
--- a/services/viz/public/cpp/compositing/transferable_resource_struct_traits.cc
+++ b/services/viz/public/cpp/compositing/transferable_resource_struct_traits.cc
@@ -25,7 +25,6 @@
     return false;
   out->id = data.id();
   out->format = static_cast<viz::ResourceFormat>(data.format());
-  out->buffer_format = static_cast<gfx::BufferFormat>(data.buffer_format());
   out->filter = data.filter();
   out->read_lock_fences_enabled = data.read_lock_fences_enabled();
   out->is_software = data.is_software();
diff --git a/services/viz/public/cpp/compositing/transferable_resource_struct_traits.h b/services/viz/public/cpp/compositing/transferable_resource_struct_traits.h
index 9f7b390..57238e81 100644
--- a/services/viz/public/cpp/compositing/transferable_resource_struct_traits.h
+++ b/services/viz/public/cpp/compositing/transferable_resource_struct_traits.h
@@ -24,11 +24,6 @@
     return static_cast<viz::mojom::ResourceFormat>(resource.format);
   }
 
-  static gfx::mojom::BufferFormat buffer_format(
-      const viz::TransferableResource& resource) {
-    return static_cast<gfx::mojom::BufferFormat>(resource.buffer_format);
-  }
-
   static uint32_t filter(const viz::TransferableResource& resource) {
     return resource.filter;
   }
diff --git a/services/viz/public/interfaces/compositing/transferable_resource.mojom b/services/viz/public/interfaces/compositing/transferable_resource.mojom
index e2aed0f..015f3d1 100644
--- a/services/viz/public/interfaces/compositing/transferable_resource.mojom
+++ b/services/viz/public/interfaces/compositing/transferable_resource.mojom
@@ -17,18 +17,26 @@
   ALPHA_8,
   LUMINANCE_8,
   RGB_565,
+  BGR_565,
   ETC1,
   RED_8,
+  RG_88,
   LUMINANCE_F16,
   RGBA_F16,
   R16_EXT,
+  RGBX_8888,
+  BGRX_8888,
+  RGBX_1010102,
+  BGRX_1010102,
+  YVU_420,
+  YUV_420_BIPLANAR,
+  UYVY_422,
 };
 
 // See components/viz/common/resources/transferable_resource.h.
 struct TransferableResource {
   uint32 id;
   ResourceFormat format;
-  gfx.mojom.BufferFormat buffer_format;
   uint32 filter;
   gfx.mojom.Size size;
   gpu.mojom.MailboxHolder mailbox_holder;
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index b9c58ec..4ffa1673 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3254,6 +3254,7 @@
           "--browser=cros-chrome",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222",
+          "--skip=telemetry.core.tracing_controller_unittest.TracingControllerTest.testBattOrTracing",
           "--skip=telemetry.internal.app.android_app_unittest.AndroidAppTest.testWebView"
         ],
         "isolate_name": "telemetry_unittests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index cdbd3ee..ddeb9fc 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -3294,6 +3294,7 @@
           "dimension_sets": [
             {
               "gpu": "none",
+              "os": "Mac-10.13",
               "pool": "Chrome-quarantine"
             }
           ],
@@ -3306,7 +3307,12 @@
           "--disable-features=ViewsBrowserWindows"
         ],
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Mac-10.13"
+            }
+          ]
         },
         "test": "components_browsertests"
       },
@@ -3315,7 +3321,12 @@
           "--disable-features=ViewsBrowserWindows"
         ],
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Mac-10.13"
+            }
+          ]
         },
         "test": "content_browsertests"
       },
@@ -3325,6 +3336,11 @@
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Mac-10.13"
+            }
+          ],
           "shards": 3
         },
         "test": "interactive_ui_tests"
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index bd03915..b51d196 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -562,7 +562,7 @@
             {
               "gpu": "8086:0a2e",
               "os": "Mac-10.12",
-              "pool": "Chrome-perf-fyi"
+              "pool": "chrome.tests.perf-fyi"
             }
           ],
           "expiration": 36000,
@@ -606,7 +606,7 @@
             {
               "gpu": "8086:0a2e",
               "os": "Mac-10.12",
-              "pool": "Chrome-perf-fyi"
+              "pool": "chrome.tests.perf-fyi"
             }
           ],
           "expiration": 36000,
@@ -647,7 +647,7 @@
             {
               "gpu": "8086:0a2e",
               "os": "Mac-10.12",
-              "pool": "Chrome-perf-fyi"
+              "pool": "chrome.tests.perf-fyi"
             }
           ],
           "expiration": 36000,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index e18c874a..7bec85fc 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -410,6 +410,9 @@
         # By default, CrOS VMs' ssh servers listen on local port 9222.
         '--remote=127.0.0.1',
         '--remote-ssh-port=9222',
+        # Flaky.
+        '--skip=telemetry.core.tracing_controller_unittest.TracingControllerTest.testBattOrTracing',
+        # Always fails.
         '--skip=telemetry.internal.app.android_app_unittest.AndroidAppTest.testWebView',
       ],
       'swarming': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 3574b6f..e831d28 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2881,6 +2881,13 @@
         ],
       },
       'mac-cocoa-rel': {
+        'swarming': {
+          'dimension_sets': [
+            {
+              'os': 'Mac-10.13',
+            },
+          ],
+        },
         'test_suites': {
           'gtest_tests': 'chromium_browser_tests',
         },
diff --git a/testing/scripts/common.py b/testing/scripts/common.py
index 28758fe..786e98f 100644
--- a/testing/scripts/common.py
+++ b/testing/scripts/common.py
@@ -167,6 +167,24 @@
 
 def get_gtest_summary_passes(output):
   """Returns a mapping of test to boolean indicating if the test passed.
+  """
+  if not output:
+    return {}
+
+  mapping = {}
+
+  for test_suite in output.get('testsuites', []):
+    suite_name = test_suite['name']
+    for test in test_suite['testsuite']:
+      full_name = '%s.%s' % (suite_name, test['name'])
+
+      mapping[full_name] = 'failures' in test
+
+  return mapping
+
+
+def get_chromium_gtest_summary_passes(output):
+  """Returns a mapping of test to boolean indicating if the test passed.
 
   Only partially parses the format. This code is based on code in tools/build,
   specifically
diff --git a/testing/scripts/run_gtest_perf_test.py b/testing/scripts/run_gtest_perf_test.py
index 83198f5c..e1dd0d5 100755
--- a/testing/scripts/run_gtest_perf_test.py
+++ b/testing/scripts/run_gtest_perf_test.py
@@ -32,6 +32,7 @@
 import os
 import shutil
 import sys
+import time
 import tempfile
 import traceback
 
@@ -82,7 +83,7 @@
 
   args, rest_args = parser.parse_known_args()
 
-  rc, charts, output_json = execute_perf_test(args, rest_args)
+  rc, charts, output_json = execute_perf_test(args, rest_args, True)
 
   # TODO(eakuefner): Make isolated_script_test_perf_output mandatory after
   # flipping flag in swarming.
@@ -100,7 +101,7 @@
   return rc
 
 
-def execute_perf_test(args, rest_args):
+def execute_perf_test(args, rest_args, chromium_gtest):
   env = os.environ.copy()
   # Assume we want to set up the sandbox environment variables all the
   # time; doing so is harmless on non-Linux platforms and is needed
@@ -108,53 +109,95 @@
   env[CHROME_SANDBOX_ENV] = CHROME_SANDBOX_PATH
 
   rc = 0
-  try:
-    executable = rest_args[0]
-    extra_flags = []
-    if len(rest_args) > 1:
-      extra_flags = rest_args[1:]
+  start_time = time.time()
+  test_results = {}
+  with common.temporary_file() as results_path:
+    try:
+      executable = rest_args[0]
+      extra_flags = []
+      if len(rest_args) > 1:
+        extra_flags = rest_args[1:]
 
-    # These flags are to make sure that test output perf metrics in the log.
-    if not '--verbose' in extra_flags:
-      extra_flags.append('--verbose')
-    if not '--test-launcher-print-test-stdio=always' in extra_flags:
-      extra_flags.append('--test-launcher-print-test-stdio=always')
-    if args.isolated_script_test_filter:
-      filter_list = common.extract_filter_list(
-        args.isolated_script_test_filter)
-      extra_flags.append('--gtest_filter=' + ':'.join(filter_list))
-
-    if IsWindows():
-      executable = '.\%s.exe' % executable
-    else:
-      executable = './%s' % executable
-    with common.temporary_file() as tempfile_path:
-      env['CHROME_HEADLESS'] = '1'
-      cmd = [executable] + extra_flags
-
-      if args.xvfb:
-        rc = xvfb.run_executable(cmd, env, stdoutfile=tempfile_path)
+      if chromium_gtest:
+        output_flag = '--test-launcher-summary-output'
+        output_file = results_path
       else:
-        rc = test_env.run_command_with_output(cmd, env=env,
-                                              stdoutfile=tempfile_path)
+        output_flag = '--gtest_output'
+        output_file = 'json:%s' % results_path
 
-      # Now get the correct json format from the stdout to write to the perf
-      # results file
-      results_processor = (
-          generate_legacy_perf_dashboard_json.LegacyResultsProcessor())
-      charts = results_processor.GenerateJsonResults(tempfile_path)
-  except Exception:
-    traceback.print_exc()
-    rc = 1
+      assert not any(output_flag in flag for flag in extra_flags), (
+          'Duplicate %s flag detected.' % output_flag)
+      extra_flags.append('%s=%s' % (output_flag, output_file))
 
-  valid = (rc == 0)
-  failures = [] if valid else ['(entire test suite)']
+      # These flags are to make sure that test output perf metrics in the log.
+      if not '--verbose' in extra_flags:
+        extra_flags.append('--verbose')
+      if not '--test-launcher-print-test-stdio=always' in extra_flags:
+        extra_flags.append('--test-launcher-print-test-stdio=always')
+      if args.isolated_script_test_filter:
+        filter_list = common.extract_filter_list(
+          args.isolated_script_test_filter)
+        extra_flags.append('--gtest_filter=' + ':'.join(filter_list))
+
+      if IsWindows():
+        executable = '.\%s.exe' % executable
+      else:
+        executable = './%s' % executable
+      with common.temporary_file() as tempfile_path:
+        env['CHROME_HEADLESS'] = '1'
+        cmd = [executable] + extra_flags
+
+        print ' '.join(cmd)
+        if args.xvfb:
+          rc = xvfb.run_executable(cmd, env, stdoutfile=tempfile_path)
+        else:
+          rc = test_env.run_command_with_output(cmd, env=env,
+                                                stdoutfile=tempfile_path)
+
+        # Now get the correct json format from the stdout to write to the perf
+        # results file
+        results_processor = (
+            generate_legacy_perf_dashboard_json.LegacyResultsProcessor())
+        charts = results_processor.GenerateJsonResults(tempfile_path)
+    except Exception:
+      traceback.print_exc()
+      rc = 1
+
+    if os.path.exists(results_path):
+      with open(results_path) as f:
+        if chromium_gtest:
+          func = common.get_chromium_gtest_summary_passes
+        else:
+          func = common.get_gtest_summary_passes
+        test_results = func(json.load(f))
+
   output_json = {
-      'valid': valid,
-      'failures': failures,
+    'version': 3,
+    'interrupted': False,
+    'path_delimiter': '/',
+    'seconds_since_epoch': start_time,
+    'num_failures_by_type': {
+      'PASS': sum(1 for success in test_results.values() if success),
+      'FAIL': sum(1 for success in test_results.values() if not success),
+    },
+    'tests': {
+        test: test_result_entry(success) for (
+            test, success) in test_results.items()
     }
+  }
+
   return rc, charts, output_json
 
+
+def test_result_entry(success):
+  test = {
+    'expected': 'PASS',
+    'actual': 'PASS' if success else 'FAIL',
+  }
+  if not success:
+    test['unexpected'] = True
+  return test
+
 # This is not really a "script test" so does not need to manually add
 # any additional compile targets.
 def main_compile_targets(args):
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py
index a491fcd..aab7c26 100755
--- a/testing/scripts/run_performance_tests.py
+++ b/testing/scripts/run_performance_tests.py
@@ -197,7 +197,7 @@
     # For non telemetry tests the benchmark name is the name of the executable.
     benchmark_name = rest_args[0]
     return_code, charts, output_json = run_gtest_perf_test.execute_perf_test(
-        args, rest_args)
+        args, rest_args, False)
 
     write_results(benchmark_name, charts, output_json,
                   benchmark_log='Not available for C++ perf test',
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 07047b1..fe30811e 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -176,6 +176,7 @@
 /python_26
 /pywebsocket/src
 /pywebsocket/src
+/quic_trace/src
 /r8/lib
 /re2/src
 /requests/src
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index f49e56ff..54a55e0 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -17,9 +17,6 @@
 crbug.com/854889 accessibility/css-generated-content.html [ Failure ]
 crbug.com/854889 accessibility/css-styles.html [ Failure ]
 
-# Hit test failure due to vertical-rl writing mode
-crbug.com/851075 fast/writing-mode/vertical-inline-block-hittest.html [ Failure ]
-
 # Wrong image alignment in vertical-rl writing mode
 crbug.com/636993 fast/writing-mode/vertical-baseline-alignment.html [ Failure ]
 
@@ -111,6 +108,7 @@
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-remove-006.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/text/white-space-mixed-003.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ]
+crbug.com/859233 external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-contain/contain-paint-007.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-filter/filtered-inline-is-container.html [ Crash ]
 crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-1.html [ Pass ]
@@ -304,7 +302,6 @@
 crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html [ Failure ]
 crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html [ Failure ]
 crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html [ Failure ]
-crbug.com/591099 external/wpt/html/semantics/interactive-elements/the-dialog-element/centering.html [ Crash ]
 crbug.com/591099 external/wpt/payment-handler/can-make-payment-event-constructor.https.worker.html [ Pass ]
 crbug.com/591099 external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html [ Pass ]
 crbug.com/591099 external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
index 2e6544b..214fa76 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -406,6 +406,12 @@
 Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ]
 Bug(none) compositing/overflow/siblings-with-border-radius-ancestor.html [ Failure ]
 Bug(none) compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Crash Failure ]
+Bug(none) fast/borders/border-radius-mask-canvas-border.html [ Failure ]
+Bug(none) fast/borders/border-radius-mask-canvas-with-mask.html [ Failure ]
+Bug(none) fast/borders/border-radius-mask-canvas.html [ Failure ]
+Bug(none) fast/borders/border-radius-mask-video-ratio.html [ Failure ]
+Bug(none) fast/borders/border-radius-mask-video-shadow.html [ Failure ]
+Bug(none) fast/borders/border-radius-mask-video.html [ Failure ]
 Bug(none) fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
 Bug(none) fast/clip/overflow-border-radius-composited.html [ Failure ]
 
@@ -471,18 +477,6 @@
 # Something wrong with vertical-rl scrollbars
 crbug.com/853945 fast/block/positioning/vertical-rl/002.html [ Failure ]
 
-# Border radius mask wrong.
-crbug.com/853943 fast/borders/border-radius-mask-canvas-all.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-canvas-border.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-canvas-padding.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-canvas-with-mask.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-canvas-with-shadow.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-canvas.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-video-ratio.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-video-shadow.html [ Failure ]
-crbug.com/853943 fast/borders/border-radius-mask-video.html [ Failure ]
-crbug.com/853943 fast/borders/overflow-hidden-border-radius-force-backing-store.html [ Failure ]
-
 # Something with the pattern is wrong. Needs investigation.
 crbug.com/853947 fast/canvas/synchronous-create-pattern.html [ Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 41e1da4..4a9dffa 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -285,6 +285,9 @@
 crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-004.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-005.html [ Failure ]
 
+# Currently also fails in LayoutNG and to be fixed there
+crbug.com/859233 external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ]
+
 ### virtual/layout_ng/external/wpt/css/CSS2/floats
 crbug.com/711704 virtual/layout_ng/external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht [ Failure ]
 crbug.com/711704 virtual/layout_ng/external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht [ Failure ]
@@ -475,7 +478,6 @@
 crbug.com/714962 [ Mac Win ] virtual/layout_ng/fast/writing-mode/english-lr-text.html [ Failure ]
 crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/japanese-rl-text.html [ Failure ]
 crbug.com/714962 [ Mac ] virtual/layout_ng/fast/writing-mode/text-orientation-basic.html [ Failure ]
-crbug.com/851075 virtual/layout_ng/fast/writing-mode/vertical-inline-block-hittest.html [ Failure ]
 
 # Crashes/asserts due to inline item reuse.
 crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-block-from-content-after-spanner.html [ Failure Crash Timeout ]
@@ -2799,6 +2801,8 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-scoping/host-specificity-002.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-scoping/slotted-specificity.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/break-spaces-001.html [ Failure ]
 crbug.com/626703 external/wpt/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 Mac10.13 ] external/wpt/compat/webkit-text-fill-color-property-002.html [ Failure ]
@@ -4736,3 +4740,6 @@
 crbug.com/859064 [ Linux Win10 Mac10.13 ] http/tests/devtools/console-resource-errors.js [ Failure ]
 crbug.com/859169 [ Win7 ] http/tests/devtools/layers/layer-scroll-rects-get.js [ Failure Pass ]
 crbug.com/859270 [ Mac10.12 ] external/wpt/gyroscope/Gyroscope-iframe-access.https.html [ Timeout ]
+
+# Sheriff 2018-07-02
+crbug.com/859605 [ Mac10.10 ] external/wpt/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 84d1894d..8189255 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -52537,6 +52537,30 @@
      {}
     ]
    ],
+   "css/css-scoping/host-specificity-002.html": [
+    [
+     "/css/css-scoping/host-specificity-002.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/host-specificity.html": [
+    [
+     "/css/css-scoping/host-specificity.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/shadow-assign-dynamic-001.html": [
     [
      "/css/css-scoping/shadow-assign-dynamic-001.html",
@@ -52729,6 +52753,18 @@
      {}
     ]
    ],
+   "css/css-scoping/slotted-specificity.html": [
+    [
+     "/css/css-scoping/slotted-specificity.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/slotted-with-pseudo-element.html": [
     [
      "/css/css-scoping/slotted-with-pseudo-element.html",
@@ -111634,6 +111670,11 @@
      {}
     ]
    ],
+   "css/css-color/parsing/resources/parsing-testcommon.js": [
+    [
+     {}
+    ]
+   ],
    "css/css-color/rebeccapurple-ref.html": [
     [
      {}
@@ -188506,6 +188547,12 @@
      {}
     ]
    ],
+   "css/css-break/hit-test-inline-fragmentation-with-border-radius.html": [
+    [
+     "/css/css-break/hit-test-inline-fragmentation-with-border-radius.html",
+     {}
+    ]
+   ],
    "css/css-cascade/all-prop-initial-xml.html": [
     [
      "/css/css-cascade/all-prop-initial-xml.html",
@@ -188556,6 +188603,30 @@
      {}
     ]
    ],
+   "css/css-color/parsing/color-invalid.html": [
+    [
+     "/css/css-color/parsing/color-invalid.html",
+     {}
+    ]
+   ],
+   "css/css-color/parsing/color-valid.html": [
+    [
+     "/css/css-color/parsing/color-valid.html",
+     {}
+    ]
+   ],
+   "css/css-color/parsing/opacity-invalid.html": [
+    [
+     "/css/css-color/parsing/opacity-invalid.html",
+     {}
+    ]
+   ],
+   "css/css-color/parsing/opacity-valid.html": [
+    [
+     "/css/css-color/parsing/opacity-valid.html",
+     {}
+    ]
+   ],
    "css/css-color/rgb-rounding-001.html": [
     [
      "/css/css-color/rgb-rounding-001.html",
@@ -296781,6 +296852,10 @@
    "926ed3f96ba7b5c6dee79ea417746cbd60342579",
    "visual"
   ],
+  "css/css-break/hit-test-inline-fragmentation-with-border-radius.html": [
+   "d0b63d150a77ee6e84c05110fb97cc2befa0e251",
+   "testharness"
+  ],
   "css/css-cascade/META.yml": [
    "d1a7ec7e6b46b861cff2ce11a7f793635a81a0c6",
    "support"
@@ -297101,6 +297176,26 @@
    "fad454c9b86d70e19fb89265c8e131ff381ed2a0",
    "reftest"
   ],
+  "css/css-color/parsing/color-invalid.html": [
+   "a716957996b6441d1bba1d6d4fa636d4368f68c5",
+   "testharness"
+  ],
+  "css/css-color/parsing/color-valid.html": [
+   "462c103850d5880ccecdf4e7a79ac55d28380bf0",
+   "testharness"
+  ],
+  "css/css-color/parsing/opacity-invalid.html": [
+   "7ba8ffc6bbb4c27d43e9e6a11edbe52f8ca21613",
+   "testharness"
+  ],
+  "css/css-color/parsing/opacity-valid.html": [
+   "edf3b52c29261dd0d4993f076ddd01dbe7edb805",
+   "testharness"
+  ],
+  "css/css-color/parsing/resources/parsing-testcommon.js": [
+   "14f32b772f27a9bc75fe90e2ea1d8e4fb3649e95",
+   "support"
+  ],
   "css/css-color/rebeccapurple-ref.html": [
    "e089e2daad5e5db7131015bf45739e64050c6b36",
    "support"
@@ -315869,6 +315964,14 @@
    "918bd04b95a276c6035383f2fe4dcfe4274bceeb",
    "reftest"
   ],
+  "css/css-scoping/host-specificity-002.html": [
+   "0ac361f08fa020664457c457c8c0de308f4f1b68",
+   "reftest"
+  ],
+  "css/css-scoping/host-specificity.html": [
+   "011fe73fba24b6046d73c64b3e99d8cd46501385",
+   "reftest"
+  ],
   "css/css-scoping/keyframes-001.html": [
    "1b72da32df7b17edbd42429d2dc8b791b9f49eff",
    "testharness"
@@ -315973,6 +316076,10 @@
    "263bcbe53e7703a2ea0a7ffae8f9ec4fcb10c7d2",
    "testharness"
   ],
+  "css/css-scoping/slotted-specificity.html": [
+   "db5d7abd272e8ee2270876ab8cba5d86390dec34",
+   "reftest"
+  ],
   "css/css-scoping/slotted-with-pseudo-element-ref.html": [
    "48561a3dff973b7ad1bfa9702461e50fd4a67c2d",
    "support"
@@ -371942,11 +372049,11 @@
    "support"
   ],
   "html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url-expected.txt": [
-   "4283a063a51cfb5bbb02028a79be1df50e704852",
+   "b347c3e1d9ed6a9902ea1d4cd2a7e024777fe8a0",
    "support"
   ],
   "html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html": [
-   "3328350068373e6ad5cfd06f1180468ea4dccfb8",
+   "be7fd0cc365f59413abfd57287675596c8124f80",
    "testharness"
   ],
   "html/semantics/scripting-1/the-script-element/module/import-something-namespace.js": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html b/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.tentative.sub.https.html
similarity index 97%
rename from third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html
rename to third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.tentative.sub.https.html
index 78c7ad0e..43c1fb12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.tentative.sub.https.html
@@ -16,7 +16,7 @@
 // of client hints it receives in the request headers.
 
 promise_test(t => {
-  return fetch("https://{{domains[]}}:{{ports[https][0]}}/client-hints/echo_client_hints_received.py", {"mode": "no-cors"}).then(r => {
+  return fetch("https://{{domains[]}}:{{ports[https][0]}}/client-hints/echo_client_hints_received.py").then(r => {
     assert_equals(r.status, 200)
     // Verify that the browser includes client hints in the headers for a
     // same-origin fetch.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html.headers b/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.tentative.sub.https.html.headers
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html.headers
rename to third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.tentative.sub.https.html.headers
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html
new file mode 100644
index 0000000..2bdced2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html
@@ -0,0 +1,35 @@
+<html>
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
+<title>Accept-CH http-equiv insecure transport test</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+
+// Even though this HTML file contains "Accept-CH" http-equiv headers, the
+// browser should NOT attach the specified client hints in the HTTP request
+// headers since the page is being fetched over an insecure transport.
+// Test this functionality by fetching an XHR from this page hosted on
+// an insecure HTTP server.
+
+// echo_client_hints_received.py sets the response headers depending on the set
+// of client hints it receives in the request headers.
+
+promise_test(t => {
+  return fetch("/client-hints/echo_client_hints_received.py").then(r => {
+    assert_equals(r.status, 200)
+    // Verify that the browser does not include client hints in the headers
+    // when fetching the XHR from an insecure HTTP server.
+    assert_false(r.headers.has("device-memory-received"), "device-memory-received");
+    assert_false(r.headers.has("dpr-received"), "dpr-received");
+    assert_false(r.headers.has("viewport-width-received"), "viewport-width-received");
+    assert_false(r.headers.has("rtt-received"), "rtt-received");
+    assert_false(r.headers.has("downlink-received"), "downlink-received");
+    assert_false(r.headers.has("ect-received"), "ect-received");
+  });
+}, "Accept-CH http-equiv test over insecure transport");
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html
new file mode 100644
index 0000000..3e4d638
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html
@@ -0,0 +1,49 @@
+<html>
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
+<title>Accept-CH http-equiv cross-navigation test</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id=test>
+    <p>Apart from this webpage, the test opens another html web page. One test
+    is run in this web page, and another in the second web page.
+</div>
+
+<script>
+
+// This test contains accept-ch http-equiv header. Due to the missing
+// Accept-CH-Lifetime header, the user-agent should not persist origin
+// preferences for the client hints specified in Accept-CH header.
+
+// Next, to verify that the origin preferences were not persisted by the user
+// agent, this test fetches resources/do_not_expect_client_hints_headers.html
+// in a new window. Fetching of
+// resources/do_not_expect_client_hints_headers.html
+// verifies that the user agent does not send the client hints in the request
+// headers.
+
+// Test is marked as tentative until https://github.com/whatwg/fetch/issues/726
+// is resolved.
+promise_test(t => {
+  return fetch("echo_client_hints_received.py").then(r => {
+    assert_equals(r.status, 200)
+    // Verify that the browser includes client hints in the request
+    // headers when fetching echo_client_hints_received.py within this page.
+    assert_true(r.headers.has("device-memory-received"), "device-memory-received");
+  });
+}, "Test that the browser attaches client hints on subresources in the same navigation");
+
+// Verify that the browser does not attach client hints on resources in a
+// different navigation. This verifies that the client hint preferences were
+// not persisted for the origin.
+window.open("resources/do_not_expect_client_hints_headers.html");
+async_test(t => {
+window.addEventListener('message', function(event) {
+  t.done();
+})
+}, "Loading of resources/do_not_expect_client_hints_headers.html did not finish.");
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
similarity index 78%
copy from third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html
copy to third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
index 78c7ad0e..459b00e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/client-hints/accept_ch.sub.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
@@ -1,22 +1,23 @@
 <html>
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
+<title>Accept-CH http-equiv same-origin and cross-origin test</title>
 <body>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 
 <script>
 
-// If the response for the HTML file contains "Accept-CH" in the response
-// headers, then the browser should attach the specified client hints in the
-// HTTP request headers depending on whether the resource is being fetched from
+// Since this HTML file contains "Accept-CH" http-equiv headers the browser
+// should attach the specified client hints in the HTTP request headers
+// depending on whether the resource is being fetched from
 // the same origin or a different origin. Test this functionality by fetching
-// same-origin and cross-origin resources from this page. The response headers
-// for this page include "Accept-CH: device-memory, dpr, viewport-width, rtt, downlink, ect".
+// same-origin and cross-origin resources from this page.
 //
 // echo_client_hints_received.py sets the response headers depending on the set
 // of client hints it receives in the request headers.
 
 promise_test(t => {
-  return fetch("https://{{domains[]}}:{{ports[https][0]}}/client-hints/echo_client_hints_received.py", {"mode": "no-cors"}).then(r => {
+  return fetch("https://{{domains[]}}:{{ports[https][0]}}/client-hints/echo_client_hints_received.py").then(r => {
     assert_equals(r.status, 200)
     // Verify that the browser includes client hints in the headers for a
     // same-origin fetch.
@@ -38,7 +39,7 @@
     assert_in_array(r.headers.get("ect-received"), ["slow-2g", "2g",
           "3g", "4g"], 'ect-received is unexpected');
   });
-}, "Accept-CH header test");
+}, "Same origin Accept-CH http-equiv test");
 
 promise_test(t => {
   return fetch("https://{{domains[www]}}:{{ports[https][0]}}/client-hints/echo_client_hints_received.py").then(r => {
@@ -52,11 +53,10 @@
     assert_false(r.headers.has("downlink-received"), "downlink-received");
     assert_false(r.headers.has("ect-received"), "ect-received");
   });
-}, "Cross-Origin Accept-CH header test");
+}, "Cross-Origin Accept-CH http-equiv test");
 
 
 
 </script>
-
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch_malformed_header.tentative.https.html b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch_malformed_header.tentative.https.html
new file mode 100644
index 0000000..dd516a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/client-hints/http_equiv_accept_ch_malformed_header.tentative.https.html
@@ -0,0 +1,28 @@
+<html>
+<meta http-equiv="Accept-CH" content="DPR Width">
+<title>Accept-CH malformed http-equiv test</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+
+promise_test(t => {
+  return fetch("/client-hints/echo_client_hints_received.py").then(r => {
+    assert_equals(r.status, 200)
+    // Verify that the browser does not include client hints in the headers
+    // since Accept-CH value in http-equiv is malformed (includes whitespace
+    // between attributes instead of comma).
+    assert_false(r.headers.has("device-memory-received"), "device-memory-received");
+    assert_false(r.headers.has("dpr-received"), "dpr-received");
+    assert_false(r.headers.has("viewport-width-received"), "viewport-width-received");
+    assert_false(r.headers.has("rtt-received"), "rtt-received");
+    assert_false(r.headers.has("downlink-received"), "downlink-received");
+    assert_false(r.headers.has("ect-received"), "ect-received");
+  });
+}, "Accept-CH malformed http-equiv test");
+
+</script>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html
new file mode 100644
index 0000000..b0610b1a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html
@@ -0,0 +1,268 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://www.w3.org/TR/css-break-3/#break-decoration"/>
+<style>
+div {
+  margin: 20px;
+}
+
+span.round {
+  padding: 20px;
+  line-height: 100px;
+  font-size: 40px;
+  border-radius: 40px;
+  background-color: yellow;
+}
+</style>
+
+<div>
+<span id="horizontal" class="round">FOO<br>BAR</span>
+</div>
+
+<div style="writing-mode:vertical-lr">
+<span id="vertical-lr" class="round">FOO<br>BAR</span>
+</div>
+
+<div style="writing-mode:vertical-rl">
+<span id="vertical-rl" class="round">FOO<br>BAR</span>
+</div>
+
+<script>
+// Hit test horizontal span with border radius
+const horizontalSpan = document.getElementById('horizontal');
+const horizontalDiv = horizontalSpan.parentNode;
+const horizontalRects = horizontalSpan.getClientRects();
+const horizontalLine1 = horizontalRects[0];
+const horizontalLine2 = horizontalRects[1];
+
+test(() => {
+  const x = horizontalLine1.left + 1;
+  const y = horizontalLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalDiv);
+}, 'Horizontal line 1, hit test outside top-left rounded corner');
+
+test(() => {
+  const x = horizontalLine1.left + 20;
+  const y = horizontalLine1.top + 20;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 1, hit test inside top-left rounded corner');
+
+test(() => {
+  const x = horizontalLine1.left + 1;
+  const y = horizontalLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalDiv);
+}, 'Horizontal line 1, hit test outside bottom-left rounded corner');
+
+test(() => {
+  const x = horizontalLine1.left + 20;
+  const y = horizontalLine1.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 1, hit test inside bottom-left rounded corner');
+
+test(() => {
+  const x = horizontalLine1.right - 1;
+  const y = horizontalLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 1, hit test inside top-right right-angled corner')
+
+test(() => {
+  const x = horizontalLine1.right - 1;
+  const y = horizontalLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 1, hit test inside bottom-right right-angled corner')
+
+test(() => {
+  const x = horizontalLine2.right - 1;
+  const y = horizontalLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalDiv);
+}, 'Horizontal line 2, hit test outside top-right rounded corner');
+
+test(() => {
+  const x = horizontalLine2.right - 20;
+  const y = horizontalLine2.top + 20;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 2, hit test inside top-right rounded corner');
+
+test(() => {
+  const x = horizontalLine2.right - 1;
+  const y = horizontalLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalDiv);
+}, 'Horizontal line 2, hit test outside bottom-right rounded corner');
+
+test(() => {
+  const x = horizontalLine2.right - 20;
+  const y = horizontalLine2.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 2, hit test inside bottom-right rounded corner');
+
+test(() => {
+  const x = horizontalLine2.left + 1;
+  const y = horizontalLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 2, hit test inside top-left right-angled corner')
+
+test(() => {
+  const x = horizontalLine2.left + 1;
+  const y = horizontalLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), horizontalSpan);
+}, 'Horizontal line 2, hit test inside bottom-left right-angled corner')
+
+// Hit test vertical-lr span with border radius
+const verticalLRSpan = document.getElementById('vertical-lr');
+const verticalLRDiv = verticalLRSpan.parentNode;
+const verticalLRRects = verticalLRSpan.getClientRects();
+const verticalLRLine1 = verticalLRRects[0];
+const verticalLRLine2 = verticalLRRects[1];
+
+test(() => {
+  const x = verticalLRLine1.left + 1;
+  const y = verticalLRLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRDiv);
+}, 'Vertical LR line 1, hit test outside top-left rounded corner');
+
+test(() => {
+  const x = verticalLRLine1.left + 20;
+  const y = verticalLRLine1.top + 20;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 1, hit test inside top-left rounded corner');
+
+test(() => {
+  const x = verticalLRLine1.right - 1;
+  const y = verticalLRLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRDiv);
+}, 'Vertical LR line 1, hit test outside top-right rounded corner');
+
+test(() => {
+  const x = verticalLRLine1.right - 20;
+  const y = verticalLRLine1.top + 20;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 1, hit test inside top-right rounded corner');
+
+test(() => {
+  const x = verticalLRLine1.left + 1;
+  const y = verticalLRLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 1, hit test inside bottom-left right-angled corner')
+
+test(() => {
+  const x = verticalLRLine1.right - 1;
+  const y = verticalLRLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 1, hit test inside bottom-right right-angled corner')
+
+test(() => {
+  const x = verticalLRLine2.left + 1;
+  const y = verticalLRLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRDiv);
+}, 'Vertical LR line 2, hit test outside bottom-left rounded corner');
+
+test(() => {
+  const x = verticalLRLine2.left + 20;
+  const y = verticalLRLine2.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 2, hit test inside bottom-left rounded corner');
+
+test(() => {
+  const x = verticalLRLine2.right - 1;
+  const y = verticalLRLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRDiv);
+}, 'Vertical LR line 2, hit test outside bottom-right rounded corner');
+
+test(() => {
+  const x = verticalLRLine2.right - 20;
+  const y = verticalLRLine2.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 2, hit test inside bottom-right rounded corner');
+
+test(() => {
+  const x = verticalLRLine2.left + 1;
+  const y = verticalLRLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 2, hit test inside top-left right-angled corner')
+
+test(() => {
+  const x = verticalLRLine2.right - 1;
+  const y = verticalLRLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalLRSpan);
+}, 'Vertical LR line 2, hit test inside top-right right-angled corner')
+
+// Hit test vertical-rl span with border radius
+const verticalRLSpan = document.getElementById('vertical-rl');
+const verticalRLDiv = verticalRLSpan.parentNode;
+const verticalRLRects = verticalRLSpan.getClientRects();
+const verticalRLLine1 = verticalRLRects[0].left > verticalRLRects[1].left ? verticalRLRects[0] : verticalRLRects[1];
+const verticalRLLine2 = verticalRLRects[0].left > verticalRLRects[1].left ? verticalRLRects[1] : verticalRLRects[0];
+
+test(() => {
+  const x = verticalRLLine1.left + 1;
+  const y = verticalRLLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLDiv);
+}, 'Vertical RL line 1, hit test outside top-left rounded corner');
+
+test(() => {
+  const x = verticalRLLine1.left + 20;
+  const y = verticalRLLine1.top + 20;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 1, hit test inside top-left rounded corner');
+
+test(() => {
+  const x = verticalRLLine1.right - 1;
+  const y = verticalRLLine1.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLDiv);
+}, 'Vertical RL line 1, hit test outside top-right rounded corner');
+
+test(() => {
+  const x = verticalRLLine1.right - 20;
+  const y = verticalRLLine1.top + 20;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 1, hit test inside top-right rounded corner');
+
+test(() => {
+  const x = verticalRLLine1.left + 1;
+  const y = verticalRLLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 1, hit test inside bottom-left right-angled corner')
+
+test(() => {
+  const x = verticalRLLine1.right - 1;
+  const y = verticalRLLine1.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 1, hit test inside bottom-right right-angled corner')
+
+test(() => {
+  const x = verticalRLLine2.left + 1;
+  const y = verticalRLLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLDiv);
+}, 'Vertical RL line 2, hit test outside bottom-left rounded corner');
+
+test(() => {
+  const x = verticalRLLine2.left + 20;
+  const y = verticalRLLine2.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 2, hit test inside bottom-left rounded corner');
+
+test(() => {
+  const x = verticalRLLine2.right - 1;
+  const y = verticalRLLine2.bottom - 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLDiv);
+}, 'Vertical RL line 2, hit test outside bottom-right rounded corner');
+
+test(() => {
+  const x = verticalRLLine2.right - 20;
+  const y = verticalRLLine2.bottom - 20;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 2, hit test inside bottom-right rounded corner');
+
+test(() => {
+  const x = verticalRLLine2.left + 1;
+  const y = verticalRLLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 2, hit test inside top-left right-angled corner')
+
+test(() => {
+  const x = verticalRLLine2.right - 1;
+  const y = verticalRLLine2.top + 1;
+  assert_equals(document.elementFromPoint(x, y), verticalRLSpan);
+}, 'Vertical RL line 2, hit test inside top-right right-angled corner')
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-invalid.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-invalid.html
new file mode 100644
index 0000000..978eb89
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-invalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Color Module Level 3: parsing color with invalid values</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-color-3/#color0">
+<meta name="assert" content="color supports only the grammar '<color>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("color", "auto");
+test_invalid_value("color", "123");
+test_invalid_value("color", "#12");
+test_invalid_value("color", "#123456789");
+test_invalid_value("color", "rgb");
+test_invalid_value("color", "rgb(1)");
+test_invalid_value("color", "rgb(1,2,3,4,5)");
+test_invalid_value("color", "hsla(1,2,3,4,5)");
+test_invalid_value("color", "rgb(10%, 20, 30%)");
+test_invalid_value("color", "rgba(-2, 300, 400%, -0.5)");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-valid.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-valid.html
new file mode 100644
index 0000000..76e84847
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/color-valid.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Color Module Level 3: parsing color with valid values</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-color-3/#color0">
+<meta name="assert" content="color supports the full grammar '<color>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("color", "currentcolor"); // Edge serializes as currentColor.
+test_valid_value("color", "transparent");
+test_valid_value("color", "red");
+test_valid_value("color", "magenta");
+test_valid_value("color", "#234", "rgb(34, 51, 68)");
+test_valid_value("color", "#FEDCBA", "rgb(254, 220, 186)");
+test_valid_value("color", "rgb(2, 3, 4)");
+test_valid_value("color", "rgb(100%, 0%, 0%)", "rgb(255, 0, 0)");
+test_valid_value("color", "rgba(2, 3, 4, 0.5)"); // Safari serializes alpha-value 0.498039
+test_valid_value("color", "hsl(120, 100%, 50%)", ["rgb(0, 255, 0)", "hsl(120, 100%, 50%)"]);
+test_valid_value("color", "hsla(120, 100%, 50%, 0.25)", ["rgba(0, 255, 0, 0.25)", "hsla(120, 100%, 50%, 0.25)"]); // Safari serializes alpha-value 0.247059
+test_valid_value("color", "rgb(-2, 3, 4)", "rgb(0, 3, 4)");
+test_valid_value("color", "rgb(100, 200, 300)", "rgb(100, 200, 255)");
+test_valid_value("color", "rgb(20, 10, 0, -10)", "rgba(20, 10, 0, 0)"); // Not supported by Edge/Safari.
+test_valid_value("color", "rgb(100%, 200%, 300%)", "rgb(255, 255, 255)");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-invalid.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-invalid.html
new file mode 100644
index 0000000..955903f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-invalid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS opacity Module Level 3: parsing opacity with invalid values</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-color-3/#opacity">
+<meta name="assert" content="opacity supports only the grammar '<alphavalue>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("opacity", "auto");
+test_invalid_value("opacity", "10px");
+test_invalid_value("opacity", "0 1");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-valid.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-valid.html
new file mode 100644
index 0000000..738c3d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/opacity-valid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS opacity Module Level 3: parsing opacity with valid values</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-color-3/#opacity">
+<meta name="assert" content="opacity supports the full grammar '<alphavalue>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("opacity", "1");
+test_valid_value("opacity", "0.5");
+test_valid_value("opacity", "0");
+test_valid_value("opacity", "-2");
+test_valid_value("opacity", "3");
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/resources/parsing-testcommon.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/resources/parsing-testcommon.js
new file mode 100644
index 0000000..b075882
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-color/parsing/resources/parsing-testcommon.js
@@ -0,0 +1,39 @@
+'use strict';
+
+// serializedValue can be the expected serialization of value,
+// or an array of permitted serializations,
+// or omitted if value should serialize as value.
+function test_valid_value(property, value, serializedValue) {
+    if (arguments.length < 3)
+        serializedValue = value;
+
+    var stringifiedValue = JSON.stringify(value);
+
+    test(function(){
+        var div = document.createElement('div');
+        div.style[property] = value;
+        assert_not_equals(div.style.getPropertyValue(property), "", "property should be set");
+
+        var div = document.createElement('div');
+        div.style[property] = value;
+        var readValue = div.style.getPropertyValue(property);
+        if (serializedValue instanceof Array)
+            assert_in_array(readValue, serializedValue, "serialization should be sound");
+        else
+            assert_equals(readValue, serializedValue, "serialization should be canonical");
+
+        div.style[property] = readValue;
+        assert_equals(div.style.getPropertyValue(property), readValue, "serialization should round-trip");
+
+    }, "e.style['" + property + "'] = " + stringifiedValue + " should set the property value");
+}
+
+function test_invalid_value(property, value) {
+    var stringifiedValue = JSON.stringify(value);
+
+    test(function(){
+        var div = document.createElement('div');
+        div.style[property] = value;
+        assert_equals(div.style.getPropertyValue(property), "");
+    }, "e.style['" + property + "'] = " + stringifiedValue + " should not set the property value");
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity-002.html
new file mode 100644
index 0000000..3132d3a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity-002.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: :host is accounted for during specificity computation</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#host-selector">
+<link rel="help" href="https://drafts.csswg.org/selectors/#specificity-rules">
+<link rel="help" href="https://bugzil.la/1454165">
+<link rel="match" href="reference/green-box.html">
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host"></div>
+<script>
+  host.attachShadow({ mode: 'open' }).innerHTML = `
+    <style>
+      .foo span {
+        display: block;
+        width: 100px;
+        height: 100px;
+        background: red;
+      }
+      :host span {
+        background: green;
+      }
+    </style>
+    <div class="foo"><span></span></div>
+  `;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity.html
new file mode 100644
index 0000000..3ef61d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/host-specificity.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: the selector inside :host() affects specificity</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#host-selector">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1915">
+<link rel="help" href="https://bugzil.la/1454165">
+<link rel="match" href="reference/green-box.html">
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host"></div>
+<script>
+  host.attachShadow({ mode: 'open' }).innerHTML = `
+    <style>
+      :host(#host) {
+        width: 100px;
+        height: 100px;
+        background: green;
+      }
+      :host {
+        background: red;
+      }
+    </style>
+    <slot></slot>
+  `;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/slotted-specificity.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/slotted-specificity.html
new file mode 100644
index 0000000..d049182
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/slotted-specificity.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: the selector inside ::slotted() affects specificity</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#slotted-pseudo">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1915">
+<link rel="help" href="https://bugzil.la/1454165">
+<link rel="match" href="reference/green-box.html">
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host"><div id="slotted"></div></div>
+<script>
+  host.attachShadow({ mode: 'open' }).innerHTML = `
+    <style>
+      ::slotted(#slotted) {
+        width: 100px;
+        height: 100px;
+        background: green;
+      }
+      ::slotted(*) {
+        background: red;
+      }
+    </style>
+    <slot></slot>
+  `;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url-expected.txt
index 4c25322..091a0ca 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url-expected.txt
@@ -2,6 +2,9 @@
 PASS import.meta.url in a root inline script
 PASS import.meta.url in a root external script
 PASS import.meta.url in a dependent external script
+PASS import.meta is an object
+PASS import.meta is extensible
+PASS import.meta's properties are writable, configurable, and enumerable
 FAIL import.meta.url when importing the module with different fragments assert_equals: expected "http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-root.js#1" but got "http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-root.js"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
index fa1c7dee..79f08eba 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
@@ -21,6 +21,27 @@
                 base + "/import-meta-dependent.js");
 }, "import.meta.url in a dependent external script");
 
+test(() => {
+  assert_equals(typeof importMetaOnRootModule, "object");
+  assert_not_equals(importMetaOnRootModule, null);
+}, "import.meta is an object");
+
+test(() => {
+  importMetaOnRootModule.newProperty = 1;
+  assert_true(Object.isExtensible(importMetaOnRootModule));
+}, "import.meta is extensible");
+
+test(() => {
+  let names = new Set(Reflect.ownKeys(importMetaOnRootModule));
+  for (name of names) {
+    var desc = Object.getOwnPropertyDescriptor(importMetaOnRootModule, name);
+    assert_equals(desc.writable, true);
+    assert_equals(desc.enumerable, true);
+    assert_equals(desc.configurable, true);
+  }
+}, "import.meta's properties are writable, configurable, and enumerable");
+
+
 import { importMetaOnRootModule as hashedImportMetaOnRootModule1,
          importMetaOnDependentModule as hashedImportMetaOnDependentModule1 }
        from "./import-meta-root.js#1";
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt
index 87812d6..cb26c6d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 213 tests; 139 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 213 tests; 140 PASS, 73 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Simplest possible test ("<div>abc")
 PASS Leading whitespace removed ("<div> abc")
 PASS Trailing whitespace removed ("<div>abc ")
@@ -202,7 +202,7 @@
 PASS innerText not supported on MathML elements ("<math>abc")
 PASS <rt> and no <rp> ("<div><ruby>abc<rt>def</rt></ruby>")
 PASS <rp> ("<div><ruby>abc<rp>(</rp><rt>def</rt><rp>)</rp></ruby>")
-FAIL Lone <rp> ("<div><rp>abc</rp>") assert_equals: expected "" but got "abc"
+PASS Lone <rp> ("<div><rp>abc</rp>")
 PASS visibility:hidden <rp> ("<div><rp style='visibility:hidden'>abc</rp>")
 PASS display:block <rp> ("<div><rp style='display:block'>abc</rp>def")
 PASS display:block <rp> with whitespace ("<div><rp style='display:block'> abc </rp>def")
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
new file mode 100644
index 0000000..475ca2d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -0,0 +1,44 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='outer'",
+      "position": [50, 50],
+      "bounds": [300, 300]
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='content'",
+      "bounds": [285, 1000],
+      "contentsOpaque": true,
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [50, 50, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/shadow-dom/untriaged/events/retargeting-focus-events/test-002-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/shadow-dom/untriaged/events/retargeting-focus-events/test-002-expected.txt
deleted file mode 100644
index 02f3a06..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/external/wpt/shadow-dom/untriaged/events/retargeting-focus-events/test-002-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A_05_03_02_T01 assert_true: Event listener was not invoked expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 66b2905b..a2ce21b 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -8858,6 +8858,19 @@
 interface WebGLVertexArrayObject
     attribute @@toStringTag
     method constructor
+interface WebGPU
+    attribute @@toStringTag
+    method constructor
+    method getAdapter
+interface WebGPUAdapter
+    attribute @@toStringTag
+    getter name
+    method constructor
+    method createDevice
+interface WebGPUDevice
+    attribute @@toStringTag
+    getter adapter
+    method constructor
 interface WebKitAnimationEvent : Event
     attribute @@toStringTag
     getter animationName
@@ -9555,6 +9568,7 @@
     getter styleMedia
     getter toolbar
     getter visualViewport
+    getter webgpu
     getter webkitStorageInfo
     method NodeFilter
     method alert
@@ -9736,6 +9750,7 @@
     setter statusbar
     setter toolbar
     setter visualViewport
+    setter webgpu
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h
index be88239..79ed940 100644
--- a/third_party/blink/public/platform/web_url_response.h
+++ b/third_party/blink/public/platform/web_url_response.h
@@ -305,15 +305,13 @@
 #endif
 
  private:
-  struct ResourceResponseContainer;
-
   // If this instance owns a ResourceResponse then |owned_resource_response_|
   // is non-null and |resource_response_| points to the ResourceResponse
   // instance it contains.
-  std::unique_ptr<ResourceResponseContainer> owned_resource_response_;
+  const std::unique_ptr<ResourceResponse> owned_resource_response_;
 
   // Should never be null.
-  ResourceResponse* resource_response_;
+  ResourceResponse* const resource_response_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
index 756991ff..9f28d3ad 100644
--- a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
+++ b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
@@ -22,6 +22,7 @@
     'Uint16',
     'Uint32',
     'WebGL2',
+    'WebGPU',
     'ASCII',
     'CSSOM',
     'CType',
diff --git a/third_party/blink/renderer/core/css/document_style_environment_variables.cc b/third_party/blink/renderer/core/css/document_style_environment_variables.cc
index 20cca093..dbb6dfae 100644
--- a/third_party/blink/renderer/core/css/document_style_environment_variables.cc
+++ b/third_party/blink/renderer/core/css/document_style_environment_variables.cc
@@ -42,15 +42,22 @@
 }
 
 CSSVariableData* DocumentStyleEnvironmentVariables::ResolveVariable(
-    const AtomicString& name) {
+    const AtomicString& name,
+    bool record_metrics) {
   unsigned id = GenerateHashFromName(name);
-  RecordVariableUsage(id);
+  if (record_metrics)
+    RecordVariableUsage(id);
 
   // Mark the variable as seen so we will invalidate the style if we change it.
   seen_variables_.insert(id);
   return StyleEnvironmentVariables::ResolveVariable(name);
 }
 
+CSSVariableData* DocumentStyleEnvironmentVariables::ResolveVariable(
+    const AtomicString& name) {
+  return ResolveVariable(name, true /* record_metrics */);
+}
+
 void DocumentStyleEnvironmentVariables::InvalidateVariable(
     const AtomicString& name) {
   DCHECK(document_);
diff --git a/third_party/blink/renderer/core/css/document_style_environment_variables.h b/third_party/blink/renderer/core/css/document_style_environment_variables.h
index 165121b..032f5f1 100644
--- a/third_party/blink/renderer/core/css/document_style_environment_variables.h
+++ b/third_party/blink/renderer/core/css/document_style_environment_variables.h
@@ -28,7 +28,14 @@
 
   // Resolve the variable |name| and return the data. This will also cause
   // future changes to this variable to invalidate the associated document's
-  // style.
+  // style. If |record_metrics| is true we will record UseCounter metrics when
+  // this function is called.
+  CSSVariableData* ResolveVariable(const AtomicString& name,
+                                   bool record_metrics);
+
+  // Resolve the variable |name| and return the data. This will also cause
+  // future changes to this variable to invalidate the associated document's
+  // style. UseCounter metrics will be recorded when this function is used.
   CSSVariableData* ResolveVariable(const AtomicString& name) override;
 
  protected:
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
index e000027..5074fd9 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
@@ -21,6 +21,7 @@
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/css_property_names.h"
 #include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/style_inherited_variables.h"
 #include "third_party/blink/renderer/core/style/style_non_inherited_variables.h"
@@ -240,10 +241,15 @@
 
 CSSVariableData* CSSVariableResolver::ValueForEnvironmentVariable(
     const AtomicString& name) {
+  // If we are in a User Agent Shadow DOM then we should not record metrics.
+  ContainerNode& scope_root = state_.GetTreeScope().RootNode();
+  bool is_ua_scope =
+      scope_root.IsShadowRoot() && ToShadowRoot(scope_root).IsUserAgent();
+
   return state_.GetDocument()
       .GetStyleEngine()
       .EnsureEnvironmentVariables()
-      .ResolveVariable(name);
+      .ResolveVariable(name, !is_ua_scope);
 }
 
 bool CSSVariableResolver::ResolveTokenRange(
diff --git a/third_party/blink/renderer/core/css/style_environment_variables_test.cc b/third_party/blink/renderer/core/css/style_environment_variables_test.cc
index 881481d..a4fb69a 100644
--- a/third_party/blink/renderer/core/css/style_environment_variables_test.cc
+++ b/third_party/blink/renderer/core/css/style_environment_variables_test.cc
@@ -39,6 +39,9 @@
     PageTestBase::SetUp();
 
     RuntimeEnabledFeatures::SetCSSEnvironmentVariablesEnabled(true);
+
+    // Needed for RecordUseCounter_IgnoreMediaControls.
+    RuntimeEnabledFeatures::SetModernMediaControlsEnabled(true);
   }
 
   void TearDown() override {
@@ -337,6 +340,21 @@
   }
 }
 
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_IgnoreMediaControls) {
+  InitializeWithHTML(GetFrame(), "<video controls />");
+
+  EXPECT_FALSE(UseCounter::IsCounted(GetDocument(),
+                                     WebFeature::kCSSEnvironmentVariable));
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetTop));
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetLeft));
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetBottom));
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetRight));
+}
+
 TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_InvalidProperty) {
   InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 4360c9e..e1f2f96f 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2694,32 +2694,29 @@
   if (!layer || layer->Client().ShouldThrottleRendering())
     return;
 
-  scoped_refptr<cc::Layer> contents_layer = layer->ContentsLayer();
-  if (layer->DrawsContent() || contents_layer) {
+  if (layer->DrawsContent()) {
     ScopedPaintChunkProperties scope(context.GetPaintController(),
                                      layer->GetPropertyTreeState(), *layer,
                                      DisplayItem::kForeignLayerWrapper);
+    // TODO(trchen): Currently the GraphicsLayer hierarchy is still built
+    // during CompositingUpdate, and we have to clear them here to ensure no
+    // extraneous layers are still attached. In future we will disable all
+    // those layer hierarchy code so we won't need this line.
+    layer->CcLayer()->RemoveAllChildren();
+    RecordForeignLayer(context, *layer, DisplayItem::kForeignLayerWrapper,
+                       layer->CcLayer(), layer->GetOffsetFromTransformNode(),
+                       layer->Size());
+  }
 
-    if (layer->DrawsContent()) {
-      // TODO(trchen): Currently the GraphicsLayer hierarchy is still built
-      // during CompositingUpdate, and we have to clear them here to ensure no
-      // extraneous layers are still attached. In future we will disable all
-      // those layer hierarchy code so we won't need this line.
-      layer->CcLayer()->RemoveAllChildren();
-      RecordForeignLayer(context, *layer, DisplayItem::kForeignLayerWrapper,
-                         layer->CcLayer(), layer->GetOffsetFromTransformNode(),
-                         layer->Size());
-    }
-    if (contents_layer) {
-      auto position = contents_layer->position();
-      auto size = contents_layer->bounds();
-      RecordForeignLayer(context, *layer,
-                         DisplayItem::kForeignLayerContentsWrapper,
-                         std::move(contents_layer),
-                         layer->GetOffsetFromTransformNode() +
-                             FloatSize(position.x(), position.y()),
-                         IntSize(size.width(), size.height()));
-    }
+  if (scoped_refptr<cc::Layer> contents_layer = layer->ContentsLayer()) {
+    ScopedPaintChunkProperties scope(
+        context.GetPaintController(), layer->GetContentsPropertyTreeState(),
+        *layer, DisplayItem::kForeignLayerContentsWrapper);
+    auto size = contents_layer->bounds();
+    RecordForeignLayer(
+        context, *layer, DisplayItem::kForeignLayerContentsWrapper,
+        std::move(contents_layer), layer->GetContentsOffsetFromTransformNode(),
+        IntSize(size.width(), size.height()));
   }
 
   DCHECK(!layer->ContentsClippingMaskLayer());
@@ -3824,6 +3821,16 @@
       });
 }
 
+void LocalFrameView::SetSelfVisible(bool visible) {
+  if (visible != self_visible_) {
+    // Frame view visibility affects PLC::CanBeComposited, which in turn
+    // affects compositing inputs.
+    if (LayoutView* view = GetLayoutView())
+      view->Layer()->SetNeedsCompositingInputsUpdate();
+  }
+  self_visible_ = visible;
+}
+
 void LocalFrameView::Show() {
   if (!IsSelfVisible()) {
     SetSelfVisible(true);
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index c55b3a2..e77966e 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -421,7 +421,7 @@
     return self_visible_ && parent_visible_;
   }  // Whether or not we are actually visible.
   void SetParentVisible(bool) override;
-  void SetSelfVisible(bool v) { self_visible_ = v; }
+  void SetSelfVisible(bool);
   void AttachToLayout() override;
   void DetachFromLayout() override;
   bool IsAttached() const override { return is_attached_; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 340e12fb94..8b061ad 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -40,11 +40,14 @@
 
   default_containing_block_.style = &container_style;
   default_containing_block_.content_size = container_builder_->Size();
-  default_containing_block_.content_size.inline_size -=
-      borders_and_scrollers.InlineSum();
-  default_containing_block_.content_size.block_size -=
-      borders_and_scrollers.BlockSum();
-
+  default_containing_block_.content_size.inline_size =
+      std::max(default_containing_block_.content_size.inline_size -
+                   borders_and_scrollers.InlineSum(),
+               LayoutUnit());
+  default_containing_block_.content_size.block_size =
+      std::max(default_containing_block_.content_size.block_size -
+                   borders_and_scrollers.BlockSum(),
+               LayoutUnit());
   default_containing_block_.content_offset = NGLogicalOffset{
       borders_and_scrollers.inline_start, borders_and_scrollers.block_start};
   default_containing_block_.content_physical_offset =
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
index 53fcf3e..40e428e 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -190,6 +190,9 @@
         info.needs_reparent_scroll_for_fixed = false;
   }
 
+  PaintLayerCompositor* compositor =
+      layer->GetLayoutObject().View()->Compositor();
+
   // The sequence of updates to compositing triggers goes like this:
   // 1. Apply all triggers from kComboAllDirectNonStyleDeterminedReasons for
   //    |layer|. This may depend on ancestor composited scrolling (i.e. step
@@ -212,7 +215,7 @@
 
   if (layer->GetScrollableArea()) {
     layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(
-        layer->GetLayoutObject().View()->Compositor()->CanBeComposited(layer) &&
+        compositor->CanBeComposited(layer) &&
         layer->DirectCompositingReasons());
     layer->GetScrollableArea()->SetHasPaintLayerScrollChild(false);
   }
@@ -228,7 +231,9 @@
       UpdateRecursive(child, update_type, info);
     descendant_has_direct_compositing_reason |=
         child->DescendantHasDirectOrScrollingCompositingReason() ||
-        child->DirectCompositingReasons() || child->NeedsCompositedScrolling();
+        child->NeedsCompositedScrolling() ||
+        (compositor->CanBeComposited(child) &&
+         child->DirectCompositingReasons());
   }
   layer->SetDescendantHasDirectOrScrollingCompositingReason(
       descendant_has_direct_compositing_reason);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
index 7af3911..d27606af 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
@@ -125,6 +125,15 @@
     SetContainerLayerState(mapping->ForegroundLayer());
   }
 
+  auto* main_graphics_layer = mapping->MainGraphicsLayer();
+  if (const auto* contents_layer = main_graphics_layer->ContentsLayer()) {
+    auto position = contents_layer->position();
+    main_graphics_layer->SetContentsLayerState(
+        fragment_data.ContentsProperties(),
+        snapped_paint_offset + main_graphics_layer->OffsetFromLayoutObject() +
+            IntSize(position.x(), position.y()));
+  }
+
   if (auto* squashing_layer = mapping->SquashingLayer()) {
     auto state = fragment_data.PreEffectProperties();
     // The squashing layer's ClippingContainer is the common ancestor of clip
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
index fcb17c4..d4a5d96 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -248,7 +248,8 @@
       kNegativeZOrderChildren | kNormalFlowChildren | kPositiveZOrderChildren);
   while (PaintLayer* cur_layer = iterator.Next()) {
     DCHECK(cur_layer->GetCompositingState() == kNotComposited);
-    DCHECK(!cur_layer->DirectCompositingReasons());
+    DCHECK(!cur_layer->DirectCompositingReasons() ||
+           !layer->Compositor()->CanBeComposited(cur_layer));
     CheckSubtreeHasNoCompositing(cur_layer);
   }
 }
@@ -287,8 +288,11 @@
       !current_recursion_data.compositing_ancestor_->IsRootLayer();
   const bool ignore_lcd_text = has_non_root_composited_scrolling_ancestor;
 
-  CompositingReasons direct_from_paint_layer =
-      layer->DirectCompositingReasons();
+  const bool layer_can_be_composited = compositor->CanBeComposited(layer);
+
+  CompositingReasons direct_from_paint_layer = 0;
+  if (layer_can_be_composited)
+    direct_from_paint_layer = layer->DirectCompositingReasons();
 
   if (compositing_reason_finder_.RequiresCompositingForScrollDependentPosition(
           layer,
@@ -296,14 +300,18 @@
     direct_from_paint_layer |= CompositingReason::kScrollDependentPosition;
   }
 
-  DCHECK(
-      direct_from_paint_layer ==
-      compositing_reason_finder_.DirectReasons(
-          layer, ignore_lcd_text || moves_with_respect_to_compositing_ancestor))
-      << " Expected: "
-      << CompositingReason::ToString(
-             compositing_reason_finder_.DirectReasons(layer, ignore_lcd_text))
-      << " Actual: " << CompositingReason::ToString(direct_from_paint_layer);
+#if DCHECK_IS_ON()
+  if (layer_can_be_composited) {
+    DCHECK(direct_from_paint_layer ==
+           compositing_reason_finder_.DirectReasons(
+               layer,
+               ignore_lcd_text || moves_with_respect_to_compositing_ancestor))
+        << " Expected: "
+        << CompositingReason::ToString(
+               compositing_reason_finder_.DirectReasons(layer, ignore_lcd_text))
+        << " Actual: " << CompositingReason::ToString(direct_from_paint_layer);
+  }
+#endif
 
   direct_reasons |= direct_from_paint_layer;
 
@@ -320,7 +328,8 @@
   // testing is not used, we must assume we overlap if there is anything
   // composited behind us in paint-order.
   CompositingReasons overlap_compositing_reason =
-      current_recursion_data.subtree_is_compositing_
+      (layer_can_be_composited &&
+       current_recursion_data.subtree_is_compositing_)
           ? CompositingReason::kAssumedOverlap
           : CompositingReason::kNone;
 
@@ -337,7 +346,8 @@
         unclipped_descendants_to_remove.push_back(i);
         continue;
       }
-      if (layer->ScrollsWithRespectTo(unclipped_descendant))
+      if (layer_can_be_composited &&
+          layer->ScrollsWithRespectTo(unclipped_descendant))
         reasons_to_composite |= CompositingReason::kAssumedOverlap;
     }
 
@@ -372,7 +382,7 @@
   }
 
   absolute_descendant_bounding_box = abs_bounds;
-  if (current_recursion_data.testing_overlap_ &&
+  if (layer_can_be_composited && current_recursion_data.testing_overlap_ &&
       !RequiresCompositingOrSquashing(direct_reasons)) {
     bool overlaps =
         overlap_map.OverlapsLayers(abs_bounds, use_clipped_bounding_rect);
@@ -573,7 +583,8 @@
             compositing_reason_finder_, layer,
             child_recursion_data.subtree_is_compositing_,
             any_descendant_has3d_transform);
-    reasons_to_composite |= subtree_compositing_reasons;
+    if (layer_can_be_composited)
+      reasons_to_composite |= subtree_compositing_reasons;
     if (!will_be_composited_or_squashed && can_be_composited &&
         RequiresCompositingOrSquashing(subtree_compositing_reasons)) {
       child_recursion_data.compositing_ancestor_ = layer;
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index b0398c0..8ad4a737 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -47,4 +47,86 @@
   EXPECT_EQ(CompositingReason::kNone, fixed->Layer()->GetCompositingReasons());
 }
 
+TEST_F(CompositingRequirementsUpdaterTest,
+       NoOverlapReasonForNonSelfPaintingLayer) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+       overflow: auto;
+       width: 100px;
+       height: 100px;
+       margin-top: -50px;
+     }
+    </style>
+    <div style="position: relative; width: 500px; height: 300px;
+        will-change: transform"></div>
+    <div id=target></div>
+  )HTML");
+
+  PaintLayer* target =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+  EXPECT_FALSE(target->GetCompositingReasons());
+
+  // Now make |target| self-painting.
+  GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+                                                       "position: relative");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  EXPECT_EQ(CompositingReason::kOverlap, target->GetCompositingReasons());
+}
+
+TEST_F(CompositingRequirementsUpdaterTest,
+       NoAssumedOverlapReasonForNonSelfPaintingLayer) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+       overflow: auto;
+       width: 100px;
+       height: 100px;
+     }
+    </style>
+    <div style="position: relative; width: 500px; height: 300px;
+        transform: translateZ(0)"></div>
+    <div id=target></div>
+  )HTML");
+
+  PaintLayer* target =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+  EXPECT_FALSE(target->GetCompositingReasons());
+
+  // Now make |target| self-painting.
+  GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+                                                       "position: relative");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+  EXPECT_EQ(CompositingReason::kAssumedOverlap,
+            target->GetCompositingReasons());
+}
+
+TEST_F(CompositingRequirementsUpdaterTest,
+       NoDescendantReasonForNonSelfPaintingLayer) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+        overflow: auto;
+        width: 100px;
+        height: 100px;
+      }
+    </style>
+    <div id=target>
+      <div style="backface-visibility: hidden"></div>
+    </div>
+  )HTML");
+
+  PaintLayer* target =
+      ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+  EXPECT_FALSE(target->GetCompositingReasons());
+
+  // Now make |target| self-painting.
+  GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+                                                       "position: relative");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+  EXPECT_EQ(CompositingReason::kClipsCompositingDescendants,
+            target->GetCompositingReasons());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/inline_text_box_painter.cc b/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
index bf8ca7a..cf03d6f 100644
--- a/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
+++ b/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
@@ -127,16 +127,11 @@
       (inline_text_box_.IsHorizontal() ? paint_offset.X() : paint_offset.Y());
   LayoutUnit logical_extent = logical_visual_overflow.Width();
 
-  // We round the y-axis to ensure consistent line heights.
-  LayoutPoint adjusted_paint_offset(paint_offset);
-
   if (inline_text_box_.IsHorizontal()) {
-    adjusted_paint_offset.SetY(LayoutUnit(adjusted_paint_offset.Y().Round()));
     if (!paint_info.GetCullRect().IntersectsHorizontalRange(
             logical_start, logical_start + logical_extent))
       return;
   } else {
-    adjusted_paint_offset.SetX(LayoutUnit(adjusted_paint_offset.X().Round()));
     if (!paint_info.GetCullRect().IntersectsVerticalRange(
             logical_start, logical_start + logical_extent))
       return;
@@ -173,6 +168,7 @@
 
   LayoutPoint box_origin(inline_text_box_.PhysicalLocation() + paint_offset);
 
+  // We round the y-axis to ensure consistent line heights.
   if (inline_text_box_.IsHorizontal()) {
     box_origin.SetY(LayoutUnit(box_origin.Y().Round()));
   } else {
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index a85dd15..620f511 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -29,7 +29,6 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
-#include "cc/layers/layer.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/paint/display_item_list.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -87,9 +86,7 @@
   DCHECK(node_);
   DCHECK(owning_web_view);
   content_layer_ = cc::PictureLayer::Create(this);
-  clip_layer_ = cc::Layer::Create();
-  clip_layer_->SetTransformOrigin(FloatPoint3D());
-  clip_layer_->AddChild(content_layer_);
+  content_layer_->SetTransformOrigin(FloatPoint3D());
 
   compositor_animation_ = CompositorAnimation::Create();
   DCHECK(compositor_animation_);
@@ -118,14 +115,6 @@
   ReleaseResources();
 }
 
-cc::PictureLayer* LinkHighlightImpl::ContentLayer() {
-  return content_layer_.get();
-}
-
-cc::Layer* LinkHighlightImpl::ClipLayer() {
-  return clip_layer_.get();
-}
-
 void LinkHighlightImpl::ReleaseResources() {
   node_.Clear();
 }
@@ -144,8 +133,6 @@
   if (!new_graphics_layer)
     return;
 
-  clip_layer_->SetTransform(gfx::Transform());
-
   if (current_graphics_layer_ != new_graphics_layer) {
     if (current_graphics_layer_)
       ClearGraphicsLayerLinkHighlightPointer();
@@ -408,7 +395,7 @@
 }
 
 cc::Layer* LinkHighlightImpl::Layer() {
-  return ClipLayer();
+  return content_layer_.get();
 }
 
 CompositorAnimation* LinkHighlightImpl::GetCompositorAnimation() const {
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.h b/third_party/blink/renderer/core/paint/link_highlight_impl.h
index 116aef5..9c4a76d8f 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.h
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.h
@@ -60,8 +60,6 @@
   static std::unique_ptr<LinkHighlightImpl> Create(Node*, WebViewImpl*);
   ~LinkHighlightImpl() override;
 
-  cc::PictureLayer* ContentLayer();
-  cc::Layer* ClipLayer();
   void StartHighlightAnimationIfNeeded();
   void UpdateGeometry();
 
@@ -103,7 +101,6 @@
   bool ComputeHighlightLayerPathAndPosition(const LayoutBoxModelObject&);
 
   scoped_refptr<cc::PictureLayer> content_layer_;
-  scoped_refptr<cc::Layer> clip_layer_;
   Path path_;
 
   Persistent<Node> node_;
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index e5b9130..b24337a 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -105,8 +105,7 @@
       GetTargetedEvent(web_view_impl, touch_event));
 
   EXPECT_TRUE(web_view_impl->GetLinkHighlight(0));
-  EXPECT_TRUE(web_view_impl->GetLinkHighlight(0)->ContentLayer());
-  EXPECT_TRUE(web_view_impl->GetLinkHighlight(0)->ClipLayer());
+  EXPECT_TRUE(web_view_impl->GetLinkHighlight(0)->Layer());
 
   // Find a target inside a scrollable div
   touch_event.SetPositionInWidget(WebFloatPoint(20, 100));
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index cfe8033..977c07e6 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -54,25 +54,6 @@
   return !ToLayoutTableCell(object).Table()->ShouldCollapseBorders();
 }
 
-// In hit testing, legacy and NG assumes different semantics for the
-// |accumulated_offset| parameter:
-// - Legacy: offset of the containing block of |child| (excluding |child| when
-// it is block by itslef) in the paint layer.
-// - NG: offset of the fragment itself in the paint layer
-// This function converts the NG offset to legacy so that hit testing can fall
-// back to legacy with the correct |accumulated_offset|.
-LayoutPoint FallbackAccumulatedOffset(const NGPaintFragment& child,
-                                      const LayoutPoint& accumulated_offset) {
-  DCHECK(child.Parent());
-  const NGPaintFragment& parent = *child.Parent();
-  if (parent.PhysicalFragment().IsBlockFlow()) {
-    return accumulated_offset -
-           LayoutSize(child.Offset().left, child.Offset().top);
-  }
-  const NGPhysicalOffset inline_offset = child.InlineOffsetToContainerBox();
-  return accumulated_offset - LayoutSize(inline_offset.left, inline_offset.top);
-}
-
 bool FragmentVisibleToHitTestRequest(const NGPaintFragment& fragment,
                                      const HitTestRequest& request) {
   return fragment.Style().Visibility() == EVisibility::kVisible &&
@@ -92,8 +73,10 @@
   DCHECK(fragment.Parent());
   DCHECK(fragment.PhysicalFragment().IsInline());
   const NGPaintFragment& parent = *fragment.Parent();
+  // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline,
+  // where it equals the physical offset of the containing block in paint layer.
   const LayoutPoint fallback_accumulated_offset =
-      FallbackAccumulatedOffset(fragment, physical_offset);
+      physical_offset - fragment.InlineOffsetToContainerBox().ToLayoutSize();
   const LayoutObject* limit_layout_object =
       parent.PhysicalFragment().IsLineBox() ? parent.Parent()->GetLayoutObject()
                                             : parent.GetLayoutObject();
@@ -1079,8 +1062,12 @@
         // atomically, as if it created its own stacking context. (See Appendix
         // E.2, section 7.4 on inline block/table elements in CSS2.2 spec)
         bool should_hit_test_all_phases = fragment.IsAtomicInline();
+        // To be passed as |accumulated_offset| to legacy hit test functions of
+        // LayoutBox or subclass overrides, where it isn't in any well-defined
+        // coordinate space, but only equals the difference below.
         LayoutPoint fallback_accumulated_offset =
-            FallbackAccumulatedOffset(*child, child_physical_offset);
+            child_physical_offset -
+            ToLayoutSize(ToLayoutBox(fragment.GetLayoutObject())->Location());
         if (should_hit_test_all_phases) {
           stop_hit_testing = fragment.GetLayoutObject()->HitTestAllPhases(
               result, location_in_container, fallback_accumulated_offset);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc
index 0a4aab2..c66b7c1 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -233,7 +233,6 @@
   if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
     return;
 
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='scroll' style='width: 100px; height: 100px; overflow: scroll;
         will-change: transform'>
@@ -486,7 +485,6 @@
 }
 
 TEST_P(PaintLayerTest, HasVisibleDescendant) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='invisible' style='position:relative'>
       <div id='visible' style='visibility: visible; position: relative'>
@@ -504,7 +502,6 @@
 }
 
 TEST_P(PaintLayerTest, Has3DTransformedDescendant) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='parent' style='position:relative; z-index: 0'>
       <div id='child' style='transform: translateZ(1px)'>
@@ -519,7 +516,6 @@
 }
 
 TEST_P(PaintLayerTest, Has3DTransformedDescendantChangeStyle) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='parent' style='position:relative; z-index: 0'>
       <div id='child' style='position:relative '>
@@ -541,7 +537,6 @@
 }
 
 TEST_P(PaintLayerTest, Has3DTransformedDescendantNotStacking) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='parent' style='position:relative;'>
       <div id='child' style='transform: translateZ(1px)'>
@@ -558,7 +553,6 @@
 }
 
 TEST_P(PaintLayerTest, Has3DTransformedGrandchildWithPreserve3d) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='parent' style='position:relative; z-index: 0'>
       <div id='child' style='transform-style: preserve-3d'>
@@ -577,7 +571,6 @@
 }
 
 TEST_P(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <style>body { margin: 0; }</style>
     <div id='transform' style='transform: translate3d(4px, 5px, 6px);'>
@@ -669,7 +662,6 @@
 }
 
 TEST_P(PaintLayerTest, PaintInvalidationOnCompositedScroll) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <style>* { margin: 0 } ::-webkit-scrollbar { display: none }</style>
     <div id='scroller' style='overflow: scroll; width: 50px; height: 50px;
@@ -699,7 +691,6 @@
 }
 
 TEST_P(PaintLayerTest, CompositingContainerStackedFloatUnderStackingInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -724,7 +715,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerStackedFloatUnderStackingCompositedInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -749,7 +739,6 @@
 }
 
 TEST_P(PaintLayerTest, CompositingContainerNonStackedFloatUnderStackingInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -775,7 +764,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerNonStackedFloatUnderStackingCompositedInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -801,7 +789,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerStackedUnderFloatUnderStackingInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -828,7 +815,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerStackedUnderFloatUnderStackingCompositedInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -856,7 +842,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerNonStackedUnderFloatUnderStackingInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -884,7 +869,6 @@
 
 TEST_P(PaintLayerTest,
        CompositingContainerNonStackedUnderFloatUnderStackingCompositedInline) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -1090,7 +1074,6 @@
 }
 
 TEST_P(PaintLayerTest, CompositingContainerFloatingIframe) {
-  EnableCompositing();
   SetBodyInnerHTML(R"HTML(
     <div id='compositedContainer' style='position: relative;
         will-change: transform'>
@@ -1229,7 +1212,6 @@
 }
 
 TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
-  EnableCompositing();
   SetBodyInnerHTML(
       "<style>body {margin-top: 200px; backface-visibility: hidden}</style>"
       "<div id='target' style='position: absolute; top: 0'>Text</div>");
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
index aceeed5..ae3fe2b 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
@@ -47,8 +47,8 @@
 
     const hbox = this.contentElement.createChild('div', 'hbox styles-sidebar-pane-toolbar');
     const filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-filter-box');
-    const filterInput = Elements.StylesSidebarPane.createPropertyFilterElement(
-        Common.UIString('Filter'), hbox, filterCallback.bind(this), 'styles-filter-engaged');
+    const filterInput =
+        Elements.StylesSidebarPane.createPropertyFilterElement(ls`Filter`, hbox, filterCallback.bind(this));
     UI.ARIAUtils.setAccessibleName(filterInput, Common.UIString('Filter Computed Styles'));
     filterContainerElement.appendChild(filterInput);
     this.setDefaultFocusedElement(filterInput);
@@ -57,6 +57,9 @@
     toolbar.appendToolbarItem(new UI.ToolbarSettingCheckbox(
         this._showInheritedComputedStylePropertiesSetting, undefined, Common.UIString('Show all')));
 
+    this._noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');
+    this._noMatchesElement.textContent = ls`No matching property`;
+
     this._propertiesOutline = new UI.TreeOutlineInShadow();
     this._propertiesOutline.hideOverflow();
     this._propertiesOutline.registerRequiredCSS('elements/computedStyleWidgetTree.css');
@@ -336,11 +339,14 @@
    */
   _updateFilter(regex) {
     const children = this._propertiesOutline.rootElement().children();
+    let hasMatch = false;
     for (const child of children) {
       const property = child[Elements.ComputedStyleWidget._propertySymbol];
       const matched = !regex || regex.test(property.name) || regex.test(property.value);
       child.hidden = !matched;
+      hasMatch |= matched;
     }
+    this._noMatchesElement.classList.toggle('hidden', hasMatch);
   }
 };
 
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index 166b5d5..2845ba43 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -47,6 +47,9 @@
     this._pendingWidgetToggle = null;
     this._toolbarPaneElement = this._createStylesSidebarToolbar();
 
+    this._noMatchesElement = this.contentElement.createChild('div', 'gray-info-message hidden');
+    this._noMatchesElement.textContent = ls`No matching selector or style`;
+
     this._sectionsContainer = this.contentElement.createChild('div');
     UI.ARIAUtils.markAsTree(this._sectionsContainer);
     this._sectionsContainer.addEventListener('keydown', this._sectionsContainerKeyDown.bind(this), false);
@@ -144,17 +147,15 @@
    * @param {string} placeholder
    * @param {!Element} container
    * @param {function(?RegExp)} filterCallback
-   * @param {string} activeClassName
    * @return {!Element}
    */
-  static createPropertyFilterElement(placeholder, container, filterCallback, activeClassName) {
+  static createPropertyFilterElement(placeholder, container, filterCallback) {
     const input = createElementWithClass('input');
     input.placeholder = placeholder;
 
     function searchHandler() {
       const regex = input.value ? new RegExp(input.value.escapeForRegExp(), 'i') : null;
       filterCallback(regex);
-      container.classList.toggle(activeClassName, !!input.value);
     }
     input.addEventListener('input', searchHandler, false);
 
@@ -579,8 +580,10 @@
   }
 
   _updateFilter() {
+    let hasAnyVisibleBlock = false;
     for (const block of this._sectionBlocks)
-      block.updateFilter();
+      hasAnyVisibleBlock |= block.updateFilter();
+    this._noMatchesElement.classList.toggle('hidden', hasAnyVisibleBlock);
   }
 
   /**
@@ -615,8 +618,8 @@
     const container = this.contentElement.createChild('div', 'styles-sidebar-pane-toolbar-container');
     const hbox = container.createChild('div', 'hbox styles-sidebar-pane-toolbar');
     const filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-filter-box');
-    const filterInput = Elements.StylesSidebarPane.createPropertyFilterElement(
-        Common.UIString('Filter'), hbox, this._onFilterChanged.bind(this), 'styles-filter-engaged');
+    const filterInput =
+        Elements.StylesSidebarPane.createPropertyFilterElement(ls`Filter`, hbox, this._onFilterChanged.bind(this));
     UI.ARIAUtils.setAccessibleName(filterInput, Common.UIString('Filter Styles'));
     filterContainerElement.appendChild(filterInput);
     const toolbar = new UI.Toolbar('styles-pane-toolbar', hbox);
@@ -743,12 +746,16 @@
     return new Elements.SectionBlock(separatorElement);
   }
 
+  /**
+   * @return {boolean}
+   */
   updateFilter() {
     let hasAnyVisibleSection = false;
     for (const section of this.sections)
       hasAnyVisibleSection |= section._updateFilter();
     if (this._titleElement)
       this._titleElement.classList.toggle('hidden', !hasAnyVisibleSection);
+    return hasAnyVisibleSection;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css b/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
index d6055ad..21a0057e 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
+++ b/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
@@ -23,14 +23,12 @@
     outline: none !important;
     border: none;
     width: 100%;
-    background: transparent;
-    margin-left: 4px;
+    background: white;
+    padding-left: 4px;
+    margin: 3px;
 }
 
-.styles-filter-engaged {
-    background-color: rgba(255, 255, 0, 0.5);
-}
-
-:host-context(.-theme-with-dark-background) .styles-filter-engaged {
-    background-color: hsla(133, 100%, 30%, 0.5);
+.styles-sidebar-pane-filter-box > input:focus,
+.styles-sidebar-pane-filter-box > input:not(:placeholder-shown) {
+    box-shadow: var(--focus-ring-active-shadow);
 }
diff --git a/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css b/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
index a4f3b7c..b6f41b9 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
+++ b/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
@@ -34,12 +34,10 @@
     background-color: hsl(215, 25%, 91%);
 }
 
-.styles-filter-engaged,
 .styles-section .simple-selector.filter-match {
     background-color: rgba(255, 255, 0, 0.5);
 }
 
-:host-context(.-theme-with-dark-background) .styles-filter-engaged,
 :host-context(.-theme-with-dark-background) .styles-section .simple-selector.filter-match {
     background-color: hsla(133, 100%, 30%, 0.5);
 }
@@ -179,7 +177,8 @@
     box-shadow: var(--focus-ring-inactive-shadow);
 }
 
-.styles-sidebar-pane-filter-box > input:focus {
+.styles-sidebar-pane-filter-box > input:focus,
+.styles-sidebar-pane-filter-box > input:not(:placeholder-shown) {
     box-shadow: var(--focus-ring-active-shadow);
 }
 
diff --git a/third_party/blink/renderer/devtools/front_end/ui/filter.css b/third_party/blink/renderer/devtools/front_end/ui/filter.css
index 5afc729..025789e 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/filter.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/filter.css
@@ -151,6 +151,7 @@
     box-shadow: var(--focus-ring-inactive-shadow);
 }
 
-.filter-input-field:focus {
+.filter-input-field:focus,
+.filter-input-field:not(:empty) {
     box-shadow: var(--focus-ring-active-shadow);
 }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/toolbar.css b/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
index 6dcd7d3..d45a3f95 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
@@ -242,7 +242,8 @@
     box-shadow: var(--focus-ring-inactive-shadow);
 }
 
-.toolbar-input.focused {
+.toolbar-input.focused,
+.toolbar-input:not(.toolbar-input-empty) {
     box-shadow: var(--focus-ring-active-shadow);
 }
 
@@ -334,7 +335,8 @@
     box-shadow: var(--focus-ring-inactive-shadow);
 }
 
-input[is=history-input]:focus {
+input[is=history-input]:focus,
+input[is=history-input]:not(:placeholder-shown) {
     box-shadow: var(--focus-ring-active-shadow);
 }
 
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 8c03825e..3e21134 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -156,6 +156,7 @@
     "//third_party/blink/renderer/modules/webaudio",
     "//third_party/blink/renderer/modules/webdatabase",
     "//third_party/blink/renderer/modules/webgl",
+    "//third_party/blink/renderer/modules/webgpu",
     "//third_party/blink/renderer/modules/webmidi",
     "//third_party/blink/renderer/modules/webshare",
     "//third_party/blink/renderer/modules/websockets",
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
index 7223b2b9..a279118 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -137,8 +137,9 @@
       origin->Protocol() != url::kHttpsScheme) {
     resolver->Reject(DOMException::Create(
         DOMExceptionCode::kNotAllowedError,
-        "Public-key credentials are only available to secure HTTP or HTTPS "
-        "origins. See https://crbug.com/824383"));
+        "Public-key credentials are only available to HTTPS origin or "
+        "HTTP origins that fall under 'localhost'. See "
+        "https://crbug.com/824383"));
     return false;
   }
 
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index dae1d97..9fca2cb 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -397,6 +397,9 @@
           "webgl/webgl_uniform_location.idl",
           "webgl/webgl_vertex_array_object.idl",
           "webgl/webgl_vertex_array_object_oes.idl",
+          "webgpu/webgpu.idl",
+          "webgpu/webgpu_adapter.idl",
+          "webgpu/webgpu_device.idl",
           "webmidi/midi_access.idl",
           "webmidi/midi_connection_event.idl",
           "webmidi/midi_input.idl",
@@ -645,6 +648,7 @@
           "webaudio/wave_shaper_options.idl",
           "webgl/webgl_context_attributes.idl",
           "webgl/webgl_context_event_init.idl",
+          "webgpu/webgpu_adapter_descriptor.idl",
           "webmidi/midi_connection_event_init.idl",
           "webmidi/midi_message_event_init.idl",
           "webmidi/midi_options.idl",
@@ -758,6 +762,7 @@
           "webdatabase/window_web_database.idl",
           "webgl/webgl2_rendering_context_base.idl",
           "webgl/webgl_rendering_context_base.idl",
+          "webgpu/window_webgpu.idl",
           "webmidi/navigator_web_midi.idl",
           "webshare/navigator_share.idl",
           "webusb/navigator_usb.idl",
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn
new file mode 100644
index 0000000..3e2e9ff
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("webgpu") {
+  sources = [
+    "webgpu.cc",
+    "webgpu.h",
+    "webgpu_adapter.cc",
+    "webgpu_adapter.h",
+    "webgpu_device.cc",
+    "webgpu_device.h",
+    "window_webgpu.cc",
+    "window_webgpu.h",
+  ]
+}
diff --git a/third_party/blink/renderer/modules/webgpu/OWNERS b/third_party/blink/renderer/modules/webgpu/OWNERS
new file mode 100644
index 0000000..1a2169f
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/OWNERS
@@ -0,0 +1,5 @@
+cwallez@chromium.org
+kainino@chromium.org
+kbr@chromium.org
+
+# COMPONENT: Blink>WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/README.md b/third_party/blink/renderer/modules/webgpu/README.md
new file mode 100644
index 0000000..fc38f89
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/README.md
@@ -0,0 +1,7 @@
+# WebGPU Blink module
+
+The WebGPU API is the successor to the WebGL and WebGL 2 graphics APIs for the Web.
+It will provide modern features such as “GPU compute” as well as lower overhead access to GPU hardware and better, more predictable performance.
+WebGPU is being developed by the [“GPU for the Web”](https://www.w3.org/community/gpu/) W3C community group.
+
+This Blink module implements the WebGPU API's [sketch WebIDL](https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl) that will evolve as WebGPU gets closer to an MVP.
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.cc b/third_party/blink/renderer/modules/webgpu/webgpu.cc
new file mode 100644
index 0000000..4ec95c9
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu.cc
@@ -0,0 +1,23 @@
+// 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/webgpu/webgpu.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h"
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.h"
+
+namespace blink {
+
+// static
+WebGPU* WebGPU::Create() {
+  return new WebGPU();
+}
+
+WebGPUAdapter* WebGPU::getAdapter(const WebGPUAdapterDescriptor& descriptor) {
+  return WebGPUAdapter::Create(descriptor.powerPreference());
+}
+
+WebGPU::WebGPU() {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.h b/third_party/blink/renderer/modules/webgpu/webgpu.h
new file mode 100644
index 0000000..d989b7a
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu.h
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class WebGPUAdapter;
+class WebGPUAdapterDescriptor;
+
+class WebGPU final : public ScriptWrappable {
+  DISALLOW_COPY_AND_ASSIGN(WebGPU);
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static WebGPU* Create();
+
+  WebGPUAdapter* getAdapter(const WebGPUAdapterDescriptor&);
+
+ private:
+  WebGPU();
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu.idl b/third_party/blink/renderer/modules/webgpu/webgpu.idl
new file mode 100644
index 0000000..8877baf
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu.idl
@@ -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.
+
+[
+    RuntimeEnabled=WebGPU
+] interface WebGPU {
+    WebGPUAdapter getAdapter(WebGPUAdapterDescriptor descriptor);
+};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc
new file mode 100644
index 0000000..1e1f49e
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_device.h"
+
+namespace blink {
+
+// static
+WebGPUAdapter* WebGPUAdapter::Create(const String& name) {
+  return new WebGPUAdapter(name);
+}
+
+const String& WebGPUAdapter::name() const {
+  return name_;
+}
+
+WebGPUDevice* WebGPUAdapter::createDevice() {
+  return WebGPUDevice::Create(this);
+}
+
+WebGPUAdapter::WebGPUAdapter(const String& name) : name_(name) {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h
new file mode 100644
index 0000000..d1342c60
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class WebGPUDevice;
+
+class WebGPUAdapter final : public ScriptWrappable {
+  DISALLOW_COPY_AND_ASSIGN(WebGPUAdapter);
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static WebGPUAdapter* Create(const String& name);
+
+  const String& name() const;
+
+  WebGPUDevice* createDevice();
+
+ private:
+  WebGPUAdapter(const String& name);
+
+  String name_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl
new file mode 100644
index 0000000..7623ef7
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    RuntimeEnabled=WebGPU
+] interface WebGPUAdapter {
+    readonly attribute DOMString name;
+
+    WebGPUDevice createDevice();
+};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl b/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl
new file mode 100644
index 0000000..4c9a6ca
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl
@@ -0,0 +1,13 @@
+// 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.
+
+enum WebGPUPowerPreference {
+    "default",
+    "low-power",
+    "high-performance",
+};
+
+dictionary WebGPUAdapterDescriptor {
+    WebGPUPowerPreference powerPreference = "default";
+};
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.cc b/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
new file mode 100644
index 0000000..2364f6e
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.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 "third_party/blink/renderer/modules/webgpu/webgpu_device.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h"
+
+namespace blink {
+
+// static
+WebGPUDevice* WebGPUDevice::Create(WebGPUAdapter* adapter) {
+  return new WebGPUDevice(adapter);
+}
+
+WebGPUAdapter* WebGPUDevice::adapter() const {
+  return adapter_;
+}
+
+void WebGPUDevice::Trace(blink::Visitor* visitor) {
+  visitor->Trace(adapter_);
+  ScriptWrappable::Trace(visitor);
+}
+
+WebGPUDevice::WebGPUDevice(WebGPUAdapter* adapter) : adapter_(adapter) {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.h b/third_party/blink/renderer/modules/webgpu/webgpu_device.h
new file mode 100644
index 0000000..9fa78127
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class WebGPUAdapter;
+
+class WebGPUDevice final : public ScriptWrappable {
+  DISALLOW_COPY_AND_ASSIGN(WebGPUDevice);
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static WebGPUDevice* Create(WebGPUAdapter*);
+
+  WebGPUAdapter* adapter() const;
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  WebGPUDevice(WebGPUAdapter*);
+
+  Member<WebGPUAdapter> adapter_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
diff --git a/third_party/blink/renderer/modules/webgpu/webgpu_device.idl b/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
new file mode 100644
index 0000000..e7fb903
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
@@ -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.
+
+[
+    RuntimeEnabled=WebGPU
+] interface WebGPUDevice {
+   readonly attribute WebGPUAdapter adapter;
+};
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.cc b/third_party/blink/renderer/modules/webgpu/window_webgpu.cc
new file mode 100644
index 0000000..1a57845
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/window_webgpu.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/webgpu/window_webgpu.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/webgpu/webgpu.h"
+
+namespace blink {
+
+const char WindowWebGPU::kSupplementName[] = "WindowWebGPU";
+
+// static
+WindowWebGPU& WindowWebGPU::From(LocalDOMWindow& window) {
+  WindowWebGPU* supplement =
+      Supplement<LocalDOMWindow>::From<WindowWebGPU>(window);
+  if (!supplement) {
+    supplement = new WindowWebGPU(window);
+    ProvideTo(window, supplement);
+  }
+  return *supplement;
+}
+
+// static
+WebGPU* WindowWebGPU::webgpu(LocalDOMWindow& window) {
+  return WindowWebGPU::From(window).webgpu();
+}
+
+WebGPU* WindowWebGPU::webgpu() const {
+  if (!webgpu_) {
+    webgpu_ = WebGPU::Create();
+  }
+  return webgpu_.Get();
+}
+
+void WindowWebGPU::Trace(blink::Visitor* visitor) {
+  visitor->Trace(webgpu_);
+  Supplement<LocalDOMWindow>::Trace(visitor);
+}
+
+WindowWebGPU::WindowWebGPU(LocalDOMWindow& window)
+    : Supplement<LocalDOMWindow>(window) {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.h b/third_party/blink/renderer/modules/webgpu/window_webgpu.h
new file mode 100644
index 0000000..426040f
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/window_webgpu.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class WebGPU;
+class LocalDOMWindow;
+
+class WindowWebGPU final : public GarbageCollected<WindowWebGPU>,
+                           public Supplement<LocalDOMWindow> {
+  USING_GARBAGE_COLLECTED_MIXIN(WindowWebGPU);
+
+ public:
+  static const char kSupplementName[];
+
+  static WindowWebGPU& From(LocalDOMWindow&);
+  static WebGPU* webgpu(LocalDOMWindow&);
+  WebGPU* webgpu() const;
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  explicit WindowWebGPU(LocalDOMWindow&);
+
+  mutable Member<WebGPU> webgpu_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
diff --git a/third_party/blink/renderer/modules/webgpu/window_webgpu.idl b/third_party/blink/renderer/modules/webgpu/window_webgpu.idl
new file mode 100644
index 0000000..344cd7d
--- /dev/null
+++ b/third_party/blink/renderer/modules/webgpu/window_webgpu.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.
+
+[
+    RuntimeEnabled=WebGPU,
+    ImplementedAs=WindowWebGPU
+] partial interface Window {
+    [Replaceable, SameObject] readonly attribute WebGPU webgpu;
+};
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc
index 3c4dde6..eee8ae58 100644
--- a/third_party/blink/renderer/platform/exported/web_url_response.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -70,28 +70,16 @@
 
 }  // namespace
 
-// The purpose of this struct is to permit allocating a ResourceResponse on the
-// heap, which is otherwise disallowed by the DISALLOW_NEW_EXCEPT_PLACEMENT_NEW
-// annotation on ResourceResponse.
-struct WebURLResponse::ResourceResponseContainer {
-  ResourceResponseContainer() = default;
-
-  explicit ResourceResponseContainer(const ResourceResponse& r)
-      : resource_response(r) {}
-
-  ResourceResponse resource_response;
-};
-
 WebURLResponse::~WebURLResponse() = default;
 
 WebURLResponse::WebURLResponse()
-    : owned_resource_response_(new ResourceResponseContainer()),
-      resource_response_(&owned_resource_response_->resource_response) {}
+    : owned_resource_response_(std::make_unique<ResourceResponse>()),
+      resource_response_(owned_resource_response_.get()) {}
 
 WebURLResponse::WebURLResponse(const WebURLResponse& r)
     : owned_resource_response_(
-          new ResourceResponseContainer(*r.resource_response_)),
-      resource_response_(&owned_resource_response_->resource_response) {}
+          std::make_unique<ResourceResponse>(*r.resource_response_)),
+      resource_response_(owned_resource_response_.get()) {}
 
 WebURLResponse::WebURLResponse(const WebURL& url) : WebURLResponse() {
   SetURL(url);
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 2fce804..40395ce 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -1361,6 +1361,17 @@
   layer_state_->offset = layer_offset;
 }
 
+void GraphicsLayer::SetContentsLayerState(const PropertyTreeState& layer_state,
+                                          const IntPoint& layer_offset) {
+  if (!contents_layer_state_) {
+    contents_layer_state_ =
+        std::make_unique<LayerState>(LayerState{layer_state, layer_offset});
+    return;
+  }
+  contents_layer_state_->state = layer_state;
+  contents_layer_state_->offset = layer_offset;
+}
+
 scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
     PaintingControlSetting painting_control) {
   TRACE_EVENT0("blink,benchmark", "GraphicsLayer::PaintContents");
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 2d00839..bd93646 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -290,6 +290,17 @@
   }
   IntPoint GetOffsetFromTransformNode() const { return layer_state_->offset; }
 
+  void SetContentsLayerState(const PropertyTreeState&,
+                             const IntPoint& layer_offset);
+  const PropertyTreeState& GetContentsPropertyTreeState() const {
+    return contents_layer_state_ ? contents_layer_state_->state
+                                 : GetPropertyTreeState();
+  }
+  IntPoint GetContentsOffsetFromTransformNode() const {
+    return contents_layer_state_ ? contents_layer_state_->offset
+                                 : GetOffsetFromTransformNode();
+  }
+
   // Capture the last painted result into a PaintRecord. This GraphicsLayer
   // must DrawsContent. The result is never nullptr.
   sk_sp<PaintRecord> CapturePaintRecord() const;
@@ -438,6 +449,7 @@
     IntPoint offset;
   };
   std::unique_ptr<LayerState> layer_state_;
+  std::unique_ptr<LayerState> contents_layer_state_;
 
   std::unique_ptr<RasterInvalidator> raster_invalidator_;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index fec4db50..05ba712 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -61,8 +61,6 @@
 // member variable to this class, do not forget to add the corresponding
 // one in CrossThreadResourceResponseData and write copying logic.
 class PLATFORM_EXPORT ResourceResponse final {
-  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-
  public:
   enum HTTPVersion : uint8_t {
     kHTTPVersionUnknown,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 09552079..4d9dc45d 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -255,7 +255,7 @@
     },
     {
       name: "CSSEnvironmentVariables",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "CSSFocusVisible",
diff --git a/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h b/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h
index 3b01b24..e3ee7c91 100644
--- a/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h
@@ -23,7 +23,6 @@
     : public RefCountedThreadSafe<GracefulQueueShutdownHelper> {
  public:
   GracefulQueueShutdownHelper();
-  ~GracefulQueueShutdownHelper();
 
   void GracefullyShutdownTaskQueue(
       std::unique_ptr<internal::TaskQueueImpl> queue);
@@ -33,6 +32,10 @@
   std::vector<std::unique_ptr<internal::TaskQueueImpl>> TakeQueues();
 
  private:
+  // This class is ref-counted so it controls its own lifetime.
+  ~GracefulQueueShutdownHelper();
+  friend class RefCountedThreadSafe<GracefulQueueShutdownHelper>;
+
   Lock lock_;
   bool sequence_manager_deleted_;
   std::vector<std::unique_ptr<internal::TaskQueueImpl>> queues_;
diff --git a/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc b/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc
index 797d0fc..03ef8432 100644
--- a/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc
@@ -4,9 +4,7 @@
 
 #include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
 
-#include "base/bind.h"
-#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
+#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_forward.h"
 
 namespace base {
 namespace sequence_manager {
diff --git a/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h b/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h
index 3465ba4..7489b83f 100644
--- a/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h
+++ b/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h
@@ -5,8 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
 
-#include <set>
-
 #include "base/macros.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/time_domain_forward.h"
diff --git a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.cc b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.cc
index 30e37a3..b3aae71 100644
--- a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.cc
@@ -11,14 +11,15 @@
 #include "base/bit_cast.h"
 #include "base/compiler_specific.h"
 #include "base/debug/crash_logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "base/task/sequence_manager/task_time_observer.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/tick_clock.h"
 #include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
 #include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 #include "third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
 #include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
@@ -26,6 +27,12 @@
 namespace base {
 namespace sequence_manager {
 
+std::unique_ptr<SequenceManager> CreateSequenceManagerOnCurrentThread() {
+  return internal::SequenceManagerImpl::CreateOnCurrentThread();
+}
+
+namespace internal {
+
 namespace {
 
 constexpr base::TimeDelta kLongTaskTraceEventThreshold =
@@ -47,10 +54,6 @@
 
 }  // namespace
 
-std::unique_ptr<SequenceManager> CreateSequenceManagerOnCurrentThread() {
-  return SequenceManagerImpl::CreateOnCurrentThread();
-}
-
 SequenceManagerImpl::SequenceManagerImpl(
     std::unique_ptr<internal::ThreadController> controller)
     : graceful_shutdown_helper_(new internal::GracefulQueueShutdownHelper()),
@@ -113,7 +116,7 @@
 // static
 std::unique_ptr<SequenceManagerImpl>
 SequenceManagerImpl::CreateOnCurrentThread() {
-  return std::unique_ptr<SequenceManagerImpl>(
+  return WrapUnique(
       new SequenceManagerImpl(internal::ThreadControllerImpl::Create(
           MessageLoop::current(), DefaultTickClock::GetInstance())));
 }
@@ -402,12 +405,14 @@
   if (executing_task->task_queue->GetQuiescenceMonitored())
     main_thread_only().task_was_run_on_quiescence_monitored_queue = true;
 
+#if !defined(OS_NACL)
   debug::SetCrashKeyString(
       main_thread_only().file_name_crash_key,
       executing_task->pending_task.posted_from.file_name());
   debug::SetCrashKeyString(
       main_thread_only().function_name_crash_key,
       executing_task->pending_task.posted_from.function_name());
+#endif  // OS_NACL
 
   if (executing_task->task_queue->GetShouldNotifyObservers()) {
     {
@@ -685,10 +690,12 @@
     const char* function_name_crash_key_name) {
   DCHECK(!main_thread_only().file_name_crash_key);
   DCHECK(!main_thread_only().function_name_crash_key);
+#if !defined(OS_NACL)
   main_thread_only().file_name_crash_key = debug::AllocateCrashKeyString(
       file_name_crash_key_name, debug::CrashKeySize::Size64);
   main_thread_only().function_name_crash_key = debug::AllocateCrashKeyString(
       function_name_crash_key_name, debug::CrashKeySize::Size64);
+#endif  // OS_NACL
 }
 
 internal::TaskQueueImpl* SequenceManagerImpl::currently_executing_task_queue()
@@ -698,5 +705,6 @@
   return main_thread_only().task_execution_stack.rbegin()->task_queue;
 }
 
+}  // namespace internal
 }  // namespace sequence_manager
 }  // namespace base
diff --git a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h
index 1a87728..dd3a94e 100644
--- a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 
 namespace base {
+
 namespace debug {
 struct CrashKeyString;
 }  // namespace debug
@@ -42,20 +43,19 @@
 namespace trace_event {
 class ConvertableToTraceFormat;
 }  // namespace trace_event
-}  // namespace base
 
-namespace base {
 namespace sequence_manager {
 
-namespace internal {
-class RealTimeDomain;
-class TaskQueueImpl;
-}  // namespace internal
-
+class SequenceManagerForTest;
 class TaskQueue;
 class TaskTimeObserver;
 class TimeDomain;
 
+namespace internal {
+
+class RealTimeDomain;
+class TaskQueueImpl;
+
 // The task queue manager provides N task queues and a selector interface for
 // choosing which task queue to service next. Each task queue consists of two
 // sub queues:
@@ -145,7 +145,7 @@
       std::unique_ptr<internal::ThreadController> controller);
 
   friend class internal::TaskQueueImpl;
-  friend class SequenceManagerForTest;
+  friend class ::base::sequence_manager::SequenceManagerForTest;
 
  private:
   enum class ProcessTaskResult {
@@ -325,6 +325,7 @@
   DISALLOW_COPY_AND_ASSIGN(SequenceManagerImpl);
 };
 
+}  // namespace internal
 }  // namespace sequence_manager
 }  // namespace base
 
diff --git a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl_unittest.cc
index 9ffc98b..b160bf8 100644
--- a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl_unittest.cc
@@ -47,6 +47,9 @@
 
 namespace base {
 namespace sequence_manager {
+namespace internal {
+// To avoid symbol collisions in jumbo builds.
+namespace sequence_manager_impl_unittest {
 
 class SequenceManagerTestBase : public testing::Test {
  protected:
@@ -3184,5 +3187,7 @@
   test_executed.Wait();
 }
 
+}  // namespace sequence_manager_impl_unittest
+}  // namespace internal
 }  // namespace sequence_manager
 }  // namespace base
diff --git a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_perftest.cc b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_perftest.cc
index 477fcb4..70bd824 100644
--- a/third_party/blink/renderer/platform/scheduler/base/sequence_manager_perftest.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/sequence_manager_perftest.cc
@@ -18,12 +18,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/mock_time_domain.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/test_task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
 
 namespace base {
 namespace sequence_manager {
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue.cc b/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
index c03b41e7..2a7aafb 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
@@ -4,8 +4,7 @@
 
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
-#include "base/bind_helpers.h"
-#include "base/optional.h"
+#include "base/bind.h"
 #include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h b/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
index 9cb7c114..3db0a4e5c 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
@@ -7,9 +7,6 @@
 
 #include <stddef.h>
 
-#include <set>
-
-#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/pending_task.h"
 #include "base/threading/thread_checker.h"
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h b/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h
index 0e85d67..7c8e91c 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h
@@ -7,6 +7,7 @@
 
 namespace base {
 namespace sequence_manager {
+namespace internal {
 
 // Used to describe the logic trigerred when a task queue is selected to
 // service.
@@ -29,6 +30,7 @@
   kCount = 9,
 };
 
+}  // namespace internal
 }  // namespace sequence_manager
 }  // namespace base
 
diff --git a/third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h b/third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h
index 566350e..460911a 100644
--- a/third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h
+++ b/third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h
@@ -16,7 +16,7 @@
 namespace base {
 namespace sequence_manager {
 
-class SequenceManagerForTest : public SequenceManagerImpl {
+class SequenceManagerForTest : public internal::SequenceManagerImpl {
  public:
   explicit SequenceManagerForTest(
       std::unique_ptr<internal::ThreadController> thread_controller);
@@ -37,8 +37,8 @@
   size_t QueuesToDeleteCount() const;
   size_t QueuesToShutdownCount();
 
-  using SequenceManagerImpl::GetNextSequenceNumber;
-  using SequenceManagerImpl::WakeUpReadyDelayedQueues;
+  using internal::SequenceManagerImpl::GetNextSequenceNumber;
+  using internal::SequenceManagerImpl::WakeUpReadyDelayedQueues;
 };
 
 }  // namespace sequence_manager
diff --git a/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h b/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h
index e6473caf..5e005c2 100644
--- a/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h
@@ -17,6 +17,8 @@
 
 namespace base {
 
+// TODO(kraynov): https://crbug.com/828835
+// Consider going away from using MessageLoop in the renderer process.
 class MessageLoop;
 
 namespace sequence_manager {
@@ -113,7 +115,7 @@
   RepeatingClosure immediate_do_work_closure_;
   RepeatingClosure delayed_do_work_closure_;
   CancelableClosure cancelable_delayed_do_work_closure_;
-  SequencedTaskSource* sequence_ = nullptr;  // NOT OWNED
+  SequencedTaskSource* sequence_ = nullptr;  // Not owned.
   debug::TaskAnnotator task_annotator_;
 
   WeakPtrFactory<ThreadControllerImpl> weak_factory_;
diff --git a/third_party/blink/renderer/platform/scheduler/base/time_domain.cc b/third_party/blink/renderer/platform/scheduler/base/time_domain.cc
index 25298477c..bcf7f0e 100644
--- a/third_party/blink/renderer/platform/scheduler/base/time_domain.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/time_domain.cc
@@ -20,7 +20,7 @@
 }
 
 void TimeDomain::OnRegisterWithSequenceManager(
-    SequenceManagerImpl* sequence_manager) {
+    internal::SequenceManagerImpl* sequence_manager) {
   DCHECK(sequence_manager);
   DCHECK(!sequence_manager_);
   sequence_manager_ = sequence_manager;
diff --git a/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc b/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc
index c744a854..476485e 100644
--- a/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_forward.h"
+#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
 
@@ -22,7 +22,7 @@
 
 class TaskQueueImplForTest : public internal::TaskQueueImpl {
  public:
-  TaskQueueImplForTest(SequenceManagerImpl* sequence_manager,
+  TaskQueueImplForTest(internal::SequenceManagerImpl* sequence_manager,
                        TimeDomain* time_domain,
                        const TaskQueue::Spec& spec)
       : TaskQueueImpl(sequence_manager, time_domain, spec) {}
diff --git a/third_party/blink/renderer/platform/scheduler/base/work_queue.h b/third_party/blink/renderer/platform/scheduler/base/work_queue.h
index 30c80640..fe1c7d5a 100644
--- a/third_party/blink/renderer/platform/scheduler/base/work_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/base/work_queue.h
@@ -5,10 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_H_
 
-#include <stddef.h>
-
-#include <set>
-
 #include "base/task/sequence_manager/enqueue_order.h"
 #include "base/task/sequence_manager/intrusive_heap.h"
 #include "base/task/sequence_manager/sequenced_task_source.h"
diff --git a/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc b/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc
index 0d34d146b..94235c9 100644
--- a/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc
@@ -70,8 +70,8 @@
   bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
   DCHECK(has_enqueue_order);
   size_t set_index = work_queue->work_queue_set_index();
-  DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = "
-                                                 << set_index;
+  DCHECK_LT(set_index, work_queue_heaps_.size())
+      << " set_index = " << set_index;
   // |work_queue| should not be in work_queue_heaps_[set_index].
   DCHECK(!work_queue->heap_handle().IsValid());
   work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
@@ -136,8 +136,8 @@
 }
 
 bool WorkQueueSets::IsSetEmpty(size_t set_index) const {
-  DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = "
-                                                 << set_index;
+  DCHECK_LT(set_index, work_queue_heaps_.size())
+      << " set_index = " << set_index;
   return work_queue_heaps_[set_index].empty();
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h b/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h
index aab5294..8e9fb97e 100644
--- a/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h
+++ b/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h
@@ -5,8 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_SETS_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_SETS_H_
 
-#include <stddef.h>
-
 #include <map>
 #include <vector>
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
index c14ed39..a7f5f49 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -10,7 +10,6 @@
 #include "base/message_loop/message_loop.h"
 #include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h b/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
index 05b9930..42e7ca8 100644
--- a/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
@@ -8,6 +8,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/platform/web_thread_type.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
index 3ee6026..81963783 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -12,6 +12,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/time/tick_clock.h"
 #include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h b/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
index 959a788..8d7bb3e 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_
 
 #include "base/macros.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/time_domain_forward.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
index bebf668..09526dc 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/time/time_override.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/time_domain_forward.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index a1cc862b..5739991 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -30,7 +30,6 @@
 #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl_forward.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
 #include "third_party/blink/renderer/platform/scheduler/child/features.h"
 #include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index dde8b23..daf1088 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -24,7 +24,6 @@
 #include "third_party/blink/public/common/page/launching_process_state.h"
 #include "third_party/blink/public/platform/web_mouse_wheel_event.h"
 #include "third_party/blink/public/platform/web_touch_event.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/child/features.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h b/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
index bb331955..903d7eb 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PRIORITIZE_COMPOSITING_AFTER_INPUT_EXPERIMENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PRIORITIZE_COMPOSITING_AFTER_INPUT_EXPERIMENT_H_
 
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h b/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h
index 5b67686..325baf6 100644
--- a/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h
+++ b/third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h
@@ -10,6 +10,9 @@
 #include "base/threading/platform_thread.h"
 #include "third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h"
 
+// TODO(kraynov): Move to //base/task/sequence_manager/test to avoid
+// cross-component exposure of internal ThreadControllerImpl.
+
 namespace blink {
 namespace scheduler {
 
diff --git a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
index 3bfb76a6d..75e3dad 100644
--- a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
@@ -9,7 +9,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/sequence_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/test/lazy_thread_controller_for_test.h"
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
index 4e4c1e44..b247336c 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
 
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace blink {
diff --git a/third_party/quic_trace/BUILD.gn b/third_party/quic_trace/BUILD.gn
new file mode 100644
index 0000000..eb83eeaf
--- /dev/null
+++ b/third_party/quic_trace/BUILD.gn
@@ -0,0 +1,36 @@
+import("//third_party/protobuf/proto_library.gni")
+
+# Since most of the Chromium uses proto_lite, modify the source proto file to
+# use the lite runtime.
+action("quic_trace_proto_lite_runtime") {
+  script = "append_lite_runtime.py"
+  inputs = [
+    "src/lib/quic_trace.proto",
+  ]
+  outputs = [
+    "$target_gen_dir/quic_trace.proto",
+  ]
+  args =
+      rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
+}
+
+proto_library("quic_trace_proto") {
+  # QUIC trace is only used in unit tests and stand-alone command line tools.
+  # It is not linked into the network stack itself due to the Cronet binary
+  # size concerns.
+  visibility = [ "//net:quic_test_tools" ]
+
+  sources = [
+    "$target_gen_dir/quic_trace.proto",
+  ]
+  deps = [
+    ":quic_trace_proto_lite_runtime",
+  ]
+  component_build_force_source_set = true
+  testonly = true
+
+  # The result can be included as third_party/quic_trace/lib/quic_trace.pb.h
+  proto_out_dir = rebase_path(".", "//") + "/lib"
+
+  extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
+}
diff --git a/third_party/quic_trace/OWNERS b/third_party/quic_trace/OWNERS
new file mode 100644
index 0000000..3a9a3cb
--- /dev/null
+++ b/third_party/quic_trace/OWNERS
@@ -0,0 +1,5 @@
+rch@chromium.org
+vasilvv@chromium.org
+zhongyi@chromium.org
+
+file://net/OWNERS
diff --git a/third_party/quic_trace/README.chromium b/third_party/quic_trace/README.chromium
new file mode 100644
index 0000000..e2112438
--- /dev/null
+++ b/third_party/quic_trace/README.chromium
@@ -0,0 +1,11 @@
+Name: QUIC trace format description and utilities
+Short Name: quic-trace
+URL: https://github.com/google/quic-trace
+Version: git
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+A format for transcribing all connection-related events that has occurred
+througout a QUIC session.
diff --git a/third_party/quic_trace/append_lite_runtime.py b/third_party/quic_trace/append_lite_runtime.py
new file mode 100755
index 0000000..7d1aeb0
--- /dev/null
+++ b/third_party/quic_trace/append_lite_runtime.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# Copyright (c) 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Appends the LITE_RUNTIME annotation to a proto2 protocol buffer file.
+"""
+
+import sys
+
+if len(sys.argv) != 3:
+  sys.stderr.write("Usage: append_lite_runtime.py in.proto out.proto\n")
+  sys.exit(1)
+
+with open(sys.argv[1], "rb") as source:
+  with open(sys.argv[2], "wb") as output:
+    for line in source:
+      output.write(line)
+      if line.strip() == 'syntax = "proto2";':
+        output.write("option optimize_for = LITE_RUNTIME;\n")
diff --git a/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp b/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
index b906f7ad..9df0b47 100644
--- a/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
+++ b/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
@@ -161,9 +161,8 @@
     auto constructor_conversion = cxxConstructExpr(
         is_once_callback, argumentCountIs(1),
         hasArgument(0, ignoringImplicit(parameter_construction)));
-    auto implicit_conversion = implicitCastExpr(
-        is_once_callback, hasSourceExpression(constructor_conversion));
-    return implicit_conversion;
+    return implicitCastExpr(is_once_callback,
+                            hasSourceExpression(constructor_conversion));
   }
 
   void run(const MatchFinder::MatchResult& result) override {
@@ -577,6 +576,64 @@
   Replacements* replacements_;
 };
 
+// Remove base::AdaptCallbackForRepeating() where resulting
+// base::RepeatingCallback is implicitly converted into base::OnceCallback.
+// Example:
+//   // Before
+//   base::PostTask(
+//       FROM_HERE,
+//       base::AdaptCallbackForRepeating(base::BindOnce(&Foo)));
+//   base::OnceCallback<void()> cb = base::AdaptCallbackForRepeating(
+//       base::OnceBind(&Foo));
+//
+//   // After
+//   base::PostTask(FROM_HERE, base::BindOnce(&Foo));
+//   base::OnceCallback<void()> cb = base::BindOnce(&Foo);
+class AdaptCallbackForRepeatingRewriter : public MatchFinder::MatchCallback,
+                                          public Rewriter {
+ public:
+  explicit AdaptCallbackForRepeatingRewriter(Replacements* replacements)
+      : replacements_(replacements) {}
+
+  StatementMatcher GetMatcher() {
+    auto is_once_callback = hasType(hasCanonicalType(hasDeclaration(
+        classTemplateSpecializationDecl(hasName("::base::OnceCallback")))));
+    auto is_repeating_callback =
+        hasType(hasCanonicalType(hasDeclaration(classTemplateSpecializationDecl(
+            hasName("::base::RepeatingCallback")))));
+
+    auto adapt_callback_call =
+        callExpr(
+            callee(namedDecl(hasName("::base::AdaptCallbackForRepeating"))))
+            .bind("target");
+    auto parameter_construction =
+        cxxConstructExpr(is_repeating_callback, argumentCountIs(1),
+                         hasArgument(0, ignoringImplicit(adapt_callback_call)));
+    auto constructor_conversion = cxxConstructExpr(
+        is_once_callback, argumentCountIs(1),
+        hasArgument(0, ignoringImplicit(parameter_construction)));
+    return implicitCastExpr(is_once_callback,
+                            hasSourceExpression(constructor_conversion));
+  }
+
+  void run(const MatchFinder::MatchResult& result) override {
+    auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target");
+
+    auto left = clang::CharSourceRange::getTokenRange(
+        result.SourceManager->getSpellingLoc(target->getLocStart()),
+        result.SourceManager->getSpellingLoc(target->getArg(0)->getExprLoc())
+            .getLocWithOffset(-1));
+    replacements_->emplace_back(*result.SourceManager, left, "");
+    auto r_paren = clang::CharSourceRange::getTokenRange(
+        result.SourceManager->getSpellingLoc(target->getRParenLoc()),
+        result.SourceManager->getSpellingLoc(target->getRParenLoc()));
+    replacements_->emplace_back(*result.SourceManager, r_paren, "");
+  }
+
+ private:
+  Replacements* replacements_;
+};
+
 llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
 llvm::cl::OptionCategory rewriter_category("Rewriter Options");
 
@@ -588,6 +645,7 @@
     bind_to_bind_once
     pass_by_value
     add_std_move
+    remove_unneeded_adapt_callback
 The default is remove_unneeded_passed.
 )"),
     llvm::cl::init("remove_unneeded_passed"),
@@ -623,6 +681,12 @@
     auto add_std_move = llvm::make_unique<AddStdMoveRewriter>(&replacements);
     match_finder.addMatcher(add_std_move->GetMatcher(), add_std_move.get());
     rewriter = std::move(add_std_move);
+  } else if (rewriter_option == "remove_unneeded_adapt_callback") {
+    auto remove_unneeded_adapt_callback =
+        llvm::make_unique<AdaptCallbackForRepeatingRewriter>(&replacements);
+    match_finder.addMatcher(remove_unneeded_adapt_callback->GetMatcher(),
+                            remove_unneeded_adapt_callback.get());
+    rewriter = std::move(remove_unneeded_adapt_callback);
   } else {
     abort();
   }
diff --git a/tools/clang/base_bind_rewriters/tests/callback.h b/tools/clang/base_bind_rewriters/tests/callback.h
index f89836ed..2872039 100644
--- a/tools/clang/base_bind_rewriters/tests/callback.h
+++ b/tools/clang/base_bind_rewriters/tests/callback.h
@@ -95,6 +95,11 @@
   return RepeatingCallback<void()>();
 }
 
+RepeatingCallback<void()> AdaptCallbackForRepeating(
+    OnceCallback<void()> callback) {
+  return Callback<void()>();
+}
+
 }  // namespace base
 
 #endif  // TOOLS_CLANG_BASE_BIND_REWRITERS_TESTS_CALLBACK_H_
diff --git a/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-expected.cc b/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-expected.cc
new file mode 100644
index 0000000..62275279
--- /dev/null
+++ b/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-expected.cc
@@ -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.
+
+#include "callback.h"
+
+void Foo(base::OnceClosure) {}
+
+void Test() {
+  base::OnceClosure cb = base::BindOnce([] {});
+  Foo(base::BindOnce([] {}));
+
+  using namespace base;
+
+  OnceClosure cb2 = BindOnce([] {});
+  Foo(BindOnce([] {}));
+
+  OnceClosure cb3 = base::BindOnce([] {});
+}
diff --git a/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-original.cc b/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-original.cc
new file mode 100644
index 0000000..233e262
--- /dev/null
+++ b/tools/clang/base_bind_rewriters/tests/remove-adapt-callback-for-repeating-original.cc
@@ -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.
+
+#include "callback.h"
+
+void Foo(base::OnceClosure) {}
+
+void Test() {
+  base::OnceClosure cb = base::AdaptCallbackForRepeating(base::BindOnce([] {}));
+  Foo(base::AdaptCallbackForRepeating(base::BindOnce([] {})));
+
+  using namespace base;
+
+  OnceClosure cb2 = AdaptCallbackForRepeating(BindOnce([] {}));
+  Foo(AdaptCallbackForRepeating(BindOnce([] {})));
+
+  OnceClosure cb3 = base::BindOnce([] {});
+}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index fb86347a..9c1b447 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -2999,6 +2999,7 @@
   <int value="11" label="Offline content notification task"/>
   <int value="12" label="WebAPK update task"/>
   <int value="13" label="Download resumption task"/>
+  <int value="14" label="Feed refresh task"/>
 </enum>
 
 <enum name="BackgroundTracingState">
@@ -28014,6 +28015,7 @@
   <int value="-78035185" label="custom_summary"/>
   <int value="-77872983" label="BookmarkAppsMac:disabled"/>
   <int value="-76631048" label="disable-offline-auto-reload-visible-only"/>
+  <int value="-75418012" label="ContextualSuggestionsOptOut:disabled"/>
   <int value="-72455054" label="WebVrAutopresent:disabled"/>
   <int value="-70595606" label="ash-enable-unified-desktop"/>
   <int value="-69427025" label="OfflinePagesPrefetchingUI:enabled"/>
@@ -29036,6 +29038,7 @@
   <int value="2101151142" label="disable-direct-write"/>
   <int value="2104788328" label="use-winrt-midi-api"/>
   <int value="2113804526" label="EnableAppShortcutSearch:enabled"/>
+  <int value="2114843059" label="ContextualSuggestionsOptOut:enabled"/>
   <int value="2119964154" label="enable-download-resumption"/>
   <int value="2121056855" label="IncreaseInputAudioBufferSize:disabled"/>
   <int value="2121550859" label="PreferHtmlOverPlugins:enabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 44445b7..e18ad55 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -49734,6 +49734,9 @@
 </histogram>
 
 <histogram name="Net.ErrAborted.ReceivedBytes" units="bytes">
+  <obsolete>
+    Removed from Chromium as of 2018/7/2.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The TotalReceivedBytes() at the time the request finishes with ERR_ABORTED.
@@ -49741,6 +49744,9 @@
 </histogram>
 
 <histogram name="Net.ErrAborted.SentBytes" units="bytes">
+  <obsolete>
+    Removed from Chromium as of 2018/7/2.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The TotalSentBytes() at the time the request finishes with ERR_ABORTED.
@@ -53767,6 +53773,9 @@
 </histogram>
 
 <histogram name="Net.RequestTime2Success.MainFrame" units="ms">
+  <obsolete>
+    Removed from Chromium as of 2018/7/2.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The amount of time between request initiation and request completion for
@@ -53775,6 +53784,9 @@
 </histogram>
 
 <histogram name="Net.RequestTime2Success.Subresource" units="ms">
+  <obsolete>
+    Removed from Chromium as of 2018/7/2.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The amount of time between request initiation and request completion for
@@ -53892,6 +53904,9 @@
 </histogram>
 
 <histogram name="Net.ResourceLoader.TimeToURLRequestStart" units="ms">
+  <obsolete>
+    Removed from Chromium as of 2018/7/2.
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The time elapsed from URLRequest creation to when a ResourceLoader actually
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py
index 36f79963..815ce9b1 100644
--- a/tools/perf/benchmarks/media.py
+++ b/tools/perf/benchmarks/media.py
@@ -37,10 +37,6 @@
     # 'toplevel' category provides CPU time slices used by # cpuTimeMetric.
     category_filter.AddIncludedCategory('toplevel')
 
-    # 'rail' category is used by powerMetric to attribute different period of
-    # time to different activities, such as video_animation, etc.
-    category_filter.AddIncludedCategory('rail')
-
     # Collect media related events required by mediaMetric.
     category_filter.AddIncludedCategory('media')
 
@@ -48,15 +44,14 @@
     category_filter.AddDisabledByDefault('disabled-by-default-memory-infra')
 
     options = timeline_based_measurement.Options(category_filter)
-    options.config.enable_battor_trace = True
     options.config.enable_android_graphics_memtrack = True
 
     # Setting an empty memory dump config disables periodic dumps.
     options.config.chrome_trace_config.SetMemoryDumpConfig(
         chrome_trace_config.MemoryDumpConfig())
 
-    options.SetTimelineBasedMetrics(['powerMetric', 'mediaMetric',
-                                     'cpuTimeMetric', 'memoryMetric'])
+    options.SetTimelineBasedMetrics(['mediaMetric', 'cpuTimeMetric',
+                                     'memoryMetric'])
     return options
 
   @classmethod
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py
index 71d6843..f97accb4 100644
--- a/tools/perf/benchmarks/power.py
+++ b/tools/perf/benchmarks/power.py
@@ -12,20 +12,16 @@
 from telemetry.web_perf import timeline_based_measurement
 
 
-class _BattOrPowerBenchmark(perf_benchmark.PerfBenchmark):
+class _PowerBenchmark(perf_benchmark.PerfBenchmark):
+  """A benchmark that indirectly measures power through CPU time."""
 
   def CreateCoreTimelineBasedMeasurementOptions(self):
     category_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter(
         filter_string='toplevel')
     options = timeline_based_measurement.Options(category_filter)
-    options.config.chrome_trace_config.category_filter.AddFilterString('rail')
-    options.config.enable_atrace_trace = True
-    options.config.atrace_config.categories = ['sched']
-    options.config.enable_battor_trace = True
     options.config.enable_chrome_trace = True
     options.config.enable_cpu_trace = True
-    options.SetTimelineBasedMetrics(
-        ['powerMetric', 'clockSyncLatencyMetric', 'cpuTimeMetric'])
+    options.SetTimelineBasedMetrics(['cpuTimeMetric'])
     return options
 
 
@@ -44,6 +40,8 @@
     return 'power.typical_10_mobile'
 
 
+# TODO(charliea): Delete this benchmark now that we're no longer measuring
+# ground-truth power.
 @benchmark.Owner(emails=['charliea@chromium.org'])
 class IdlePlatformBenchmark(perf_benchmark.PerfBenchmark):
   """Idle platform benchmark.
@@ -55,14 +53,11 @@
   def CreateCoreTimelineBasedMeasurementOptions(self):
     options = timeline_based_measurement.Options(
         chrome_trace_category_filter.ChromeTraceCategoryFilter())
-    options.config.enable_battor_trace = True
     options.config.enable_cpu_trace = True
     # Atrace tracing agent autodetects if its android and only runs if it is.
     options.config.enable_atrace_trace = True
     options.config.enable_chrome_trace = False
     options.SetTimelineBasedMetrics([
-        'clockSyncLatencyMetric',
-        'powerMetric',
         'tracingMetric'
     ])
     return options
@@ -76,7 +71,7 @@
 
 
 @benchmark.Owner(emails=['charliea@chromium.org'])
-class PowerDesktop(_BattOrPowerBenchmark):
+class PowerDesktop(_PowerBenchmark):
   SUPPORTED_PLATFORMS = [story.expectations.ALL_DESKTOP]
 
   def CreateStorySet(self, options):
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py
index 4e672089..a0217c84 100644
--- a/tools/perf/benchmarks/system_health.py
+++ b/tools/perf/benchmarks/system_health.py
@@ -41,13 +41,10 @@
     cat_filter.AddIncludedCategory('accessibility')
 
     options = timeline_based_measurement.Options(cat_filter)
-    options.config.enable_battor_trace = True
     options.config.enable_chrome_trace = True
     options.config.enable_cpu_trace = True
     options.SetTimelineBasedMetrics([
-        'clockSyncLatencyMetric',
         'cpuTimeMetric',
-        'powerMetric',
         'tracingMetric',
         'accessibilityMetric',
         'limitedCpuTimeMetric'
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 3b89d4fe..3a356d9 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -696,9 +696,9 @@
 def get_tests_in_performance_test_suite():
   tests = sets.Set()
   add_benchmarks_from_sharding_map(
-      tests, "shard_maps/desktop_26_shard_map.json")
+      tests, "shard_maps/linux_perf_shard_map.json")
   add_benchmarks_from_sharding_map(
-      tests, "shard_maps/mobile_39_shard_map.json")
+      tests, "shard_maps/pixel2_7_shard_map.json")
   return tests
 
 
@@ -707,7 +707,9 @@
   if os.path.exists(path):
     with open(path) as f:
       sharding_map = json.load(f)
-    for _, benchmarks in sharding_map.iteritems():
+    for shard, benchmarks in sharding_map.iteritems():
+      if "extra_infos" in shard:
+        continue
       for benchmark, _ in benchmarks['benchmarks'].iteritems():
         tests.add(benchmark)
 
@@ -855,7 +857,7 @@
       ],
       'platform': 'mac',
       'dimension': {
-        'pool': 'Chrome-perf-fyi',
+        'pool': 'chrome.tests.perf-fyi',
         'os': 'Mac-10.12',
         'gpu': '8086:0a2e'
       },
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py
index b997378..28a92ba 100644
--- a/tools/perf/core/perf_json_config_validator.py
+++ b/tools/perf/core/perf_json_config_validator.py
@@ -12,7 +12,7 @@
     'gpu', 'device_ids', 'os', 'pool', 'perf_tests', 'perf_tests_with_args',
     'device_os', 'device_type', 'device_os_flavor', 'id'}
 _VALID_PERF_POOLS = {
-    'Chrome-perf', 'Chrome-perf-fyi',
+    'Chrome-perf',
     'chrome.tests.perf', 'chrome.tests.perf-webview',
     'chrome.tests.perf-fyi', 'chrome.tests.perf-webview-fyi'}
 
diff --git a/tools/perf/core/shard_maps/android_go_14_shard_map.json b/tools/perf/core/shard_maps/android_go_14_shard_map.json
index 59603bc..704ff65 100644
--- a/tools/perf/core/shard_maps/android_go_14_shard_map.json
+++ b/tools/perf/core/shard_maps/android_go_14_shard_map.json
@@ -1,215 +1,126 @@
 {
     "0": {
         "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {
-                "end": 1
+            "system_health.common_mobile": {},
+            "start_with_url.warm.startup_pages": {},
+            "start_with_url.cold.startup_pages": {},
+            "system_health.memory_mobile": {},
+            "system_health.webview_startup": {},
+            "power.typical_10_mobile": {
+                "end": 3
             }
         }
     },
     "1": {
         "benchmarks": {
-            "blink_perf.dom": {
-                "begin": 1
-            },
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {},
-            "blink_perf.owp_storage": {
-                "end": 3
+            "power.typical_10_mobile": {
+                "begin": 3,
+                "end": 6
             }
         }
     },
     "2": {
         "benchmarks": {
-            "blink_perf.owp_storage": {
-                "begin": 3
-            },
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {
-                "end": 6
+            "power.typical_10_mobile": {
+                "begin": 6,
+                "end": 9
             }
         }
     },
     "3": {
         "benchmarks": {
-            "blink_perf.svg": {
-                "begin": 6
+            "power.typical_10_mobile": {
+                "begin": 9
             },
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {
-                "end": 9
+            "memory.top_10_mobile": {
+                "end": 1
             }
         }
     },
     "4": {
         "benchmarks": {
-            "loading.mobile": {
-                "begin": 9,
-                "end": 34
+            "memory.top_10_mobile": {
+                "begin": 1,
+                "end": 3
             }
         }
     },
     "5": {
         "benchmarks": {
-            "loading.mobile": {
-                "begin": 34,
-                "end": 90
+            "memory.top_10_mobile": {
+                "begin": 3,
+                "end": 5
             }
         }
     },
     "6": {
         "benchmarks": {
-            "loading.mobile": {
-                "begin": 90
-            },
-            "media.desktop": {},
-            "media.mobile": {},
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {},
             "memory.top_10_mobile": {
-                "end": 12
+                "begin": 5,
+                "end": 7
             }
         }
     },
     "7": {
         "benchmarks": {
             "memory.top_10_mobile": {
-                "begin": 12
-            },
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {
-                "end": 16
+                "begin": 7,
+                "end": 9
             }
         }
     },
     "8": {
         "benchmarks": {
-            "rasterize_and_record_micro.top_25": {
-                "begin": 16
-            },
-            "rendering.desktop": {},
-            "rendering.mobile": {
-                "end": 93
+            "memory.top_10_mobile": {
+                "begin": 9,
+                "end": 10
             }
         }
     },
     "9": {
         "benchmarks": {
-            "rendering.mobile": {
-                "begin": 93
-            },
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {
-                "end": 9
+            "memory.top_10_mobile": {
+                "begin": 10,
+                "end": 12
             }
         }
     },
     "10": {
         "benchmarks": {
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {
-                "begin": 9
-            },
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {},
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-            "smoothness.top_25_smooth": {}
+            "memory.top_10_mobile": {
+                "begin": 12,
+                "end": 14
+            }
         }
     },
     "11": {
         "benchmarks": {
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {},
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {},
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {},
-            "system_health.memory_desktop": {},
-            "system_health.memory_mobile": {},
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {},
-            "thread_times.key_mobile_sites_smooth": {},
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {
-                "end": 32
+            "memory.top_10_mobile": {
+                "begin": 14,
+                "end": 16
             }
         }
     },
     "12": {
         "benchmarks": {
-            "thread_times.tough_scrolling_cases": {
-                "begin": 32
-            },
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
-            "v8.browsing_mobile": {
-                "end": 24
+            "memory.top_10_mobile": {
+                "begin": 16,
+                "end": 18
             }
         }
     },
     "13": {
         "benchmarks": {
-            "v8.browsing_mobile": {
-                "begin": 24
-            },
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
+            "memory.top_10_mobile": {
+                "begin": 18
+            }
         }
     },
     "extra_infos": {
-        "num_stories": 2401,
-        "predicted_min_shard_time": 6936.110622523241,
-        "predicted_min_shard_index": 4,
-        "predicted_max_shard_time": 7595.144805609757,
-        "predicted_max_shard_index": 5
+        "num_stories": 160,
+        "predicted_min_shard_time": 224.836488080808,
+        "predicted_min_shard_index": 8,
+        "predicted_max_shard_time": 599.3532815757576,
+        "predicted_max_shard_index": 3
     }
 }
diff --git a/tools/perf/core/shard_maps/benchmark_android_bot_map.json b/tools/perf/core/shard_maps/benchmark_android_bot_map.json
deleted file mode 100644
index 087ea7cd..0000000
--- a/tools/perf/core/shard_maps/benchmark_android_bot_map.json
+++ /dev/null
@@ -1,250 +0,0 @@
-{
-  "0": {
-    "benchmarks": {
-      "power.desktop": {},
-      "smoothness.desktop_tough_pinch_zoom_cases": {},
-      "tab_switching.typical_25": {}
-    }
-  },
-  "1": {
-    "benchmarks": {
-      "smoothness.gpu_rasterization.polymer": {},
-      "thread_times.key_hit_test_cases": {}
-    }
-  },
-  "10": {
-    "benchmarks": {
-      "blink_perf.paint": {},
-      "smoothness.key_mobile_sites_smooth": {},
-      "v8.browsing_desktop": {}
-    }
-  },
-  "11": {
-    "benchmarks": {
-      "blink_perf.parser": {},
-      "smoothness.key_silk_cases": {},
-      "v8.browsing_desktop-future": {}
-    }
-  },
-  "12": {
-    "benchmarks": {
-      "blink_perf.shadow_dom": {},
-      "smoothness.maps": {},
-      "v8.browsing_mobile": {}
-    }
-  },
-  "13": {
-    "benchmarks": {
-      "blink_perf.svg": {},
-      "smoothness.pathological_mobile_sites": {},
-      "v8.browsing_mobile-future": {}
-    }
-  },
-  "14": {
-    "benchmarks": {
-      "dromaeo": {},
-      "smoothness.simple_mobile_sites": {}
-    }
-  },
-  "15": {
-    "benchmarks": {
-      "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-      "v8.runtime_stats.top_25": {}
-    }
-  },
-  "16": {
-    "benchmarks": {
-      "smoothness.top_25_smooth": {},
-      "rendering.mobile": {}
-    }
-  },
-  "17": {
-    "benchmarks": {
-      "smoothness.tough_ad_cases": {},
-      "rendering.desktop": {}
-    }
-  },
-  "18": {
-    "benchmarks": {
-      "smoothness.tough_animation_cases": {},
-      "wasm": {}
-    }
-  },
-  "19": {
-    "benchmarks": {
-      "dummy_benchmark.histogram_benchmark_1": {},
-      "smoothness.tough_canvas_cases": {},
-      "webrtc": {}
-    }
-  },
-  "2": {
-    "benchmarks": {
-      "blink_perf.bindings": {},
-      "smoothness.gpu_rasterization.top_25_smooth": {},
-      "thread_times.key_idle_power_cases": {}
-    }
-  },
-  "20": {
-    "benchmarks": {
-      "dummy_benchmark.noisy_benchmark_1": {},
-      "smoothness.tough_filters_cases": {}
-    }
-  },
-  "21": {
-    "benchmarks": {
-      "dummy_benchmark.stable_benchmark_1": {},
-      "smoothness.tough_image_decode_cases": {}
-    }
-  },
-  "22": {
-    "benchmarks": {
-      "jetstream": {},
-      "smoothness.tough_path_rendering_cases": {}
-    }
-  },
-  "23": {
-    "benchmarks": {
-      "kraken": {},
-      "smoothness.tough_pinch_zoom_cases": {}
-    }
-  },
-  "24": {
-    "benchmarks": {
-      "loading.desktop": {},
-      "smoothness.tough_scrolling_cases": {}
-    }
-  },
-  "25": {
-    "benchmarks": {
-      "loading.mobile": {},
-      "smoothness.tough_texture_upload_cases": {}
-    }
-  },
-  "26": {
-    "benchmarks": {
-      "media.desktop": {},
-      "smoothness.tough_webgl_ad_cases": {}
-    }
-  },
-  "27": {
-    "benchmarks": {
-      "media.mobile": {},
-      "smoothness.tough_webgl_cases": {}
-    }
-  },
-  "28": {
-    "benchmarks": {
-      "memory.desktop": {},
-      "speedometer": {}
-    }
-  },
-  "29": {
-    "benchmarks": {
-      "memory.long_running_idle_gmail_background_tbmv2": {},
-      "speedometer-future": {}
-    }
-  },
-  "3": {
-    "benchmarks": {
-      "blink_perf.canvas": {},
-      "smoothness.gpu_rasterization.tough_filters_cases": {},
-      "thread_times.key_mobile_sites_smooth": {}
-    }
-  },
-  "30": {
-    "benchmarks": {
-      "memory.long_running_idle_gmail_tbmv2": {},
-      "speedometer2": {}
-    }
-  },
-  "31": {
-    "benchmarks": {
-      "memory.top_10_mobile": {},
-      "speedometer2-future": {}
-    }
-  },
-  "32": {
-    "benchmarks": {
-      "octane": {},
-      "start_with_url.cold.startup_pages": {}
-    }
-  },
-  "33": {
-    "benchmarks": {
-      "oortonline_tbmv2": {},
-      "start_with_url.warm.startup_pages": {}
-    }
-  },
-  "34": {
-    "benchmarks": {
-      "power.idle_platform": {},
-      "system_health.common_desktop": {}
-    }
-  },
-  "35": {
-    "benchmarks": {
-      "power.typical_10_mobile": {},
-      "system_health.common_mobile": {}
-    }
-  },
-  "36": {
-    "benchmarks": {
-      "rasterize_and_record_micro.partial_invalidation": {},
-      "system_health.memory_desktop": {}
-    }
-  },
-  "37": {
-    "benchmarks": {
-      "rasterize_and_record_micro.top_25": {},
-      "system_health.memory_mobile": {}
-    }
-  },
-  "38": {
-    "benchmarks": {
-      "scheduler.tough_scheduling_cases": {},
-      "system_health.webview_startup": {}
-    }
-  },
-  "4": {
-    "benchmarks": {
-      "blink_perf.css": {},
-      "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-      "thread_times.key_noop_cases": {}
-    }
-  },
-  "5": {
-    "benchmarks": {
-      "blink_perf.dom": {},
-      "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-      "thread_times.key_silk_cases": {}
-    }
-  },
-  "6": {
-    "benchmarks": {
-      "blink_perf.events": {},
-      "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-      "thread_times.simple_mobile_sites": {}
-    }
-  },
-  "7": {
-    "benchmarks": {
-      "blink_perf.image_decoder": {},
-      "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-      "thread_times.tough_compositor_cases": {}
-    }
-  },
-  "8": {
-    "benchmarks": {
-      "blink_perf.layout": {},
-      "smoothness.image_decoding_cases": {},
-      "thread_times.tough_scrolling_cases": {}
-    }
-  },
-  "9": {
-    "benchmarks": {
-      "blink_perf.owp_storage": {},
-      "smoothness.key_desktop_move_cases": {},
-      "tracing.tracing_with_background_memory_infra": {}
-    }
-  }
-}
diff --git a/tools/perf/core/shard_maps/benchmark_desktop_bot_map.json b/tools/perf/core/shard_maps/benchmark_desktop_bot_map.json
deleted file mode 100644
index efd97c5..0000000
--- a/tools/perf/core/shard_maps/benchmark_desktop_bot_map.json
+++ /dev/null
@@ -1,198 +0,0 @@
-{
-  "0": {
-    "benchmarks": {
-      "media.desktop": {},
-      "smoothness.pathological_mobile_sites": {},
-      "tab_switching.typical_25": {}
-    }
-  },
-  "1": {
-    "benchmarks": {
-      "media.mobile": {},
-      "power.desktop": {},
-      "smoothness.simple_mobile_sites": {},
-      "thread_times.key_hit_test_cases": {}
-    }
-  },
-  "10": {
-    "benchmarks": {
-      "blink_perf.paint": {},
-      "rasterize_and_record_micro.partial_invalidation": {},
-      "smoothness.tough_pinch_zoom_cases": {},
-      "v8.browsing_desktop": {}
-    }
-  },
-  "11": {
-    "benchmarks": {
-      "blink_perf.parser": {},
-      "rasterize_and_record_micro.top_25": {},
-      "smoothness.tough_scrolling_cases": {},
-      "v8.browsing_desktop-future": {}
-    }
-  },
-  "12": {
-    "benchmarks": {
-      "blink_perf.shadow_dom": {},
-      "scheduler.tough_scheduling_cases": {},
-      "smoothness.tough_texture_upload_cases": {},
-      "v8.browsing_mobile": {}
-    }
-  },
-  "13": {
-    "benchmarks": {
-      "blink_perf.svg": {},
-      "smoothness.desktop_tough_pinch_zoom_cases": {},
-      "smoothness.tough_webgl_ad_cases": {},
-      "v8.browsing_mobile-future": {}
-    }
-  },
-  "14": {
-    "benchmarks": {
-      "dromaeo": {},
-      "smoothness.gpu_rasterization.polymer": {},
-      "smoothness.tough_webgl_cases": {}
-    }
-  },
-  "15": {
-    "benchmarks": {
-      "smoothness.gpu_rasterization.top_25_smooth": {},
-      "speedometer": {},
-      "v8.runtime_stats.top_25": {}
-    }
-  },
-  "16": {
-    "benchmarks": {
-      "smoothness.gpu_rasterization.tough_filters_cases": {},
-      "speedometer-future": {},
-       "rendering.mobile": {}
-    }
-  },
-  "17": {
-    "benchmarks": {
-      "rendering.desktop": {},
-      "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-      "speedometer2": {}
-    }
-  },
-  "18": {
-    "benchmarks": {
-      "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-      "speedometer2-future": {},
-      "wasm": {}
-    }
-  },
-  "19": {
-    "benchmarks": {
-      "dummy_benchmark.histogram_benchmark_1": {},
-      "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-      "start_with_url.cold.startup_pages": {},
-      "webrtc": {}
-    }
-  },
-  "2": {
-    "benchmarks": {
-      "blink_perf.bindings": {},
-      "memory.desktop": {},
-      "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-      "thread_times.key_idle_power_cases": {}
-    }
-  },
-  "20": {
-    "benchmarks": {
-      "dummy_benchmark.noisy_benchmark_1": {},
-      "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-      "start_with_url.warm.startup_pages": {}
-    }
-  },
-  "21": {
-    "benchmarks": {
-      "dummy_benchmark.stable_benchmark_1": {},
-      "smoothness.image_decoding_cases": {},
-      "system_health.common_desktop": {}
-    }
-  },
-  "22": {
-    "benchmarks": {
-      "jetstream": {},
-      "smoothness.key_desktop_move_cases": {},
-      "system_health.common_mobile": {}
-    }
-  },
-  "23": {
-    "benchmarks": {
-      "kraken": {},
-      "smoothness.key_mobile_sites_smooth": {},
-      "system_health.memory_desktop": {}
-    }
-  },
-  "24": {
-    "benchmarks": {
-      "loading.desktop": {},
-      "smoothness.key_silk_cases": {},
-      "system_health.memory_mobile": {}
-    }
-  },
-  "25": {
-    "benchmarks": {
-      "loading.mobile": {},
-      "smoothness.maps": {},
-      "system_health.webview_startup": {}
-    }
-  },
-  "3": {
-    "benchmarks": {
-      "blink_perf.canvas": {},
-      "memory.long_running_idle_gmail_background_tbmv2": {},
-      "smoothness.top_25_smooth": {},
-      "thread_times.key_mobile_sites_smooth": {}
-    }
-  },
-  "4": {
-    "benchmarks": {
-      "blink_perf.css": {},
-      "memory.long_running_idle_gmail_tbmv2": {},
-      "smoothness.tough_ad_cases": {},
-      "thread_times.key_noop_cases": {}
-    }
-  },
-  "5": {
-    "benchmarks": {
-      "blink_perf.dom": {},
-      "memory.top_10_mobile": {},
-      "smoothness.tough_animation_cases": {},
-      "thread_times.key_silk_cases": {}
-    }
-  },
-  "6": {
-    "benchmarks": {
-      "blink_perf.events": {},
-      "octane": {},
-      "smoothness.tough_canvas_cases": {},
-      "thread_times.simple_mobile_sites": {}
-    }
-  },
-  "7": {
-    "benchmarks": {
-      "blink_perf.image_decoder": {},
-      "oortonline_tbmv2": {},
-      "smoothness.tough_filters_cases": {},
-      "thread_times.tough_compositor_cases": {}
-    }
-  },
-  "8": {
-    "benchmarks": {
-      "blink_perf.layout": {},
-      "power.idle_platform": {},
-      "smoothness.tough_image_decode_cases": {},
-      "thread_times.tough_scrolling_cases": {}
-    }
-  },
-  "9": {
-    "benchmarks": {
-      "blink_perf.owp_storage": {},
-      "power.typical_10_mobile": {},
-      "smoothness.tough_path_rendering_cases": {},
-      "tracing.tracing_with_background_memory_infra": {}
-    }
-  }
-}
diff --git a/tools/perf/core/shard_maps/desktop_26_shard_map.json b/tools/perf/core/shard_maps/desktop_26_shard_map.json
deleted file mode 100644
index 6292fc7..0000000
--- a/tools/perf/core/shard_maps/desktop_26_shard_map.json
+++ /dev/null
@@ -1,232 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {
-                "end": 47
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "blink_perf.layout": {
-                "begin": 47
-            },
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {
-                "end": 2
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "loading.desktop": {
-                "begin": 2,
-                "end": 40
-            }
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "loading.desktop": {
-                "begin": 40
-            },
-            "loading.mobile": {},
-            "media.desktop": {
-                "end": 27
-            }
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "media.desktop": {
-                "begin": 27
-            },
-            "media.mobile": {},
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {}
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "memory.top_10_mobile": {},
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {
-                "end": 2
-            }
-        }
-    },
-    "6": {
-        "benchmarks": {
-            "rasterize_and_record_micro.top_25": {
-                "begin": 2
-            },
-            "rendering.desktop": {
-                "end": 40
-            }
-        }
-    },
-    "7": {
-        "benchmarks": {
-            "rendering.desktop": {
-                "begin": 40,
-                "end": 101
-            }
-        }
-    },
-    "8": {
-        "benchmarks": {
-            "rendering.desktop": {
-                "begin": 101
-            },
-            "rendering.mobile": {}
-        }
-    },
-    "9": {
-        "benchmarks": {
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {
-                "end": 8
-            }
-        }
-    },
-    "10": {
-        "benchmarks": {
-            "system_health.common_desktop": {
-                "begin": 8,
-                "end": 45
-            }
-        }
-    },
-    "11": {
-        "benchmarks": {
-            "system_health.common_desktop": {
-                "begin": 45
-            }
-        }
-    },
-    "12": {
-        "benchmarks": {
-            "system_health.common_mobile": {},
-            "system_health.memory_desktop": {
-                "end": 12
-            }
-        }
-    },
-    "13": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 12,
-                "end": 26
-            }
-        }
-    },
-    "14": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 26,
-                "end": 46
-            }
-        }
-    },
-    "15": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 46,
-                "end": 54
-            }
-        }
-    },
-    "16": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 54,
-                "end": 62
-            }
-        }
-    },
-    "17": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 62
-            },
-            "system_health.memory_mobile": {},
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "tracing.tracing_with_background_memory_infra": {
-                "end": 1
-            }
-        }
-    },
-    "18": {
-        "benchmarks": {
-            "tracing.tracing_with_background_memory_infra": {
-                "begin": 1
-            },
-            "v8.browsing_desktop": {
-                "end": 13
-            }
-        }
-    },
-    "19": {
-        "benchmarks": {
-            "v8.browsing_desktop": {
-                "begin": 13
-            },
-            "v8.browsing_desktop-future": {
-                "end": 8
-            }
-        }
-    },
-    "20": {
-        "benchmarks": {
-            "v8.browsing_desktop-future": {
-                "begin": 8
-            },
-            "v8.browsing_mobile": {},
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {
-                "end": 3
-            }
-        }
-    },
-    "21": {
-        "benchmarks": {
-            "v8.runtime_stats.top_25": {
-                "begin": 3
-            }
-        }
-    },
-    "22": {
-        "benchmarks": {
-            "wasm": {},
-            "webrtc": {}
-        }
-    }
-}
diff --git a/tools/perf/core/shard_maps/desktop_5_shard_map.json b/tools/perf/core/shard_maps/desktop_5_shard_map.json
deleted file mode 100644
index 4d32f8e2..0000000
--- a/tools/perf/core/shard_maps/desktop_5_shard_map.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {},
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {},
-            "media.desktop": {},
-            "media.mobile": {},
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {},
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {
-                "end": 2
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "power.desktop": {
-                "begin": 2
-            },
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {},
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {},
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-            "smoothness.top_25_smooth": {},
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {
-                "end": 19
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "smoothness.tough_animation_cases": {
-                "begin": 19
-            },
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {},
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {},
-            "system_health.memory_desktop": {
-                "end": 8
-            }
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "system_health.memory_desktop": {
-                "begin": 8
-            },
-            "system_health.memory_mobile": {},
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {},
-            "thread_times.key_mobile_sites_smooth": {},
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {
-                "end": 23
-            }
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "thread_times.tough_scrolling_cases": {
-                "begin": 23
-            },
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
-            "v8.browsing_mobile": {},
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
-        }
-    }
-}
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/mac1012_5_shard_map.json b/tools/perf/core/shard_maps/mac1012_5_shard_map.json
index 1397aec..4e38c8c 100644
--- a/tools/perf/core/shard_maps/mac1012_5_shard_map.json
+++ b/tools/perf/core/shard_maps/mac1012_5_shard_map.json
@@ -1,134 +1,105 @@
 {
     "0": {
         "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
+            "system_health.common_mobile": {},
+            "v8.browsing_mobile-future": {},
+            "rendering.mobile": {},
             "blink_perf.image_decoder": {},
-            "blink_perf.layout": {},
+            "power.desktop": {},
+            "speedometer-future": {},
             "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
+            "memory.desktop": {},
+            "start_with_url.warm.startup_pages": {},
+            "wasm": {},
             "dummy_benchmark.histogram_benchmark_1": {},
+            "speedometer": {},
+            "memory.long_running_idle_gmail_tbmv2": {},
+            "octane": {},
             "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
+            "blink_perf.svg": {},
+            "system_health.webview_startup": {},
+            "speedometer2-future": {},
             "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {},
-            "media.desktop": {},
-            "media.mobile": {},
-            "memory.desktop": {
-                "end": 6
+            "smoothness.tough_pinch_zoom_cases": {},
+            "power.idle_platform": {},
+            "power.typical_10_mobile": {},
+            "v8.runtime_stats.top_25": {
+                "end": 79
             }
         }
     },
     "1": {
         "benchmarks": {
-            "memory.desktop": {
-                "begin": 6
+            "v8.runtime_stats.top_25": {
+                "begin": 79
             },
+            "loading.mobile": {},
+            "speedometer2": {},
+            "v8.browsing_desktop-future": {},
+            "webrtc": {},
+            "blink_perf.shadow_dom": {},
+            "blink_perf.events": {},
+            "blink_perf.layout": {},
             "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {},
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {},
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {
-                "end": 6
+            "tab_switching.typical_25": {},
+            "blink_perf.dom": {},
+            "media.mobile": {},
+            "start_with_url.cold.startup_pages": {},
+            "blink_perf.bindings": {},
+            "system_health.memory_desktop": {
+                "end": 22
             }
         }
     },
     "2": {
         "benchmarks": {
-            "smoothness.desktop_tough_pinch_zoom_cases": {
-                "begin": 6
-            },
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {},
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-            "smoothness.top_25_smooth": {},
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {},
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {},
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {},
             "system_health.memory_desktop": {
-                "end": 8
+                "begin": 22,
+                "end": 60
             }
         }
     },
     "3": {
         "benchmarks": {
             "system_health.memory_desktop": {
-                "begin": 8
+                "begin": 60
             },
-            "system_health.memory_mobile": {},
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {},
-            "thread_times.key_mobile_sites_smooth": {},
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {},
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {
-                "end": 16
+            "media.desktop": {},
+            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
+            "rasterize_and_record_micro.partial_invalidation": {},
+            "v8.browsing_desktop": {},
+            "blink_perf.parser": {},
+            "memory.top_10_mobile": {},
+            "blink_perf.canvas": {},
+            "loading.desktop": {
+                "end": 79
             }
         }
     },
     "4": {
         "benchmarks": {
-            "v8.browsing_desktop": {
-                "begin": 16
+            "loading.desktop": {
+                "begin": 79
             },
-            "v8.browsing_desktop-future": {},
+            "dromaeo": {},
+            "kraken": {},
+            "oortonline_tbmv2": {},
+            "system_health.common_desktop": {},
+            "rasterize_and_record_micro.top_25": {},
+            "dummy_benchmark.stable_benchmark_1": {},
+            "system_health.memory_mobile": {},
+            "rendering.desktop": {},
+            "blink_perf.css": {},
             "v8.browsing_mobile": {},
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
+            "blink_perf.paint": {},
+            "tracing.tracing_with_background_memory_infra": {}
         }
+    },
+    "extra_infos": {
+        "num_stories": 1831,
+        "predicted_min_shard_time": 19266.939837765593,
+        "predicted_min_shard_index": 3,
+        "predicted_max_shard_time": 19772.160803,
+        "predicted_max_shard_index": 2
     }
 }
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/mobile_21_shard_map.json b/tools/perf/core/shard_maps/mobile_21_shard_map.json
deleted file mode 100644
index a259256..0000000
--- a/tools/perf/core/shard_maps/mobile_21_shard_map.json
+++ /dev/null
@@ -1,263 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {
-                "end": 5
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "blink_perf.layout": {
-                "begin": 5
-            },
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {
-                "end": 16
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "blink_perf.parser": {
-                "begin": 16
-            },
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {
-                "end": 5
-            }
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "loading.mobile": {
-                "begin": 5
-            },
-            "media.desktop": {},
-            "media.mobile": {},
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {}
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {},
-            "octane": {}
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {
-                "end": 27
-            }
-        }
-    },
-    "6": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 27,
-                "end": 124
-            }
-        }
-    },
-    "7": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 124,
-                "end": 223
-            }
-        }
-    },
-    "8": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 223
-            },
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {
-                "end": 28
-            }
-        }
-    },
-    "9": {
-        "benchmarks": {
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {
-                "begin": 28
-            },
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {},
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {
-                "end": 21
-            }
-        }
-    },
-    "10": {
-        "benchmarks": {
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {
-                "begin": 21
-            },
-            "smoothness.top_25_smooth": {},
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {
-                "end": 47
-            }
-        }
-    },
-    "11": {
-        "benchmarks": {
-            "smoothness.tough_animation_cases": {
-                "begin": 47
-            },
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {
-                "end": 37
-            }
-        }
-    },
-    "12": {
-        "benchmarks": {
-            "smoothness.tough_scrolling_cases": {
-                "begin": 37
-            },
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {
-                "end": 8
-            }
-        }
-    },
-    "13": {
-        "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 8,
-                "end": 59
-            }
-        }
-    },
-    "14": {
-        "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 59
-            },
-            "system_health.memory_desktop": {},
-            "system_health.memory_mobile": {
-                "end": 18
-            }
-        }
-    },
-    "15": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 18,
-                "end": 42
-            }
-        }
-    },
-    "16": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 42,
-                "end": 55
-            }
-        }
-    },
-    "17": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 55
-            },
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {},
-            "thread_times.key_mobile_sites_smooth": {
-                "end": 15
-            }
-        }
-    },
-    "18": {
-        "benchmarks": {
-            "thread_times.key_mobile_sites_smooth": {
-                "begin": 15
-            },
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {},
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
-            "v8.browsing_mobile": {
-                "end": 8
-            }
-        }
-    },
-    "19": {
-        "benchmarks": {
-            "v8.browsing_mobile": {
-                "begin": 8
-            },
-            "v8.browsing_mobile-future": {
-                "end": 8
-            }
-        }
-    },
-    "20": {
-        "benchmarks": {
-            "v8.browsing_mobile-future": {
-                "begin": 8
-            },
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
-        }
-    }
-}
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/mobile_39_shard_map.json b/tools/perf/core/shard_maps/mobile_39_shard_map.json
deleted file mode 100644
index 3b8e9d2..0000000
--- a/tools/perf/core/shard_maps/mobile_39_shard_map.json
+++ /dev/null
@@ -1,315 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {
-                "end": 4
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "blink_perf.css": {
-                "begin": 4
-            },
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {
-                "end": 16
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "blink_perf.layout": {
-                "begin": 16
-            },
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {
-                "end": 2
-            }
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "blink_perf.paint": {
-                "begin": 2
-            },
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {
-                "end": 6
-            }
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "blink_perf.shadow_dom": {
-                "begin": 6
-            },
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {}
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {
-                "end": 18
-            }
-        }
-    },
-    "6": {
-        "benchmarks": {
-            "loading.mobile": {
-                "begin": 18
-            },
-            "media.desktop": {},
-            "media.mobile": {
-                "end": 13
-            }
-        }
-    },
-    "7": {
-        "benchmarks": {
-            "media.mobile": {
-                "begin": 13
-            },
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {
-                "end": 4
-            }
-        }
-    },
-    "8": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 4,
-                "end": 17
-            }
-        }
-    },
-    "9": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 17
-            },
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {}
-        }
-    },
-    "10": {
-        "benchmarks": {
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {
-                "end": 20
-            }
-        }
-    },
-    "11": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 20,
-                "end": 70
-            }
-        }
-    },
-    "12": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 70,
-                "end": 124
-            }
-        }
-    },
-    "13": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 124,
-                "end": 178
-            }
-        }
-    },
-    "14": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 178,
-                "end": 228
-            }
-        }
-    },
-    "15": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 228
-            }
-        }
-    },
-    "16": {
-        "benchmarks": {
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {}
-        }
-    },
-    "17": {
-        "benchmarks": {
-            "smoothness.tough_pinch_zoom_cases": {}
-        }
-    },
-    "18": {
-        "benchmarks": {
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {}
-        }
-    },
-    "19": {
-        "benchmarks": {
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {
-                "end": 2
-            }
-        }
-    },
-    "20": {
-        "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 2,
-                "end": 26
-            }
-        }
-    },
-    "21": {
-        "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 26,
-                "end": 59
-            }
-        }
-    },
-    "22": {
-        "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 59
-            },
-            "system_health.memory_desktop": {},
-            "system_health.memory_mobile": {
-                "end": 9
-            }
-        }
-    },
-    "23": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 9,
-                "end": 18
-            }
-        }
-    },
-    "24": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 18,
-                "end": 29
-            }
-        }
-    },
-    "25": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 29,
-                "end": 47
-            }
-        }
-    },
-    "26": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 47,
-                "end": 53
-            }
-        }
-    },
-    "27": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 53,
-                "end": 59
-            }
-        }
-    },
-    "28": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 59
-            },
-            "system_health.webview_startup": {}
-        }
-    },
-    "29": {
-        "benchmarks": {
-            "tab_switching.typical_25": {}
-        }
-    },
-    "30": {
-        "benchmarks": {
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
-            "v8.browsing_mobile": {
-                "end": 1
-            }
-        }
-    },
-    "31": {
-        "benchmarks": {
-            "v8.browsing_mobile": {
-                "begin": 1,
-                "end": 16
-            }
-        }
-    },
-    "32": {
-        "benchmarks": {
-            "v8.browsing_mobile": {
-                "begin": 16
-            },
-            "v8.browsing_mobile-future": {
-                "end": 6
-            }
-        }
-    },
-    "33": {
-        "benchmarks": {
-            "v8.browsing_mobile-future": {
-                "begin": 6,
-                "end": 18
-            }
-        }
-    },
-    "34": {
-        "benchmarks": {
-            "v8.browsing_mobile-future": {
-                "begin": 18
-            },
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
-        }
-    }
-}
diff --git a/tools/perf/core/shard_maps/mobile_7_shard_map.json b/tools/perf/core/shard_maps/mobile_7_shard_map.json
deleted file mode 100644
index 5b589f5..0000000
--- a/tools/perf/core/shard_maps/mobile_7_shard_map.json
+++ /dev/null
@@ -1,142 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {},
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {}
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "loading.desktop": {},
-            "loading.mobile": {},
-            "media.desktop": {},
-            "media.mobile": {},
-            "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
-            "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {},
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
-            "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {
-                "end": 7
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "rendering.mobile": {
-                "begin": 7
-            },
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {}
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {},
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-            "smoothness.top_25_smooth": {},
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {},
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {
-                "end": 35
-            }
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "smoothness.tough_scrolling_cases": {
-                "begin": 35
-            },
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
-            "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
-            "system_health.common_desktop": {},
-            "system_health.common_mobile": {},
-            "system_health.memory_desktop": {},
-            "system_health.memory_mobile": {
-                "end": 17
-            }
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "system_health.memory_mobile": {
-                "begin": 17
-            },
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {
-                "end": 3
-            }
-        }
-    },
-    "6": {
-        "benchmarks": {
-            "thread_times.key_idle_power_cases": {
-                "begin": 3
-            },
-            "thread_times.key_mobile_sites_smooth": {},
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {},
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
-            "v8.browsing_mobile": {},
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
-        }
-    }
-}
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/pixel2_7_shard_map.json b/tools/perf/core/shard_maps/pixel2_7_shard_map.json
index c42ead3..5796e80 100644
--- a/tools/perf/core/shard_maps/pixel2_7_shard_map.json
+++ b/tools/perf/core/shard_maps/pixel2_7_shard_map.json
@@ -1,152 +1,114 @@
 {
     "0": {
         "benchmarks": {
-            "blink_perf.bindings": {},
-            "blink_perf.canvas": {},
-            "blink_perf.css": {},
-            "blink_perf.dom": {},
-            "blink_perf.events": {},
-            "blink_perf.image_decoder": {},
-            "blink_perf.layout": {},
-            "blink_perf.owp_storage": {},
-            "blink_perf.paint": {},
-            "blink_perf.parser": {},
-            "blink_perf.shadow_dom": {},
-            "blink_perf.svg": {},
-            "dromaeo": {},
-            "dummy_benchmark.histogram_benchmark_1": {},
-            "dummy_benchmark.noisy_benchmark_1": {},
-            "dummy_benchmark.stable_benchmark_1": {},
-            "jetstream": {},
-            "kraken": {},
-            "loading.desktop": {},
-            "loading.mobile": {
-                "end": 35
+            "system_health.common_mobile": {},
+            "v8.browsing_mobile-future": {},
+            "rendering.mobile": {
+                "end": 284
             }
         }
     },
     "1": {
         "benchmarks": {
-            "loading.mobile": {
-                "begin": 35
+            "rendering.mobile": {
+                "begin": 284
             },
-            "media.desktop": {},
-            "media.mobile": {},
+            "blink_perf.image_decoder": {},
+            "power.desktop": {},
+            "speedometer-future": {},
+            "blink_perf.owp_storage": {},
             "memory.desktop": {},
-            "memory.long_running_idle_gmail_background_tbmv2": {},
+            "start_with_url.warm.startup_pages": {},
+            "wasm": {},
+            "dummy_benchmark.histogram_benchmark_1": {},
+            "speedometer": {},
             "memory.long_running_idle_gmail_tbmv2": {},
-            "memory.top_10_mobile": {
-                "end": 6
-            }
+            "octane": {},
+            "dummy_benchmark.noisy_benchmark_1": {},
+            "blink_perf.svg": {},
+            "system_health.webview_startup": {},
+            "speedometer2-future": {},
+            "jetstream": {},
+            "smoothness.tough_pinch_zoom_cases": {},
+            "power.idle_platform": {}
         }
     },
     "2": {
         "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 6
-            },
-            "octane": {},
-            "oortonline_tbmv2": {},
-            "power.desktop": {},
-            "power.idle_platform": {},
             "power.typical_10_mobile": {},
-            "rasterize_and_record_micro.partial_invalidation": {},
-            "rasterize_and_record_micro.top_25": {},
-            "rendering.desktop": {},
-            "rendering.mobile": {
-                "end": 185
+            "v8.runtime_stats.top_25": {},
+            "loading.mobile": {
+                "end": 53
             }
         }
     },
     "3": {
         "benchmarks": {
-            "rendering.mobile": {
-                "begin": 185
+            "loading.mobile": {
+                "begin": 53
             },
-            "scheduler.tough_scheduling_cases": {},
-            "smoothness.desktop_tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.polymer": {},
-            "smoothness.gpu_rasterization.top_25_smooth": {},
-            "smoothness.gpu_rasterization.tough_filters_cases": {},
-            "smoothness.gpu_rasterization.tough_path_rendering_cases": {},
-            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
-            "smoothness.gpu_rasterization.tough_scrolling_cases": {},
-            "smoothness.gpu_rasterization_and_decoding.image_decoding_cases": {},
-            "smoothness.image_decoding_cases": {},
-            "smoothness.key_desktop_move_cases": {},
-            "smoothness.key_mobile_sites_smooth": {},
-            "smoothness.key_silk_cases": {
-                "end": 14
-            }
+            "speedometer2": {},
+            "v8.browsing_desktop-future": {},
+            "webrtc": {},
+            "blink_perf.shadow_dom": {},
+            "blink_perf.events": {},
+            "blink_perf.layout": {},
+            "memory.long_running_idle_gmail_background_tbmv2": {},
+            "tab_switching.typical_25": {},
+            "blink_perf.dom": {},
+            "media.mobile": {}
         }
     },
     "4": {
         "benchmarks": {
-            "smoothness.key_silk_cases": {
-                "begin": 14
-            },
-            "smoothness.maps": {},
-            "smoothness.pathological_mobile_sites": {},
-            "smoothness.simple_mobile_sites": {},
-            "smoothness.sync_scroll.key_mobile_sites_smooth": {},
-            "smoothness.top_25_smooth": {},
-            "smoothness.tough_ad_cases": {},
-            "smoothness.tough_animation_cases": {},
-            "smoothness.tough_canvas_cases": {},
-            "smoothness.tough_filters_cases": {},
-            "smoothness.tough_image_decode_cases": {},
-            "smoothness.tough_path_rendering_cases": {},
-            "smoothness.tough_pinch_zoom_cases": {},
-            "smoothness.tough_scrolling_cases": {},
-            "smoothness.tough_texture_upload_cases": {},
-            "smoothness.tough_webgl_ad_cases": {},
-            "smoothness.tough_webgl_cases": {},
-            "speedometer": {},
-            "speedometer-future": {},
-            "speedometer2": {},
-            "speedometer2-future": {},
             "start_with_url.cold.startup_pages": {},
-            "start_with_url.warm.startup_pages": {},
+            "blink_perf.bindings": {},
+            "system_health.memory_desktop": {},
+            "media.desktop": {},
+            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
+            "rasterize_and_record_micro.partial_invalidation": {},
+            "v8.browsing_desktop": {},
+            "blink_perf.parser": {},
+            "memory.top_10_mobile": {},
+            "blink_perf.canvas": {},
+            "loading.desktop": {},
+            "dromaeo": {},
+            "kraken": {},
+            "oortonline_tbmv2": {},
             "system_health.common_desktop": {},
-            "system_health.common_mobile": {
-                "end": 33
+            "rasterize_and_record_micro.top_25": {
+                "end": 22
             }
         }
     },
     "5": {
         "benchmarks": {
-            "system_health.common_mobile": {
-                "begin": 33
+            "rasterize_and_record_micro.top_25": {
+                "begin": 22
             },
-            "system_health.memory_desktop": {},
+            "dummy_benchmark.stable_benchmark_1": {},
             "system_health.memory_mobile": {
-                "end": 59
+                "end": 48
             }
         }
     },
     "6": {
         "benchmarks": {
             "system_health.memory_mobile": {
-                "begin": 59
+                "begin": 48
             },
-            "system_health.webview_startup": {},
-            "tab_switching.typical_25": {},
-            "thread_times.key_hit_test_cases": {},
-            "thread_times.key_idle_power_cases": {},
-            "thread_times.key_mobile_sites_smooth": {},
-            "thread_times.key_noop_cases": {},
-            "thread_times.key_silk_cases": {},
-            "thread_times.simple_mobile_sites": {},
-            "thread_times.tough_compositor_cases": {},
-            "thread_times.tough_scrolling_cases": {},
-            "tracing.tracing_with_background_memory_infra": {},
-            "v8.browsing_desktop": {},
-            "v8.browsing_desktop-future": {},
+            "rendering.desktop": {},
+            "blink_perf.css": {},
             "v8.browsing_mobile": {},
-            "v8.browsing_mobile-future": {},
-            "v8.runtime_stats.top_25": {},
-            "wasm": {},
-            "webrtc": {}
+            "blink_perf.paint": {},
+            "tracing.tracing_with_background_memory_infra": {}
         }
+    },
+    "extra_infos": {
+        "num_stories": 1831,
+        "predicted_min_shard_time": 26525.673782491664,
+        "predicted_min_shard_index": 2,
+        "predicted_max_shard_time": 26868.289459214655,
+        "predicted_max_shard_index": 6
     }
 }
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/pixel2_webview_7_shard_map.json b/tools/perf/core/shard_maps/pixel2_webview_7_shard_map.json
index be05bc0..1c5b9342 100644
--- a/tools/perf/core/shard_maps/pixel2_webview_7_shard_map.json
+++ b/tools/perf/core/shard_maps/pixel2_webview_7_shard_map.json
@@ -1,6 +1,64 @@
 {
     "0": {
-        "benchmarks": {}
+        "benchmarks": {
+            "system_health.common_mobile": {},
+            "v8.browsing_mobile-future": {},
+            "rendering.mobile": {},
+            "blink_perf.image_decoder": {},
+            "power.desktop": {},
+            "speedometer-future": {},
+            "blink_perf.owp_storage": {},
+            "memory.desktop": {},
+            "start_with_url.warm.startup_pages": {},
+            "wasm": {},
+            "dummy_benchmark.histogram_benchmark_1": {},
+            "speedometer": {},
+            "memory.long_running_idle_gmail_tbmv2": {},
+            "octane": {},
+            "dummy_benchmark.noisy_benchmark_1": {},
+            "blink_perf.svg": {},
+            "system_health.webview_startup": {},
+            "speedometer2-future": {},
+            "jetstream": {},
+            "smoothness.tough_pinch_zoom_cases": {},
+            "power.idle_platform": {},
+            "power.typical_10_mobile": {},
+            "v8.runtime_stats.top_25": {},
+            "loading.mobile": {},
+            "speedometer2": {},
+            "v8.browsing_desktop-future": {},
+            "webrtc": {},
+            "blink_perf.shadow_dom": {},
+            "blink_perf.events": {},
+            "blink_perf.layout": {},
+            "memory.long_running_idle_gmail_background_tbmv2": {},
+            "tab_switching.typical_25": {},
+            "blink_perf.dom": {},
+            "media.mobile": {},
+            "start_with_url.cold.startup_pages": {},
+            "blink_perf.bindings": {},
+            "system_health.memory_desktop": {},
+            "media.desktop": {},
+            "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {},
+            "rasterize_and_record_micro.partial_invalidation": {},
+            "v8.browsing_desktop": {},
+            "blink_perf.parser": {},
+            "memory.top_10_mobile": {},
+            "blink_perf.canvas": {},
+            "loading.desktop": {},
+            "dromaeo": {},
+            "kraken": {},
+            "oortonline_tbmv2": {},
+            "system_health.common_desktop": {},
+            "rasterize_and_record_micro.top_25": {},
+            "dummy_benchmark.stable_benchmark_1": {},
+            "system_health.memory_mobile": {},
+            "rendering.desktop": {},
+            "blink_perf.css": {},
+            "v8.browsing_mobile": {},
+            "blink_perf.paint": {},
+            "tracing.tracing_with_background_memory_infra": {}
+        }
     },
     "1": {
         "benchmarks": {}
@@ -19,5 +77,12 @@
     },
     "6": {
         "benchmarks": {}
+    },
+    "extra_infos": {
+        "num_stories": 1831,
+        "predicted_min_shard_time": 0,
+        "predicted_min_shard_index": 0,
+        "predicted_max_shard_time": 0,
+        "predicted_max_shard_index": null
     }
 }
\ No newline at end of file
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 4978e31..c2e2f82 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -298,10 +298,14 @@
 crbug.com/842731 [ Android_One ] system_health.memory_mobile/background:news:nytimes [ Skip ]
 crbug.com/843547 [ Android_Go ] system_health.memory_mobile/background:news:nytimes [ Skip ]
 crbug.com/852888 [ Nexus_5X ] system_health.memory_mobile/background:news:nytimes [ Skip ]
+crbug.com/859500 [ Nexus_5X ] system_health.memory_mobile/browse:social:tumblr_infinite_scroll [ Skip ]
 
 # Benchmark: tab_switching.typical_25
 crbug.com/747026 [ Mac ] tab_switching.typical_25/multitab:misc:typical24 [ Skip ]
 
+# Benchmark: media.desktop
+crbug.com/859660 [ All ] media.desktop/video.html?src=tulip2.vp9.webm_Regular-3G [ Skip ]
+
 # Benchmark: v8.browsing_desktop
 crbug.com/773084 [ Mac ] v8.browsing_desktop/browse:tools:maps [ Skip ]
 crbug.com/788796 [ Linux ] v8.browsing_desktop/browse:media:imgur [ Skip ]
diff --git a/ui/accelerated_widget_mac/accelerated_widget_mac.h b/ui/accelerated_widget_mac/accelerated_widget_mac.h
index 468234d..44b1dfc 100644
--- a/ui/accelerated_widget_mac/accelerated_widget_mac.h
+++ b/ui/accelerated_widget_mac/accelerated_widget_mac.h
@@ -19,11 +19,6 @@
 // throughout its lifetime (one at a time, though).
 class AcceleratedWidgetMacNSView {
  public:
-  // The CALayer tree provided by the CALayerParams sent to the
-  // AcceleratedWidgetMac will be installed under the -[NSView layer] of this
-  // NSView.
-  virtual NSView* AcceleratedWidgetGetNSView() const = 0;
-
   // Called when the AcceleratedWidgetMac's CALayerFrameSink interface's
   // UpdateCALayerTree method is called. This is used to update background
   // colors and to suppressing drawing of blank windows until content is
@@ -57,11 +52,6 @@
   // a call is made with |suspended| as false.
   void SetSuspended(bool suspended);
 
-  // Translate from a gfx::AcceleratedWidget to the NSView in which it will
-  // appear. This may return nil if |widget| is invalid or is not currently
-  // attached to an NSView.
-  static NSView* GetNSView(gfx::AcceleratedWidget widget);
-
  private:
   // For CALayerFrameSink::FromAcceleratedWidget to access Get.
   friend class CALayerFrameSink;
diff --git a/ui/accelerated_widget_mac/accelerated_widget_mac.mm b/ui/accelerated_widget_mac/accelerated_widget_mac.mm
index a58c695..7bd2567 100644
--- a/ui/accelerated_widget_mac/accelerated_widget_mac.mm
+++ b/ui/accelerated_widget_mac/accelerated_widget_mac.mm
@@ -73,14 +73,6 @@
   return found->second;
 }
 
-// static
-NSView* AcceleratedWidgetMac::GetNSView(gfx::AcceleratedWidget widget) {
-  AcceleratedWidgetMac* widget_mac = Get(widget);
-  if (!widget_mac || !widget_mac->view_)
-    return nil;
-  return widget_mac->view_->AcceleratedWidgetGetNSView();
-}
-
 void AcceleratedWidgetMac::SetSuspended(bool is_suspended) {
   is_suspended_ = is_suspended;
 }
diff --git a/ui/accessibility/ax_action_data.h b/ui/accessibility/ax_action_data.h
index 2040b90..bc3fc27 100644
--- a/ui/accessibility/ax_action_data.h
+++ b/ui/accessibility/ax_action_data.h
@@ -5,7 +5,6 @@
 #ifndef UI_ACCESSIBILITY_AX_ACTION_DATA_H_
 #define UI_ACCESSIBILITY_AX_ACTION_DATA_H_
 
-#include "base/strings/string16.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_export.h"
 #include "ui/gfx/geometry/rect.h"
@@ -63,8 +62,8 @@
   // The target point for the action.
   gfx::Point target_point;
 
-  // The new value for a node, for the SET_VALUE action.
-  base::string16 value;
+  // The new value for a node, for the SET_VALUE action. UTF-8 encoded.
+  std::string value;
 
   // The event to fire in response to a HIT_TEST action.
   ax::mojom::Event hit_test_event_to_fire = ax::mojom::Event::kNone;
diff --git a/ui/accessibility/mojom/ax_action_data.mojom b/ui/accessibility/mojom/ax_action_data.mojom
index 35557cb..69ca868 100644
--- a/ui/accessibility/mojom/ax_action_data.mojom
+++ b/ui/accessibility/mojom/ax_action_data.mojom
@@ -4,7 +4,6 @@
 
 module ax.mojom;
 
-import "mojo/public/mojom/base/string16.mojom";
 import "ui/accessibility/ax_enums.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
@@ -24,6 +23,6 @@
   int32 custom_action_id;
   gfx.mojom.Rect target_rect;
   gfx.mojom.Point target_point;
-  mojo_base.mojom.String16 value;
+  string value;
   Event hit_test_event_to_fire;
 };
diff --git a/ui/accessibility/mojom/ax_action_data_mojom_traits.h b/ui/accessibility/mojom/ax_action_data_mojom_traits.h
index 65fd6ab..39782b5 100644
--- a/ui/accessibility/mojom/ax_action_data_mojom_traits.h
+++ b/ui/accessibility/mojom/ax_action_data_mojom_traits.h
@@ -5,7 +5,6 @@
 #ifndef UI_ACCESSIBILITY_MOJOM_AX_ACTION_DATA_MOJOM_TRAITS_H_
 #define UI_ACCESSIBILITY_MOJOM_AX_ACTION_DATA_MOJOM_TRAITS_H_
 
-#include "mojo/public/cpp/base/string16_mojom_traits.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/mojom/ax_action_data.mojom-shared.h"
 #include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
@@ -49,7 +48,7 @@
   static gfx::Point target_point(const ui::AXActionData& a) {
     return a.target_point;
   }
-  static base::string16 value(const ui::AXActionData& a) { return a.value; }
+  static std::string value(const ui::AXActionData& a) { return a.value; }
   static ax::mojom::Event hit_test_event_to_fire(const ui::AXActionData& a) {
     return a.hit_test_event_to_fire;
   }
diff --git a/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc b/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
index 2d583002..5ff45af 100644
--- a/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
+++ b/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
@@ -29,7 +29,7 @@
   input.custom_action_id = 9;
   input.target_rect = gfx::Rect(10, 11, 12, 13);
   input.target_point = gfx::Point(14, 15);
-  input.value = base::ASCIIToUTF16("value");
+  input.value = "value";
   input.hit_test_event_to_fire = ax::mojom::Event::kFocus;
 
   ui::AXActionData output;
@@ -49,6 +49,6 @@
   EXPECT_EQ(output.custom_action_id, 9);
   EXPECT_EQ(output.target_rect, gfx::Rect(10, 11, 12, 13));
   EXPECT_EQ(output.target_point, gfx::Point(14, 15));
-  EXPECT_EQ(output.value, base::ASCIIToUTF16("value"));
+  EXPECT_EQ(output.value, "value");
   EXPECT_EQ(output.hit_test_event_to_fire, ax::mojom::Event::kFocus);
 }
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm
index 714bde4..f91bb5f 100644
--- a/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -651,7 +651,7 @@
 
   // Set type-specific information as necessary for actions set above.
   if ([value isKindOfClass:[NSString class]]) {
-    data.value = base::SysNSStringToUTF16(value);
+    data.value = base::SysNSStringToUTF8(value);
   } else if (data.action == ax::mojom::Action::kSetSelection &&
              [value isKindOfClass:[NSValue class]]) {
     NSRange range = [value rangeValue];
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index c7d41dd..9d127ab 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -952,7 +952,7 @@
 
   AXActionData data;
   data.action = ax::mojom::Action::kSetValue;
-  data.value = new_value;
+  data.value = base::WideToUTF8(new_value);
   if (target->delegate_->AccessibilityPerformAction(data))
     return S_OK;
   return E_FAIL;
@@ -1496,7 +1496,7 @@
 
   AXActionData data;
   data.action = ax::mojom::Action::kSetValue;
-  data.value = base::string16(value);
+  data.value = base::WideToUTF8(value);
   if (delegate_->AccessibilityPerformAction(data))
     return S_OK;
   return E_FAIL;
@@ -1527,7 +1527,7 @@
 STDMETHODIMP AXPlatformNodeWin::SetValue(double value) {
   AXActionData data;
   data.action = ax::mojom::Action::kSetValue;
-  data.value = base::NumberToString16(value);
+  data.value = base::NumberToString(value);
   if (delegate_->AccessibilityPerformAction(data))
     return S_OK;
   return E_FAIL;
diff --git a/ui/compositor/test/test_compositor_host_mac.mm b/ui/compositor/test/test_compositor_host_mac.mm
index f643f0a..04301aa 100644
--- a/ui/compositor/test/test_compositor_host_mac.mm
+++ b/ui/compositor/test/test_compositor_host_mac.mm
@@ -83,7 +83,6 @@
   virtual ~TestAcceleratedWidgetMacNSView() { [view_ release]; }
 
   // AcceleratedWidgetMacNSView
-  NSView* AcceleratedWidgetGetNSView() const override { return view_; }
   void AcceleratedWidgetCALayerParamsUpdated() override {}
 
  private:
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index 151cacf..8766c67 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -145,7 +145,8 @@
       flags = GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
       break;
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
-      flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
+      flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING |
+              GBM_BO_USE_HW_VIDEO_DECODER;
       break;
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
diff --git a/ui/views/accessibility/ax_aura_obj_cache.cc b/ui/views/accessibility/ax_aura_obj_cache.cc
index f581490..519d09c 100644
--- a/ui/views/accessibility/ax_aura_obj_cache.cc
+++ b/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/accessibility/ax_aura_obj_cache.h"
 
-#include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_util.h"
 #include "ui/aura/client/aura_constants.h"
@@ -70,8 +69,9 @@
 
   // When an entire widget is deleted, it doesn't always send a notification
   // on each of its views, so we need to explore them recursively.
-  if (widget->GetRootView())
-    RemoveViewSubtree(widget->GetRootView());
+  auto* view = widget->GetRootView();
+  if (view)
+    RemoveViewSubtree(view);
 }
 
 void AXAuraObjCache::Remove(aura::Window* window, aura::Window* parent) {
@@ -84,28 +84,14 @@
 
 AXAuraObjWrapper* AXAuraObjCache::Get(int32_t id) {
   auto it = cache_.find(id);
-
-  if (it == cache_.end())
-    return nullptr;
-
-  return it->second.get();
-}
-
-void AXAuraObjCache::Remove(int32_t id) {
-  AXAuraObjWrapper* obj = Get(id);
-
-  if (id == -1 || !obj)
-    return;
-
-  cache_.erase(id);
+  return it != cache_.end() ? it->second.get() : nullptr;
 }
 
 void AXAuraObjCache::GetTopLevelWindows(
     std::vector<AXAuraObjWrapper*>* children) {
-  for (auto it = window_to_id_map_.begin(); it != window_to_id_map_.end();
-       ++it) {
-    if (!it->first->parent())
-      children->push_back(GetOrCreate(it->first));
+  for (const auto& it : window_to_id_map_) {
+    if (!it.first->parent())
+      children->push_back(GetOrCreate(it.first));
   }
 }
 
@@ -213,11 +199,11 @@
   if (it != aura_view_to_id_map.end())
     return Get(it->second);
 
-  AXAuraObjWrapper* wrapper = new AuraViewWrapper(aura_view);
+  auto wrapper = std::make_unique<AuraViewWrapper>(aura_view);
   int32_t id = wrapper->GetUniqueId().Get();
   aura_view_to_id_map[aura_view] = id;
-  cache_[id] = base::WrapUnique(wrapper);
-  return wrapper;
+  cache_[id] = std::move(wrapper);
+  return cache_[id].get();
 }
 
 template <typename AuraView>
@@ -228,10 +214,7 @@
     return -1;
 
   auto it = aura_view_to_id_map.find(aura_view);
-  if (it != aura_view_to_id_map.end())
-    return it->second;
-
-  return -1;
+  return it != aura_view_to_id_map.end() ? it->second : -1;
 }
 
 template <typename AuraView>
@@ -242,7 +225,7 @@
   if (id == -1)
     return;
   aura_view_to_id_map.erase(aura_view);
-  Remove(id);
+  cache_.erase(id);
 }
 
 }  // namespace views
diff --git a/ui/views/accessibility/ax_aura_obj_cache.h b/ui/views/accessibility/ax_aura_obj_cache.h
index ee01b96..f798bdb 100644
--- a/ui/views/accessibility/ax_aura_obj_cache.h
+++ b/ui/views/accessibility/ax_aura_obj_cache.h
@@ -69,9 +69,6 @@
   // Lookup a cached entry based on an id.
   AXAuraObjWrapper* Get(int32_t id);
 
-  // Remove a cached entry based on an id.
-  void Remove(int32_t id);
-
   // Get all top level windows this cache knows about.
   void GetTopLevelWindows(std::vector<AXAuraObjWrapper*>* children);
 
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.cc b/ui/views/accessibility/ax_view_obj_wrapper.cc
index 2645da5..f9b4ab6 100644
--- a/ui/views/accessibility/ax_view_obj_wrapper.cc
+++ b/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -4,10 +4,8 @@
 
 #include "ui/views/accessibility/ax_view_obj_wrapper.h"
 
-#include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_node_data.h"
-#include "ui/events/event_utils.h"
 #include "ui/views/accessibility/ax_aura_obj_cache.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/view.h"
@@ -30,7 +28,7 @@
   if (view_->GetWidget())
     return cache->GetOrCreate(view_->GetWidget());
 
-  return NULL;
+  return nullptr;
 }
 
 void AXViewObjWrapper::GetChildren(
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.h b/ui/views/accessibility/ax_view_obj_wrapper.h
index c14058a..2de3a6d 100644
--- a/ui/views/accessibility/ax_view_obj_wrapper.h
+++ b/ui/views/accessibility/ax_view_obj_wrapper.h
@@ -29,7 +29,7 @@
   bool HandleAccessibleAction(const ui::AXActionData& action) override;
 
  private:
-  View* view_;
+  View* const view_;
 
   DISALLOW_COPY_AND_ASSIGN(AXViewObjWrapper);
 };
diff --git a/ui/views/animation/bounds_animator.cc b/ui/views/animation/bounds_animator.cc
index 52a4756..fc4e04c 100644
--- a/ui/views/animation/bounds_animator.cc
+++ b/ui/views/animation/bounds_animator.cc
@@ -25,8 +25,8 @@
 
   // Delete all the animations, but don't remove any child views. We assume the
   // view owns us and is going to be deleted anyway.
-  for (ViewToDataMap::iterator i = data_.begin(); i != data_.end(); ++i)
-    CleanupData(false, &(i->second), i->first);
+  for (auto& entry : data_)
+    CleanupData(false, &entry.second);
 }
 
 void BoundsAnimator::AnimateViewTo(View* view, const gfx::Rect& target) {
@@ -36,8 +36,8 @@
   Data existing_data;
 
   if (IsAnimating(view)) {
-    // Don't immediatly delete the animation, that might trigger a callback from
-    // the animationcontainer.
+    // Don't immediately delete the animation, that might trigger a callback
+    // from the animation container.
     existing_data = RemoveFromMaps(view);
   }
 
@@ -55,22 +55,20 @@
 
   data.animation->Show();
 
-  CleanupData(true, &existing_data, nullptr);
+  CleanupData(true, &existing_data);
 }
 
 void BoundsAnimator::SetTargetBounds(View* view, const gfx::Rect& target) {
-  if (!IsAnimating(view)) {
+  const auto i = data_.find(view);
+  if (i == data_.end())
     AnimateViewTo(view, target);
-    return;
-  }
-
-  data_[view].target_bounds = target;
+  else
+    i->second.target_bounds = target;
 }
 
-gfx::Rect BoundsAnimator::GetTargetBounds(View* view) {
-  if (!IsAnimating(view))
-    return view->bounds();
-  return data_[view].target_bounds;
+gfx::Rect BoundsAnimator::GetTargetBounds(const View* view) const {
+  const auto i = data_.find(view);
+  return (i == data_.end()) ? view->bounds() : i->second.target_bounds;
 }
 
 void BoundsAnimator::SetAnimationForView(
@@ -78,7 +76,8 @@
     std::unique_ptr<gfx::SlideAnimation> animation) {
   DCHECK(animation);
 
-  if (!IsAnimating(view))
+  const auto i = data_.find(view);
+  if (i == data_.end())
     return;
 
   // We delay deleting the animation until the end so that we don't prematurely
@@ -86,7 +85,7 @@
   std::unique_ptr<gfx::Animation> old_animation = ResetAnimationForView(view);
 
   gfx::SlideAnimation* animation_ptr = animation.get();
-  data_[view].animation = std::move(animation);
+  i->second.animation = std::move(animation);
   animation_to_view_[animation_ptr] = view;
 
   animation_ptr->set_delegate(this);
@@ -95,22 +94,23 @@
 }
 
 const gfx::SlideAnimation* BoundsAnimator::GetAnimationForView(View* view) {
-  return !IsAnimating(view) ? nullptr : data_[view].animation.get();
+  const auto i = data_.find(view);
+  return (i == data_.end()) ? nullptr : i->second.animation.get();
 }
 
 void BoundsAnimator::SetAnimationDelegate(
     View* view,
     std::unique_ptr<AnimationDelegate> delegate) {
-  DCHECK(IsAnimating(view));
+  const auto i = data_.find(view);
+  DCHECK(i != data_.end());
 
-  data_[view].delegate = std::move(delegate);
+  i->second.delegate = std::move(delegate);
 }
 
 void BoundsAnimator::StopAnimatingView(View* view) {
-  if (!IsAnimating(view))
-    return;
-
-  data_[view].animation->Stop();
+  const auto i = data_.find(view);
+  if (i != data_.end())
+    i->second.animation->Stop();
 }
 
 bool BoundsAnimator::IsAnimating(View* view) const {
@@ -158,16 +158,17 @@
 BoundsAnimator::Data::~Data() = default;
 
 BoundsAnimator::Data BoundsAnimator::RemoveFromMaps(View* view) {
-  DCHECK(data_.count(view) > 0);
-  DCHECK(animation_to_view_.count(data_[view].animation.get()) > 0);
+  const auto i = data_.find(view);
+  DCHECK(i != data_.end());
+  DCHECK(animation_to_view_.count(i->second.animation.get()) > 0);
 
-  Data old_data = std::move(data_[view]);
+  Data old_data = std::move(i->second);
   data_.erase(view);
   animation_to_view_.erase(old_data.animation.get());
   return old_data;
 }
 
-void BoundsAnimator::CleanupData(bool send_cancel, Data* data, View* view) {
+void BoundsAnimator::CleanupData(bool send_cancel, Data* data) {
   if (send_cancel && data->delegate)
     data->delegate->AnimationCanceled(data->animation.get());
 
@@ -181,11 +182,12 @@
 
 std::unique_ptr<gfx::Animation> BoundsAnimator::ResetAnimationForView(
     View* view) {
-  if (!IsAnimating(view))
+  const auto i = data_.find(view);
+  if (i == data_.end())
     return nullptr;
 
   std::unique_ptr<gfx::Animation> old_animation =
-      std::move(data_[view].animation);
+      std::move(i->second.animation);
   animation_to_view_.erase(old_animation.get());
   // Reset the delegate so that we don't attempt any processing when the
   // animation calls us back.
@@ -212,7 +214,7 @@
     }
   }
 
-  CleanupData(false, &data, view);
+  CleanupData(false, &data);
 }
 
 void BoundsAnimator::AnimationProgressed(const gfx::Animation* animation) {
diff --git a/ui/views/animation/bounds_animator.h b/ui/views/animation/bounds_animator.h
index 71fac2759..c0a6501f 100644
--- a/ui/views/animation/bounds_animator.h
+++ b/ui/views/animation/bounds_animator.h
@@ -56,7 +56,7 @@
 
   // Returns the target bounds for the specified view. If |view| is not
   // animating its current bounds is returned.
-  gfx::Rect GetTargetBounds(View* view);
+  gfx::Rect GetTargetBounds(const View* view) const;
 
   // Sets the animation for the specified view.
   void SetAnimationForView(View* view,
@@ -127,7 +127,7 @@
     ANIMATION_CANCELED
   };
 
-  typedef std::map<View*, Data> ViewToDataMap;
+  typedef std::map<const View*, Data> ViewToDataMap;
 
   typedef std::map<const gfx::Animation*, View*> AnimationToViewMap;
 
@@ -137,7 +137,7 @@
 
   // Does the necessary cleanup for |data|. If |send_cancel| is true and a
   // delegate has been installed on |data| AnimationCanceled is invoked on it.
-  void CleanupData(bool send_cancel, Data* data, View* view);
+  void CleanupData(bool send_cancel, Data* data);
 
   // Used when changing the animation for a view. This resets the maps for
   // the animation used by view and returns the current animation. Ownership
diff --git a/ui/views/cocoa/bridged_native_widget.h b/ui/views/cocoa/bridged_native_widget.h
index 83af13a..582dd406 100644
--- a/ui/views/cocoa/bridged_native_widget.h
+++ b/ui/views/cocoa/bridged_native_widget.h
@@ -240,8 +240,7 @@
   void InitCompositor();
   void DestroyCompositor();
 
-  // Installs the NSView for hosting the composited layer. It is later provided
-  // to |compositor_widget_| via AcceleratedWidgetGetNSView().
+  // Installs the NSView for hosting the composited layer.
   void AddCompositorSuperview();
 
   // Size the layer to match the client area bounds, taking into account display
@@ -277,7 +276,6 @@
                                   float new_device_scale_factor) override;
 
   // Overridden from ui::AcceleratedWidgetMac:
-  NSView* AcceleratedWidgetGetNSView() const override;
   void AcceleratedWidgetCALayerParamsUpdated() override;
 
   // Overridden from BridgedNativeWidgetOwner:
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index 230fd8f2..94bdab1 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -1069,10 +1069,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // BridgedNativeWidget, AcceleratedWidgetMac:
 
-NSView* BridgedNativeWidget::AcceleratedWidgetGetNSView() const {
-  return compositor_superview_;
-}
-
 void BridgedNativeWidget::AcceleratedWidgetCALayerParamsUpdated() {
   // Ignore frames arriving "late" for an old size. A frame at the new size
   // should arrive soon.
diff --git a/ui/views/cocoa/native_widget_mac_nswindow.h b/ui/views/cocoa/native_widget_mac_nswindow.h
index 0de886a..97b37b8 100644
--- a/ui/views/cocoa/native_widget_mac_nswindow.h
+++ b/ui/views/cocoa/native_widget_mac_nswindow.h
@@ -12,6 +12,24 @@
 
 @protocol WindowTouchBarDelegate;
 
+// Weak lets Chrome launch even if a future macOS doesn't have the below classes
+
+WEAK_IMPORT_ATTRIBUTE
+@interface NSNextStepFrame : NSView
+@end
+
+WEAK_IMPORT_ATTRIBUTE
+@interface NSThemeFrame : NSView
+@end
+
+VIEWS_EXPORT
+@interface NativeWidgetMacNSWindowBorderlessFrame : NSNextStepFrame
+@end
+
+VIEWS_EXPORT
+@interface NativeWidgetMacNSWindowTitledFrame : NSThemeFrame
+@end
+
 // The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
 // can only be accomplished by overriding methods.
 VIEWS_EXPORT
diff --git a/ui/views/cocoa/native_widget_mac_nswindow.mm b/ui/views/cocoa/native_widget_mac_nswindow.mm
index 145bbbe0..bd4f06b2 100644
--- a/ui/views/cocoa/native_widget_mac_nswindow.mm
+++ b/ui/views/cocoa/native_widget_mac_nswindow.mm
@@ -15,7 +15,12 @@
 #include "ui/views/widget/widget_delegate.h"
 
 @interface NSWindow (Private)
++ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle;
 - (BOOL)hasKeyAppearance;
+
+// Available in later point releases of 10.10. On 10.11+, use the public
+// -performWindowDragWithEvent: instead.
+- (void)beginWindowDragWithEvent:(NSEvent*)event;
 @end
 
 @interface NativeWidgetMacNSWindow ()
@@ -29,6 +34,38 @@
 - (BOOL)_isTitleHidden;
 @end
 
+// Use this category to implement mouseDown: on multiple frame view classes
+// with different superclasses.
+@interface NSView (CRFrameViewAdditions)
+- (void)cr_mouseDownOnFrameView:(NSEvent*)event;
+@end
+
+@implementation NSView (CRFrameViewAdditions)
+// If a mouseDown: falls through to the frame view, turn it into a window drag.
+- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
+  if (@available(macOS 10.11, *))
+    return [self.window performWindowDragWithEvent:event];
+  else if ([self.window
+               respondsToSelector:@selector(beginWindowDragWithEvent:)])
+    return [self.window beginWindowDragWithEvent:event];
+  else
+    NOTREACHED();
+  [super mouseDown:event];
+}
+@end
+
+@implementation NativeWidgetMacNSWindowTitledFrame
+- (void)mouseDown:(NSEvent*)event {
+  [self cr_mouseDownOnFrameView:event];
+}
+@end
+
+@implementation NativeWidgetMacNSWindowBorderlessFrame
+- (void)mouseDown:(NSEvent*)event {
+  [self cr_mouseDownOnFrameView:event];
+}
+@end
+
 @implementation NativeWidgetMacNSWindow {
  @private
   base::scoped_nsobject<CommandDispatcher> commandDispatcher_;
@@ -99,6 +136,17 @@
 
 // NSWindow overrides.
 
++ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
+  if (windowStyle & NSWindowStyleMaskTitled) {
+    if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
+      return customFrame;
+  } else if (Class customFrame =
+                 [NativeWidgetMacNSWindowBorderlessFrame class]) {
+    return customFrame;
+  }
+  return [super frameViewClassForStyleMask:windowStyle];
+}
+
 - (BOOL)_isTitleHidden {
   if (![self delegate])
     return NO;
@@ -106,6 +154,13 @@
   return ![self viewsWidget]->widget_delegate()->ShouldShowWindowTitle();
 }
 
+// The base implementation returns YES if the window's frame view is a custom
+// class, which causes undesirable changes in behavior. AppKit NSWindow
+// subclasses are known to override it and return NO.
+- (BOOL)_usesCustomDrawing {
+  return NO;
+}
+
 // Ignore [super canBecome{Key,Main}Window]. The default is NO for windows with
 // NSBorderlessWindowMask, which is not the desired behavior.
 // Note these can be called via -[NSWindow close] while the widget is being torn
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 1d22a51..8c3d787e 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1035,11 +1035,11 @@
     return View::HandleAccessibleAction(action_data);
 
   if (action_data.action == ax::mojom::Action::kSetValue) {
-    SetText(action_data.value);
+    SetText(base::UTF8ToUTF16(action_data.value));
     ClearSelection();
     return true;
   } else if (action_data.action == ax::mojom::Action::kReplaceSelectedText) {
-    InsertOrReplaceText(action_data.value);
+    InsertOrReplaceText(base::UTF8ToUTF16(action_data.value));
     ClearSelection();
     return true;
   }
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
index a103010..0fb698c7f 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
@@ -1,4 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="network_shared_css.html">
 
@@ -6,7 +8,7 @@
   <template>
     <style include="network-shared md-select">
       .md-select {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         width: 100%;
       }
 
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
index 7c20b90..636bcc8 100644
--- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
+++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -5,7 +5,6 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
 
 <dom-module id="cr-dialog">
   <template>
@@ -61,7 +60,7 @@
       :host ::slotted([slot=body]) {
         -webkit-padding-end: 20px;
         -webkit-padding-start: 20px;
-        color: var(--secondary-text-color);
+        color: var(--cr-secondary-text-color);
         padding-bottom: 0;
         padding-top: 0;
         @apply --cr-dialog-body;
@@ -78,7 +77,7 @@
       :host ::slotted([slot=title]) {
         -webkit-padding-end: 20px;
         -webkit-padding-start: 20px;
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         flex: 1;
         font-size: calc(15 / 13 * 100%);
         line-height: 1;
@@ -108,7 +107,7 @@
       :host ::slotted([slot=footer]) {
         border-bottom-left-radius: inherit;
         border-bottom-right-radius: inherit;
-        border-top: 1px solid var(--divider-color);
+        border-top: 1px solid #dbdbdb;
         margin: 0;
         padding: 16px 20px;
       }
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.js b/ui/webui/resources/cr_elements/cr_input/cr_input.js
index bfd6110..7f4d8b3 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.js
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.js
@@ -59,6 +59,17 @@
       value: '',
     },
 
+    /**
+     * This is strictly used internally for styling, do not attempt to use
+     * this to set focus.
+     * @private
+     */
+    focused_: {
+      type: Boolean,
+      value: false,
+      reflectToAttribute: true,
+    },
+
     incremental: Boolean,
 
     invalid: {
@@ -127,8 +138,8 @@
   },
 
   listeners: {
-    'input.focus': 'onInputFocusChange_',
-    'input.blur': 'onInputFocusChange_',
+    'input.focus': 'onInputFocus_',
+    'input.blur': 'onInputBlur_',
     'input.change': 'onInputChange_',
     'input.keydown': 'onInputKeydown_',
     'focus': 'focusInput_',
@@ -159,7 +170,7 @@
   disabledChanged_: function(current, previous) {
     this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
     // In case input was focused when disabled changes.
-    this.removeAttribute('focused_');
+    this.focused_ = false;
 
     // Don't change tabindex until after finished attaching, since this.tabindex
     // might not be intialized yet.
@@ -270,13 +281,14 @@
     this.fire('change', {sourceEvent: e});
   },
 
-  // focused_ is used instead of :focus-within, so focus on elements within the
-  // suffix slot does not trigger a change in input styles.
-  onInputFocusChange_: function() {
-    if (this.shadowRoot.activeElement == this.inputElement)
-      this.setAttribute('focused_', '');
-    else
-      this.removeAttribute('focused_');
+  /** @private */
+  onInputFocus_: function() {
+    this.focused_ = true;
+  },
+
+  /** @private */
+  onInputBlur_: function() {
+    this.focused_ = false;
   },
 
   /**
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
index 4c43b0f6..1ecfead 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
+++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -5,7 +5,6 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
 
 <dom-module id="cr-link-row">
   <template strip-whitespace="">
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html
index 28bca01..13686d7 100644
--- a/ui/webui/resources/cr_elements/shared_vars_css.html
+++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -6,8 +6,8 @@
 <custom-style>
 <style is="custom-style">
   html {
-    --primary-text-color: var(--google-grey-900);
-    --secondary-text-color: var(--google-grey-refresh-700);
+    --cr-primary-text-color: var(--google-grey-900);
+    --cr-secondary-text-color: var(--google-grey-refresh-700);
 
     --cr-actionable: {
       cursor: pointer;
@@ -37,7 +37,7 @@
 
     /* Common properties for WebUI pages. */
     --cr-page-host: {
-      color: var(--primary-text-color);
+      color: var(--cr-primary-text-color);
       line-height: 154%; /* Apply 20px default line-height to all text. */
       overflow: hidden;  /* Prevent double scroll bar bugs. */
       user-select: text;
@@ -50,12 +50,12 @@
     }
 
     --cr-primary-text: {
-        color: var(--primary-text-color);
+        color: var(--cr-primary-text-color);
         line-height: 154%;  /* 20px. */
      }
 
     --cr-secondary-text: {
-      color: var(--secondary-text-color);
+      color: var(--cr-secondary-text-color);
       font-weight: 400;
     }